]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/win32.cpp
1. derive wxGTK wxRadioBox from wxRadioBoxBase now, as in all other ports
[wxWidgets.git] / src / univ / themes / win32.cpp
CommitLineData
00e086a7 1///////////////////////////////////////////////////////////////////////////////
1e6feb95
VZ
2// Name: univ/themes/win32.cpp
3// Purpose: wxUniversal theme implementing Win32-like LNF
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 06.08.00
7// RCS-ID: $Id$
442b35b5 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
65571936 9// Licence: wxWindows licence
1e6feb95
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/timer.h"
29 #include "wx/intl.h"
30 #include "wx/dc.h"
31 #include "wx/window.h"
32
33 #include "wx/dcmemory.h"
34
35 #include "wx/button.h"
51e298bb 36 #include "wx/bmpbuttn.h"
1e6feb95
VZ
37 #include "wx/listbox.h"
38 #include "wx/checklst.h"
8cb172b4 39 #include "wx/combobox.h"
1e6feb95
VZ
40 #include "wx/scrolbar.h"
41 #include "wx/slider.h"
42 #include "wx/textctrl.h"
aeb3c1cb 43 #include "wx/listbox.h"
3216dbf5 44 #include "wx/toolbar.h"
c2919ab3 45 #include "wx/statusbr.h"
b72a54d1
MB
46
47 #ifdef __WXMSW__
48 // for COLOR_* constants
49 #include "wx/msw/private.h"
50 #endif
1e6feb95
VZ
51#endif // WX_PRECOMP
52
53#include "wx/notebook.h"
54#include "wx/spinbutt.h"
8cb172b4 55#include "wx/settings.h"
8a46f9b1 56#include "wx/menu.h"
536b70ac
VS
57#include "wx/artprov.h"
58#include "wx/toplevel.h"
00e086a7 59#include "wx/image.h"
1e6feb95
VZ
60
61#include "wx/univ/scrtimer.h"
1e6feb95
VZ
62#include "wx/univ/renderer.h"
63#include "wx/univ/inphand.h"
64#include "wx/univ/colschem.h"
65#include "wx/univ/theme.h"
66
67// ----------------------------------------------------------------------------
68// constants
69// ----------------------------------------------------------------------------
70
71static const int BORDER_THICKNESS = 2;
72
73// the offset between the label and focus rect around it
74static const int FOCUS_RECT_OFFSET_X = 1;
75static const int FOCUS_RECT_OFFSET_Y = 1;
76
24a23c35
VS
77static const int FRAME_BORDER_THICKNESS = 3;
78static const int RESIZEABLE_FRAME_BORDER_THICKNESS = 4;
79static const int FRAME_TITLEBAR_HEIGHT = 18;
80static const int FRAME_BUTTON_WIDTH = 16;
81static const int FRAME_BUTTON_HEIGHT = 14;
82
71e03035
VZ
83static const size_t NUM_STATUSBAR_GRIP_BANDS = 3;
84static const size_t WIDTH_STATUSBAR_GRIP_BAND = 4;
85static const size_t STATUSBAR_GRIP_SIZE =
86 WIDTH_STATUSBAR_GRIP_BAND*NUM_STATUSBAR_GRIP_BANDS;
87
6766e5d1
JS
88static const wxCoord SLIDER_MARGIN = 6; // margin around slider
89static const wxCoord SLIDER_THUMB_LENGTH = 18;
90static const wxCoord SLIDER_TICK_LENGTH = 6;
91
1e6feb95
VZ
92enum IndicatorType
93{
94 IndicatorType_Check,
95 IndicatorType_Radio,
96 IndicatorType_Menu,
97 IndicatorType_Max
98};
99
100enum IndicatorState
101{
102 IndicatorState_Normal,
103 IndicatorState_Pressed, // this one is for check/radioboxes
104 IndicatorState_Selected = IndicatorState_Pressed, // for menus
105 IndicatorState_Disabled,
106 IndicatorState_SelectedDisabled, // only for the menus
107 IndicatorState_Max
108};
109
110enum IndicatorStatus
111{
112 IndicatorStatus_Checked,
113 IndicatorStatus_Unchecked,
415a0ff1 114 IndicatorStatus_Undeterminated,
1e6feb95
VZ
115 IndicatorStatus_Max
116};
117
1e6feb95
VZ
118// wxWin32Renderer: draw the GUI elements in Win32 style
119// ----------------------------------------------------------------------------
120
121class wxWin32Renderer : public wxRenderer
122{
123public:
124 // constants
125 enum wxArrowDirection
126 {
127 Arrow_Left,
128 Arrow_Right,
129 Arrow_Up,
130 Arrow_Down,
131 Arrow_Max
132 };
133
134 enum wxArrowStyle
135 {
136 Arrow_Normal,
137 Arrow_Disabled,
138 Arrow_Pressed,
d6922577
JS
139 Arrow_Inverted,
140 Arrow_InvertedDisabled,
1e6feb95
VZ
141 Arrow_StateMax
142 };
143
24a23c35
VS
144 enum wxFrameButtonType
145 {
146 FrameButton_Close,
147 FrameButton_Minimize,
148 FrameButton_Maximize,
149 FrameButton_Restore,
150 FrameButton_Help,
151 FrameButton_Max
152 };
153
1e6feb95
VZ
154 // ctor
155 wxWin32Renderer(const wxColourScheme *scheme);
156
157 // implement the base class pure virtuals
158 virtual void DrawBackground(wxDC& dc,
159 const wxColour& col,
160 const wxRect& rect,
193e19cf
RR
161 int flags = 0,
162 wxWindow *window = NULL);
1e6feb95
VZ
163 virtual void DrawLabel(wxDC& dc,
164 const wxString& label,
165 const wxRect& rect,
166 int flags = 0,
167 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
168 int indexAccel = -1,
169 wxRect *rectBounds = NULL);
170 virtual void DrawButtonLabel(wxDC& dc,
171 const wxString& label,
172 const wxBitmap& image,
173 const wxRect& rect,
174 int flags = 0,
175 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
176 int indexAccel = -1,
177 wxRect *rectBounds = NULL);
178 virtual void DrawBorder(wxDC& dc,
179 wxBorder border,
180 const wxRect& rect,
181 int flags = 0,
182 wxRect *rectIn = (wxRect *)NULL);
183 virtual void DrawHorizontalLine(wxDC& dc,
184 wxCoord y, wxCoord x1, wxCoord x2);
185 virtual void DrawVerticalLine(wxDC& dc,
186 wxCoord x, wxCoord y1, wxCoord y2);
187 virtual void DrawFrame(wxDC& dc,
188 const wxString& label,
189 const wxRect& rect,
190 int flags = 0,
191 int alignment = wxALIGN_LEFT,
192 int indexAccel = -1);
193 virtual void DrawTextBorder(wxDC& dc,
194 wxBorder border,
195 const wxRect& rect,
196 int flags = 0,
197 wxRect *rectIn = (wxRect *)NULL);
198 virtual void DrawButtonBorder(wxDC& dc,
199 const wxRect& rect,
200 int flags = 0,
201 wxRect *rectIn = (wxRect *)NULL);
202 virtual void DrawArrow(wxDC& dc,
203 wxDirection dir,
204 const wxRect& rect,
205 int flags = 0);
206 virtual void DrawScrollbarArrow(wxDC& dc,
207 wxDirection dir,
208 const wxRect& rect,
209 int flags = 0)
210 { DrawArrow(dc, dir, rect, flags); }
211 virtual void DrawScrollbarThumb(wxDC& dc,
212 wxOrientation orient,
213 const wxRect& rect,
214 int flags = 0);
215 virtual void DrawScrollbarShaft(wxDC& dc,
216 wxOrientation orient,
217 const wxRect& rect,
218 int flags = 0);
219 virtual void DrawScrollCorner(wxDC& dc,
220 const wxRect& rect);
221 virtual void DrawItem(wxDC& dc,
222 const wxString& label,
223 const wxRect& rect,
224 int flags = 0);
225 virtual void DrawCheckItem(wxDC& dc,
226 const wxString& label,
227 const wxBitmap& bitmap,
228 const wxRect& rect,
229 int flags = 0);
230 virtual void DrawCheckButton(wxDC& dc,
231 const wxString& label,
232 const wxBitmap& bitmap,
233 const wxRect& rect,
234 int flags = 0,
235 wxAlignment align = wxALIGN_LEFT,
236 int indexAccel = -1);
237 virtual void DrawRadioButton(wxDC& dc,
238 const wxString& label,
239 const wxBitmap& bitmap,
240 const wxRect& rect,
241 int flags = 0,
242 wxAlignment align = wxALIGN_LEFT,
243 int indexAccel = -1);
3216dbf5
VZ
244 virtual void DrawToolBarButton(wxDC& dc,
245 const wxString& label,
246 const wxBitmap& bitmap,
247 const wxRect& rect,
a8f4cabe
JS
248 int flags = 0,
249 long style = 0);
1e6feb95
VZ
250 virtual void DrawTextLine(wxDC& dc,
251 const wxString& text,
252 const wxRect& rect,
253 int selStart = -1,
254 int selEnd = -1,
255 int flags = 0);
256 virtual void DrawLineWrapMark(wxDC& dc, const wxRect& rect);
257 virtual void DrawTab(wxDC& dc,
258 const wxRect& rect,
259 wxDirection dir,
260 const wxString& label,
261 const wxBitmap& bitmap = wxNullBitmap,
262 int flags = 0,
263 int indexAccel = -1);
264
265 virtual void DrawSliderShaft(wxDC& dc,
266 const wxRect& rect,
6766e5d1 267 int lenThumb,
1e6feb95
VZ
268 wxOrientation orient,
269 int flags = 0,
6766e5d1 270 long style = 0,
1e6feb95
VZ
271 wxRect *rectShaft = NULL);
272 virtual void DrawSliderThumb(wxDC& dc,
273 const wxRect& rect,
274 wxOrientation orient,
6766e5d1
JS
275 int flags = 0,
276 long style = 0);
1e6feb95
VZ
277 virtual void DrawSliderTicks(wxDC& dc,
278 const wxRect& rect,
6766e5d1 279 int lenThumb,
1e6feb95
VZ
280 wxOrientation orient,
281 int start,
282 int end,
283 int step = 1,
6766e5d1
JS
284 int flags = 0,
285 long style = 0);
1e6feb95
VZ
286
287 virtual void DrawMenuBarItem(wxDC& dc,
288 const wxRect& rect,
289 const wxString& label,
290 int flags = 0,
291 int indexAccel = -1);
292 virtual void DrawMenuItem(wxDC& dc,
293 wxCoord y,
294 const wxMenuGeometryInfo& geometryInfo,
295 const wxString& label,
296 const wxString& accel,
297 const wxBitmap& bitmap = wxNullBitmap,
298 int flags = 0,
299 int indexAccel = -1);
300 virtual void DrawMenuSeparator(wxDC& dc,
301 wxCoord y,
302 const wxMenuGeometryInfo& geomInfo);
71e03035
VZ
303
304 virtual void DrawStatusField(wxDC& dc,
305 const wxRect& rect,
306 const wxString& label,
c2919ab3 307 int flags = 0, int style = 0);
71e03035 308
24a23c35
VS
309 // titlebars
310 virtual void DrawFrameTitleBar(wxDC& dc,
311 const wxRect& rect,
312 const wxString& title,
313 const wxIcon& icon,
314 int flags,
813edf09
VS
315 int specialButton = 0,
316 int specialButtonFlags = 0);
24a23c35
VS
317 virtual void DrawFrameBorder(wxDC& dc,
318 const wxRect& rect,
319 int flags);
320 virtual void DrawFrameBackground(wxDC& dc,
321 const wxRect& rect,
322 int flags);
323 virtual void DrawFrameTitle(wxDC& dc,
324 const wxRect& rect,
325 const wxString& title,
326 int flags);
327 virtual void DrawFrameIcon(wxDC& dc,
328 const wxRect& rect,
329 const wxIcon& icon,
330 int flags);
331 virtual void DrawFrameButton(wxDC& dc,
332 wxCoord x, wxCoord y,
333 int button,
334 int flags = 0);
335 virtual wxRect GetFrameClientArea(const wxRect& rect, int flags) const;
336 virtual wxSize GetFrameTotalSize(const wxSize& clientSize, int flags) const;
e7dda1ff 337 virtual wxSize GetFrameMinSize(int flags) const;
24a23c35 338 virtual wxSize GetFrameIconSize() const;
813edf09 339 virtual int HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const;
24a23c35 340
1e6feb95 341 virtual void GetComboBitmaps(wxBitmap *bmpNormal,
1b465102 342 wxBitmap *bmpFocus,
1e6feb95
VZ
343 wxBitmap *bmpPressed,
344 wxBitmap *bmpDisabled);
345
346 virtual void AdjustSize(wxSize *size, const wxWindow *window);
347 virtual wxRect GetBorderDimensions(wxBorder border) const;
348 virtual bool AreScrollbarsInsideBorder() const;
349
350 virtual wxSize GetScrollbarArrowSize() const
351 { return m_sizeScrollbarArrow; }
352 virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
353 wxScrollBar::Element elem,
354 int thumbPos = -1) const;
355 virtual wxCoord GetScrollbarSize(const wxScrollBar *scrollbar);
356 virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
357 const wxPoint& pt) const;
358 virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
359 int thumbPos = -1);
360 virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
361 virtual wxCoord GetListboxItemHeight(wxCoord fontHeight)
362 { return fontHeight + 2; }
363 virtual wxSize GetCheckBitmapSize() const
364 { return wxSize(13, 13); }
365 virtual wxSize GetRadioBitmapSize() const
366 { return wxSize(12, 12); }
367 virtual wxCoord GetCheckItemMargin() const
368 { return 0; }
369
3216dbf5
VZ
370 virtual wxSize GetToolBarButtonSize(wxCoord *separator) const
371 { if ( separator ) *separator = 5; return wxSize(16, 15); }
372 virtual wxSize GetToolBarMargin() const
34d26f42 373 { return wxSize(4, 4); }
3216dbf5 374
1e6feb95 375 virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
3216dbf5 376 const wxRect& rect) const;
1e6feb95
VZ
377 virtual wxRect GetTextClientArea(const wxTextCtrl *text,
378 const wxRect& rect,
3216dbf5 379 wxCoord *extraSpaceBeyond) const;
1e6feb95
VZ
380
381 virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
382 virtual wxSize GetTabPadding() const { return wxSize(6, 5); }
383
6766e5d1
JS
384 virtual wxCoord GetSliderDim() const { return SLIDER_THUMB_LENGTH + 2*BORDER_THICKNESS; }
385 virtual wxCoord GetSliderTickLen() const { return SLIDER_TICK_LENGTH; }
1e6feb95 386 virtual wxRect GetSliderShaftRect(const wxRect& rect,
6766e5d1
JS
387 int lenThumb,
388 wxOrientation orient,
389 long style = 0) const;
1e6feb95 390 virtual wxSize GetSliderThumbSize(const wxRect& rect,
6766e5d1 391 int lenThumb,
1e6feb95
VZ
392 wxOrientation orient) const;
393 virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
394
395 virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const;
396 virtual wxMenuGeometryInfo *GetMenuGeometry(wxWindow *win,
397 const wxMenu& menu) const;
71e03035
VZ
398
399 virtual wxSize GetStatusBarBorders(wxCoord *borderBetweenFields) const;
400
1e6feb95
VZ
401protected:
402 // helper of DrawLabel() and DrawCheckOrRadioButton()
403 void DoDrawLabel(wxDC& dc,
404 const wxString& label,
405 const wxRect& rect,
406 int flags = 0,
407 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
408 int indexAccel = -1,
409 wxRect *rectBounds = NULL,
410 const wxPoint& focusOffset
411 = wxPoint(FOCUS_RECT_OFFSET_X, FOCUS_RECT_OFFSET_Y));
412
413 // common part of DrawLabel() and DrawItem()
414 void DrawFocusRect(wxDC& dc, const wxRect& rect);
415
416 // DrawLabel() and DrawButtonLabel() helper
417 void DrawLabelShadow(wxDC& dc,
418 const wxString& label,
419 const wxRect& rect,
420 int alignment,
421 int indexAccel);
422
423 // DrawButtonBorder() helper
424 void DoDrawBackground(wxDC& dc,
425 const wxColour& col,
193e19cf
RR
426 const wxRect& rect,
427 wxWindow *window = NULL );
1e6feb95
VZ
428
429 // DrawBorder() helpers: all of them shift and clip the DC after drawing
430 // the border
431
432 // just draw a rectangle with the given pen
433 void DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen);
434
435 // draw the lower left part of rectangle
436 void DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen);
437
438 // draw the rectange using the first brush for the left and top sides and
439 // the second one for the bottom and right ones
440 void DrawShadedRect(wxDC& dc, wxRect *rect,
441 const wxPen& pen1, const wxPen& pen2);
442
443 // draw the normal 3D border
444 void DrawRaisedBorder(wxDC& dc, wxRect *rect);
445
446 // draw the sunken 3D border
447 void DrawSunkenBorder(wxDC& dc, wxRect *rect);
448
449 // draw the border used for scrollbar arrows
a290fa5a 450 void DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed = false);
1e6feb95
VZ
451
452 // public DrawArrow()s helper
453 void DrawArrow(wxDC& dc, const wxRect& rect,
454 wxArrowDirection arrowDir, wxArrowStyle arrowStyle);
455
456 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
457 void DrawArrowButton(wxDC& dc, const wxRect& rect,
458 wxArrowDirection arrowDir,
459 wxArrowStyle arrowStyle);
460
461 // DrawCheckButton/DrawRadioButton helper
462 void DrawCheckOrRadioButton(wxDC& dc,
463 const wxString& label,
464 const wxBitmap& bitmap,
465 const wxRect& rect,
466 int flags,
467 wxAlignment align,
468 int indexAccel,
469 wxCoord focusOffsetY);
470
471 // draw a normal or transposed line (useful for using the same code fo both
472 // horizontal and vertical widgets)
473 void DrawLine(wxDC& dc,
474 wxCoord x1, wxCoord y1,
475 wxCoord x2, wxCoord y2,
a290fa5a 476 bool transpose = false)
1e6feb95
VZ
477 {
478 if ( transpose )
479 dc.DrawLine(y1, x1, y2, x2);
480 else
481 dc.DrawLine(x1, y1, x2, y2);
482 }
483
484 // get the standard check/radio button bitmap
485 wxBitmap GetIndicator(IndicatorType indType, int flags);
486 wxBitmap GetCheckBitmap(int flags)
487 { return GetIndicator(IndicatorType_Check, flags); }
488 wxBitmap GetRadioBitmap(int flags)
489 { return GetIndicator(IndicatorType_Radio, flags); }
490
491private:
492 const wxColourScheme *m_scheme;
493
494 // the sizing parameters (TODO make them changeable)
495 wxSize m_sizeScrollbarArrow;
496
497 // GDI objects we use for drawing
498 wxColour m_colDarkGrey,
499 m_colHighlight;
500
501 wxPen m_penBlack,
502 m_penDarkGrey,
503 m_penLightGrey,
504 m_penHighlight;
71e03035 505
24a23c35 506 wxFont m_titlebarFont;
71e03035 507
e3400e2e
VZ
508 // the checked and unchecked bitmaps for DrawCheckItem()
509 wxBitmap m_bmpCheckBitmaps[IndicatorStatus_Max];
510
511 // the bitmaps returned by GetIndicator()
512 wxBitmap m_bmpIndicators[IndicatorType_Max]
513 [IndicatorState_Max]
514 [IndicatorStatus_Max];
515
24a23c35
VS
516 // titlebar icons:
517 wxBitmap m_bmpFrameButtons[FrameButton_Max];
1e6feb95
VZ
518
519 // first row is for the normal state, second - for the disabled
520 wxBitmap m_bmpArrows[Arrow_StateMax][Arrow_Max];
521};
522
523// ----------------------------------------------------------------------------
524// wxWin32InputHandler and derived classes: process the keyboard and mouse
525// messages according to Windows standards
526// ----------------------------------------------------------------------------
527
528class wxWin32InputHandler : public wxInputHandler
529{
530public:
531 wxWin32InputHandler(wxWin32Renderer *renderer);
532
67e49a98 533 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
534 const wxKeyEvent& event,
535 bool pressed);
67e49a98 536 virtual bool HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
537 const wxMouseEvent& event);
538
539protected:
540 wxWin32Renderer *m_renderer;
541};
542
543class wxWin32ScrollBarInputHandler : public wxStdScrollBarInputHandler
544{
545public:
546 wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
547 wxInputHandler *handler);
548
67e49a98
VS
549 virtual bool HandleMouse(wxInputConsumer *control, const wxMouseEvent& event);
550 virtual bool HandleMouseMove(wxInputConsumer *control, const wxMouseEvent& event);
1e6feb95
VZ
551
552 virtual bool OnScrollTimer(wxScrollBar *scrollbar,
553 const wxControlAction& action);
554
555protected:
556 virtual bool IsAllowedButton(int button) { return button == 1; }
557
61fef19b
VZ
558 virtual void Highlight(wxScrollBar * WXUNUSED(scrollbar),
559 bool WXUNUSED(doIt))
1e6feb95
VZ
560 {
561 // we don't highlight anything
562 }
563
564 // the first and last event which caused the thumb to move
565 wxMouseEvent m_eventStartDrag,
566 m_eventLastDrag;
567
568 // have we paused the scrolling because the mouse moved?
569 bool m_scrollPaused;
570
571 // we remember the interval of the timer to be able to restart it
572 int m_interval;
573};
574
575class wxWin32CheckboxInputHandler : public wxStdCheckboxInputHandler
576{
577public:
578 wxWin32CheckboxInputHandler(wxInputHandler *handler)
579 : wxStdCheckboxInputHandler(handler) { }
580
67e49a98 581 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
582 const wxKeyEvent& event,
583 bool pressed);
584};
585
586class wxWin32TextCtrlInputHandler : public wxStdTextCtrlInputHandler
587{
588public:
589 wxWin32TextCtrlInputHandler(wxInputHandler *handler)
590 : wxStdTextCtrlInputHandler(handler) { }
591
67e49a98 592 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
593 const wxKeyEvent& event,
594 bool pressed);
595};
596
71e03035
VZ
597class wxWin32StatusBarInputHandler : public wxStdInputHandler
598{
599public:
600 wxWin32StatusBarInputHandler(wxInputHandler *handler);
601
602 virtual bool HandleMouse(wxInputConsumer *consumer,
603 const wxMouseEvent& event);
604
605 virtual bool HandleMouseMove(wxInputConsumer *consumer,
606 const wxMouseEvent& event);
607
608protected:
609 // is the given point over the statusbar grip?
610 bool IsOnGrip(wxWindow *statbar, const wxPoint& pt) const;
611
612private:
613 // the cursor we had replaced with the resize one
614 wxCursor m_cursorOld;
615
616 // was the mouse over the grip last time we checked?
617 bool m_isOnGrip;
618};
619
8f71aafa
VS
620class wxWin32SystemMenuEvtHandler;
621
768f0c5a
VS
622class wxWin32FrameInputHandler : public wxStdFrameInputHandler
623{
624public:
2279b45a
VS
625 wxWin32FrameInputHandler(wxInputHandler *handler);
626 ~wxWin32FrameInputHandler();
768f0c5a
VS
627
628 virtual bool HandleMouse(wxInputConsumer *control,
629 const wxMouseEvent& event);
8f71aafa
VS
630
631 virtual bool HandleActivation(wxInputConsumer *consumer, bool activated);
00e086a7 632
8f71aafa
VS
633 void PopupSystemMenu(wxTopLevelWindow *window, const wxPoint& pos) const;
634
635private:
636 // was the mouse over the grip last time we checked?
637 wxWin32SystemMenuEvtHandler *m_menuHandler;
768f0c5a
VS
638};
639
1e6feb95
VZ
640// ----------------------------------------------------------------------------
641// wxWin32ColourScheme: uses (default) Win32 colours
642// ----------------------------------------------------------------------------
643
644class wxWin32ColourScheme : public wxColourScheme
645{
646public:
647 virtual wxColour Get(StdColour col) const;
648 virtual wxColour GetBackground(wxWindow *win) const;
649};
650
536b70ac
VS
651// ----------------------------------------------------------------------------
652// wxWin32ArtProvider
653// ----------------------------------------------------------------------------
654
655class wxWin32ArtProvider : public wxArtProvider
656{
657protected:
658 virtual wxBitmap CreateBitmap(const wxArtID& id,
659 const wxArtClient& client,
660 const wxSize& size);
661};
662
1e6feb95
VZ
663// ----------------------------------------------------------------------------
664// wxWin32Theme
665// ----------------------------------------------------------------------------
666
d5d29b8a 667WX_DEFINE_ARRAY_PTR(wxInputHandler *, wxArrayHandlers);
1e6feb95
VZ
668
669class wxWin32Theme : public wxTheme
670{
671public:
672 wxWin32Theme();
673 virtual ~wxWin32Theme();
674
240889a1 675 virtual wxRenderer *GetRenderer();
536b70ac 676 virtual wxArtProvider *GetArtProvider();
1e6feb95
VZ
677 virtual wxInputHandler *GetInputHandler(const wxString& control);
678 virtual wxColourScheme *GetColourScheme();
679
680private:
681 // get the default input handler
682 wxInputHandler *GetDefaultInputHandler();
683
684 wxWin32Renderer *m_renderer;
00e086a7 685
536b70ac 686 wxWin32ArtProvider *m_artProvider;
1e6feb95
VZ
687
688 // the names of the already created handlers and the handlers themselves
689 // (these arrays are synchronized)
690 wxSortedArrayString m_handlerNames;
691 wxArrayHandlers m_handlers;
692
693 wxWin32InputHandler *m_handlerDefault;
694
695 wxWin32ColourScheme *m_scheme;
696
697 WX_DECLARE_THEME(win32)
698};
699
700// ----------------------------------------------------------------------------
701// standard bitmaps
702// ----------------------------------------------------------------------------
703
24a23c35
VS
704// frame buttons bitmaps
705
706static const char *frame_button_close_xpm[] = {
707"12 10 2 1",
cc4bc3a0
VZ
708" c None",
709". c black",
24a23c35
VS
710" ",
711" .. .. ",
712" .. .. ",
713" .... ",
714" .. ",
715" .... ",
716" .. .. ",
717" .. .. ",
718" ",
719" "};
720
721static const char *frame_button_help_xpm[] = {
722"12 10 2 1",
cc4bc3a0
VZ
723" c None",
724". c #000000",
24a23c35
VS
725" .... ",
726" .. .. ",
727" .. .. ",
728" .. ",
729" .. ",
730" .. ",
731" ",
732" .. ",
733" .. ",
734" "};
735
736static const char *frame_button_maximize_xpm[] = {
737"12 10 2 1",
cc4bc3a0
VZ
738" c None",
739". c #000000",
24a23c35
VS
740" ......... ",
741" ......... ",
742" . . ",
743" . . ",
744" . . ",
745" . . ",
746" . . ",
747" . . ",
748" ......... ",
749" "};
750
751static const char *frame_button_minimize_xpm[] = {
752"12 10 2 1",
cc4bc3a0
VZ
753" c None",
754". c #000000",
24a23c35
VS
755" ",
756" ",
757" ",
758" ",
759" ",
760" ",
761" ",
762" ...... ",
763" ...... ",
764" "};
765
766static const char *frame_button_restore_xpm[] = {
767"12 10 2 1",
cc4bc3a0
VZ
768" c None",
769". c #000000",
24a23c35
VS
770" ...... ",
771" ...... ",
772" . . ",
773" ...... . ",
774" ...... . ",
775" . ... ",
776" . . ",
777" . . ",
778" ...... ",
779" "};
780
1e6feb95
VZ
781// menu bitmaps
782
783static const char *checked_menu_xpm[] = {
784/* columns rows colors chars-per-pixel */
785"9 9 2 1",
786"w c None",
787"b c black",
788/* pixels */
789"wwwwwwwww",
790"wwwwwwwbw",
791"wwwwwwbbw",
792"wbwwwbbbw",
793"wbbwbbbww",
794"wbbbbbwww",
795"wwbbbwwww",
796"wwwbwwwww",
797"wwwwwwwww"
798};
799
800static const char *selected_checked_menu_xpm[] = {
801/* columns rows colors chars-per-pixel */
802"9 9 2 1",
803"w c None",
804"b c white",
805/* pixels */
806"wwwwwwwww",
807"wwwwwwwbw",
808"wwwwwwbbw",
809"wbwwwbbbw",
810"wbbwbbbww",
811"wbbbbbwww",
812"wwbbbwwww",
813"wwwbwwwww",
814"wwwwwwwww"
815};
816
817static const char *disabled_checked_menu_xpm[] = {
818/* columns rows colors chars-per-pixel */
819"9 9 3 1",
820"w c None",
821"b c #7f7f7f",
822"W c #e0e0e0",
823/* pixels */
824"wwwwwwwww",
825"wwwwwwwbw",
826"wwwwwwbbW",
827"wbwwwbbbW",
828"wbbwbbbWW",
829"wbbbbbWWw",
830"wwbbbWWww",
831"wwwbWWwww",
832"wwwwWwwww"
833};
834
835static const char *selected_disabled_checked_menu_xpm[] = {
836/* columns rows colors chars-per-pixel */
837"9 9 2 1",
838"w c None",
839"b c #7f7f7f",
840/* pixels */
841"wwwwwwwww",
842"wwwwwwwbw",
843"wwwwwwbbw",
844"wbwwwbbbw",
845"wbbwbbbww",
846"wbbbbbwww",
847"wwbbbwwww",
848"wwwbwwwww",
849"wwwwwwwww"
850};
851
852// checkbox and radiobox bitmaps below
853
854static const char *checked_xpm[] = {
855/* columns rows colors chars-per-pixel */
856"13 13 5 1",
857"w c white",
858"b c black",
859"d c #7f7f7f",
860"g c #c0c0c0",
861"h c #e0e0e0",
862/* pixels */
863"ddddddddddddh",
864"dbbbbbbbbbbgh",
865"dbwwwwwwwwwgh",
866"dbwwwwwwwbwgh",
867"dbwwwwwwbbwgh",
868"dbwbwwwbbbwgh",
869"dbwbbwbbbwwgh",
870"dbwbbbbbwwwgh",
871"dbwwbbbwwwwgh",
872"dbwwwbwwwwwgh",
873"dbwwwwwwwwwgh",
874"dgggggggggggh",
875"hhhhhhhhhhhhh"
876};
877
878static const char *pressed_checked_xpm[] = {
879/* columns rows colors chars-per-pixel */
880"13 13 4 1",
881"b c black",
882"d c #7f7f7f",
883"g c #c0c0c0",
884"h c #e0e0e0",
885/* pixels */
886"ddddddddddddh",
887"dbbbbbbbbbbgh",
888"dbggggggggggh",
889"dbgggggggbggh",
890"dbggggggbbggh",
891"dbgbgggbbbggh",
892"dbgbbgbbbgggh",
893"dbgbbbbbggggh",
894"dbggbbbgggggh",
895"dbgggbggggggh",
896"dbggggggggggh",
897"dgggggggggggh",
898"hhhhhhhhhhhhh"
899};
900
901static const char *pressed_disabled_checked_xpm[] = {
902/* columns rows colors chars-per-pixel */
903"13 13 4 1",
904"b c black",
905"d c #7f7f7f",
906"g c #c0c0c0",
907"h c #e0e0e0",
908/* pixels */
909"ddddddddddddh",
910"dbbbbbbbbbbgh",
911"dbggggggggggh",
912"dbgggggggdggh",
913"dbggggggddggh",
914"dbgdgggdddggh",
915"dbgddgdddgggh",
916"dbgdddddggggh",
917"dbggdddgggggh",
918"dbgggdggggggh",
919"dbggggggggggh",
920"dgggggggggggh",
921"hhhhhhhhhhhhh"
922};
923
924static const char *checked_item_xpm[] = {
925/* columns rows colors chars-per-pixel */
926"13 13 3 1",
927"w c white",
928"b c black",
929"d c #808080",
930/* pixels */
931"wwwwwwwwwwwww",
932"wdddddddddddw",
933"wdwwwwwwwwwdw",
934"wdwwwwwwwbwdw",
935"wdwwwwwwbbwdw",
936"wdwbwwwbbbwdw",
937"wdwbbwbbbwwdw",
938"wdwbbbbbwwwdw",
939"wdwwbbbwwwwdw",
940"wdwwwbwwwwwdw",
941"wdwwwwwwwwwdw",
942"wdddddddddddw",
943"wwwwwwwwwwwww"
944};
945
946static const char *unchecked_xpm[] = {
947/* columns rows colors chars-per-pixel */
948"13 13 5 1",
949"w c white",
950"b c black",
951"d c #7f7f7f",
952"g c #c0c0c0",
953"h c #e0e0e0",
954/* pixels */
955"ddddddddddddh",
956"dbbbbbbbbbbgh",
957"dbwwwwwwwwwgh",
958"dbwwwwwwwwwgh",
959"dbwwwwwwwwwgh",
960"dbwwwwwwwwwgh",
961"dbwwwwwwwwwgh",
962"dbwwwwwwwwwgh",
963"dbwwwwwwwwwgh",
964"dbwwwwwwwwwgh",
965"dbwwwwwwwwwgh",
966"dgggggggggggh",
967"hhhhhhhhhhhhh"
968};
969
970static const char *pressed_unchecked_xpm[] = {
971/* columns rows colors chars-per-pixel */
972"13 13 4 1",
973"b c black",
974"d c #7f7f7f",
975"g c #c0c0c0",
976"h c #e0e0e0",
977/* pixels */
978"ddddddddddddh",
979"dbbbbbbbbbbgh",
980"dbggggggggggh",
981"dbggggggggggh",
982"dbggggggggggh",
983"dbggggggggggh",
984"dbggggggggggh",
985"dbggggggggggh",
986"dbggggggggggh",
987"dbggggggggggh",
988"dbggggggggggh",
989"dbggggggggggh",
990"hhhhhhhhhhhhh"
991};
992
993static const char *unchecked_item_xpm[] = {
994/* columns rows colors chars-per-pixel */
995"13 13 2 1",
996"w c white",
997"d c #808080",
998/* pixels */
999"wwwwwwwwwwwww",
1000"wdddddddddddw",
1001"wdwwwwwwwwwdw",
1002"wdwwwwwwwwwdw",
1003"wdwwwwwwwwwdw",
1004"wdwwwwwwwwwdw",
1005"wdwwwwwwwwwdw",
1006"wdwwwwwwwwwdw",
1007"wdwwwwwwwwwdw",
1008"wdwwwwwwwwwdw",
1009"wdwwwwwwwwwdw",
1010"wdddddddddddw",
1011"wwwwwwwwwwwww"
1012};
1013
415a0ff1
WS
1014static const char *undetermined_xpm[] = {
1015/* columns rows colors chars-per-pixel */
1016"13 13 5 1",
1017"A c #030303",
1018"B c #838383",
1019"C c #C3C3C3",
1020"D c #FBFBFB",
1021"E c #DBDBDB",
1022/* pixels */
1023"BBBBBBBBBBBBD",
1024"BAAAAAAAAAAED",
1025"BACDCDCDCDCED",
1026"BADCDCDCDBDED",
1027"BACDCDCDBBCED",
1028"BADBDCEBBBDED",
1029"BACBBDBBBDCED",
1030"BADBBBBBDCDED",
1031"BACDBBBDCDCED",
1032"BADCDBDCDCDED",
1033"BACDCDCDCDCED",
1034"BEEEEEEEEEEED",
1035"DDDDDDDDDDDDD"
1036};
1037
1038static const char *pressed_undetermined_xpm[] = {
1039/* columns rows colors chars-per-pixel */
1040"13 13 5 1",
1041"A c #040404",
1042"B c #848484",
1043"C c #C4C4C4",
1044"D c #FCFCFC",
1045"E c #DCDCDC",
1046/* pixels */
1047"BBBBBBBBBBBBD",
1048"BAAAAAAAAAAED",
1049"BACCCCCCCCCCD",
1050"BACCCCCCCACED",
1051"BACCCCCCAACED",
1052"BACACCCAAACED",
1053"BACAACAAACCED",
1054"BACAAAAACCCED",
1055"BACCAAACCCCCD",
1056"BACCCACCCCCED",
1057"BACCCCCCCCCED",
1058"BEEEEEEEEEEED",
1059"DDDDDDDDDDDDD"
1060};
1061
1e6feb95
VZ
1062static const char *checked_radio_xpm[] = {
1063/* columns rows colors chars-per-pixel */
1064"12 12 6 1",
1065" c None",
1066"w c white",
1067"b c black",
1068"d c #7f7f7f",
1069"g c #c0c0c0",
1070"h c #e0e0e0",
1071/* pixels */
1072" dddd ",
1073" ddbbbbdd ",
1074" dbbwwwwbbh ",
1075" dbwwwwwwgh ",
1076"dbwwwbbwwwgh",
1077"dbwwbbbbwwgh",
1078"dbwwbbbbwwgh",
1079"dbwwwbbwwwgh",
1080" dbwwwwwwgh ",
1081" dggwwwwggh ",
1082" hhgggghh ",
1083" hhhh "
1084};
1085
1086static const char *pressed_checked_radio_xpm[] = {
1087/* columns rows colors chars-per-pixel */
1088"12 12 6 1",
1089" c None",
1090"w c white",
1091"b c black",
1092"d c #7f7f7f",
1093"g c #c0c0c0",
1094"h c #e0e0e0",
1095/* pixels */
1096" dddd ",
1097" ddbbbbdd ",
1098" dbbggggbbh ",
1099" dbgggggggh ",
1100"dbgggbbggggh",
1101"dbggbbbbgggh",
1102"dbggbbbbgggh",
1103"dbgggbbggggh",
1104" dbgggggggh ",
1105" dggggggggh ",
1106" hhgggghh ",
1107" hhhh "
1108};
1109
1110static const char *pressed_disabled_checked_radio_xpm[] = {
1111/* columns rows colors chars-per-pixel */
1112"12 12 6 1",
1113" c None",
1114"w c white",
1115"b c black",
1116"d c #7f7f7f",
1117"g c #c0c0c0",
1118"h c #e0e0e0",
1119/* pixels */
1120" dddd ",
1121" ddbbbbdd ",
1122" dbbggggbbh ",
1123" dbgggggggh ",
1124"dbgggddggggh",
1125"dbggddddgggh",
1126"dbggddddgggh",
1127"dbgggddggggh",
1128" dbgggggggh ",
1129" dggggggggh ",
1130" hhgggghh ",
1131" hhhh ",
1132};
1133
1134static const char *unchecked_radio_xpm[] = {
1135/* columns rows colors chars-per-pixel */
1136"12 12 6 1",
1137" c None",
1138"w c white",
1139"b c black",
1140"d c #7f7f7f",
1141"g c #c0c0c0",
1142"h c #e0e0e0",
1143/* pixels */
1144" dddd ",
1145" ddbbbbdd ",
1146" dbbwwwwbbh ",
1147" dbwwwwwwgh ",
1148"dbwwwwwwwwgh",
1149"dbwwwwwwwwgh",
1150"dbwwwwwwwwgh",
1151"dbwwwwwwwwgh",
1152" dbwwwwwwgh ",
1153" dggwwwwggh ",
1154" hhgggghh ",
1155" hhhh "
1156};
1157
1158static const char *pressed_unchecked_radio_xpm[] = {
1159/* columns rows colors chars-per-pixel */
1160"12 12 6 1",
1161" c None",
1162"w c white",
1163"b c black",
1164"d c #7f7f7f",
1165"g c #c0c0c0",
1166"h c #e0e0e0",
1167/* pixels */
1168" dddd ",
1169" ddbbbbdd ",
1170" dbbggggbbh ",
1171" dbgggggggh ",
1172"dbgggggggggh",
1173"dbgggggggggh",
1174"dbgggggggggh",
1175"dbgggggggggh",
1176" dbgggggggh ",
1177" dggggggggh ",
1178" hhgggghh ",
1179" hhhh "
1180};
1181
1182static const char **
e3400e2e 1183 xpmIndicators[IndicatorType_Max][IndicatorState_Max][IndicatorStatus_Max] =
1e6feb95
VZ
1184{
1185 // checkboxes first
1186 {
1187 // normal state
415a0ff1 1188 { checked_xpm, unchecked_xpm, undetermined_xpm },
1e6feb95
VZ
1189
1190 // pressed state
415a0ff1 1191 { pressed_checked_xpm, pressed_unchecked_xpm, pressed_undetermined_xpm },
1e6feb95
VZ
1192
1193 // disabled state
415a0ff1 1194 { pressed_disabled_checked_xpm, pressed_unchecked_xpm, pressed_disabled_checked_xpm },
1e6feb95
VZ
1195 },
1196
1197 // radio
1198 {
1199 // normal state
415a0ff1 1200 { checked_radio_xpm, unchecked_radio_xpm, NULL },
1e6feb95
VZ
1201
1202 // pressed state
415a0ff1 1203 { pressed_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL },
1e6feb95
VZ
1204
1205 // disabled state
415a0ff1 1206 { pressed_disabled_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL },
1e6feb95
VZ
1207 },
1208
1209 // menu
1210 {
1211 // normal state
415a0ff1 1212 { checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1213
1214 // selected state
415a0ff1 1215 { selected_checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1216
1217 // disabled state
415a0ff1 1218 { disabled_checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1219
1220 // disabled selected state
415a0ff1 1221 { selected_disabled_checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1222 }
1223};
1224
e3400e2e
VZ
1225static const char **xpmChecked[IndicatorStatus_Max] =
1226{
1227 checked_item_xpm,
1228 unchecked_item_xpm
1229};
1230
1e6feb95
VZ
1231// ============================================================================
1232// implementation
1233// ============================================================================
1234
1235WX_IMPLEMENT_THEME(wxWin32Theme, win32, wxTRANSLATE("Win32 theme"));
1236
1237// ----------------------------------------------------------------------------
1238// wxWin32Theme
1239// ----------------------------------------------------------------------------
1240
1241wxWin32Theme::wxWin32Theme()
1242{
240889a1
VS
1243 m_scheme = NULL;
1244 m_renderer = NULL;
1e6feb95 1245 m_handlerDefault = NULL;
9ef3ebfb 1246 m_artProvider = NULL;
1e6feb95
VZ
1247}
1248
1249wxWin32Theme::~wxWin32Theme()
1250{
1251 size_t count = m_handlers.GetCount();
1252 for ( size_t n = 0; n < count; n++ )
1253 {
1254 if ( m_handlers[n] != m_handlerDefault )
1255 delete m_handlers[n];
1256 }
1257
1258 delete m_handlerDefault;
1259
1260 delete m_renderer;
1261 delete m_scheme;
9ef3ebfb 1262 wxArtProvider::RemoveProvider(m_artProvider);
1e6feb95
VZ
1263}
1264
240889a1
VS
1265wxRenderer *wxWin32Theme::GetRenderer()
1266{
1267 if ( !m_renderer )
1268 {
1269 m_renderer = new wxWin32Renderer(GetColourScheme());
1270 }
1271
1272 return m_renderer;
1273}
1274
536b70ac
VS
1275wxArtProvider *wxWin32Theme::GetArtProvider()
1276{
1277 if ( !m_artProvider )
1278 {
1279 m_artProvider = new wxWin32ArtProvider;
1280 }
1281
1282 return m_artProvider;
1283}
1284
1e6feb95
VZ
1285wxInputHandler *wxWin32Theme::GetDefaultInputHandler()
1286{
1287 if ( !m_handlerDefault )
1288 {
1289 m_handlerDefault = new wxWin32InputHandler(m_renderer);
1290 }
1291
1292 return m_handlerDefault;
1293}
1294
1295wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control)
1296{
1297 wxInputHandler *handler;
1298 int n = m_handlerNames.Index(control);
1299 if ( n == wxNOT_FOUND )
1300 {
1301 // create a new handler
1302 if ( control == wxINP_HANDLER_SCROLLBAR )
1303 handler = new wxWin32ScrollBarInputHandler(m_renderer,
1304 GetDefaultInputHandler());
1305#if wxUSE_BUTTON
1306 else if ( control == wxINP_HANDLER_BUTTON )
1307 handler = new wxStdButtonInputHandler(GetDefaultInputHandler());
1308#endif // wxUSE_BUTTON
1309#if wxUSE_CHECKBOX
1310 else if ( control == wxINP_HANDLER_CHECKBOX )
1311 handler = new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
1312#endif // wxUSE_CHECKBOX
1313#if wxUSE_COMBOBOX
1314 else if ( control == wxINP_HANDLER_COMBOBOX )
1315 handler = new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1316#endif // wxUSE_COMBOBOX
1317#if wxUSE_LISTBOX
1318 else if ( control == wxINP_HANDLER_LISTBOX )
1319 handler = new wxStdListboxInputHandler(GetDefaultInputHandler());
1320#endif // wxUSE_LISTBOX
1321#if wxUSE_CHECKLISTBOX
1322 else if ( control == wxINP_HANDLER_CHECKLISTBOX )
1323 handler = new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1324#endif // wxUSE_CHECKLISTBOX
1325#if wxUSE_TEXTCTRL
1326 else if ( control == wxINP_HANDLER_TEXTCTRL )
1327 handler = new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1328#endif // wxUSE_TEXTCTRL
1329#if wxUSE_SLIDER
1330 else if ( control == wxINP_HANDLER_SLIDER )
1331 handler = new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1332#endif // wxUSE_SLIDER
1333#if wxUSE_SPINBTN
1334 else if ( control == wxINP_HANDLER_SPINBTN )
1335 handler = new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1336#endif // wxUSE_SPINBTN
1337#if wxUSE_NOTEBOOK
1338 else if ( control == wxINP_HANDLER_NOTEBOOK )
1339 handler = new wxStdNotebookInputHandler(GetDefaultInputHandler());
1340#endif // wxUSE_NOTEBOOK
71e03035
VZ
1341#if wxUSE_STATUSBAR
1342 else if ( control == wxINP_HANDLER_STATUSBAR )
1343 handler = new wxWin32StatusBarInputHandler(GetDefaultInputHandler());
1344#endif // wxUSE_STATUSBAR
3216dbf5
VZ
1345#if wxUSE_TOOLBAR
1346 else if ( control == wxINP_HANDLER_TOOLBAR )
1347 handler = new wxStdToolbarInputHandler(GetDefaultInputHandler());
1348#endif // wxUSE_TOOLBAR
813edf09 1349 else if ( control == wxINP_HANDLER_TOPLEVEL )
768f0c5a 1350 handler = new wxWin32FrameInputHandler(GetDefaultInputHandler());
1e6feb95
VZ
1351 else
1352 handler = GetDefaultInputHandler();
1353
1354 n = m_handlerNames.Add(control);
1355 m_handlers.Insert(handler, n);
1356 }
1357 else // we already have it
1358 {
1359 handler = m_handlers[n];
1360 }
1361
1362 return handler;
1363}
1364
1365wxColourScheme *wxWin32Theme::GetColourScheme()
1366{
240889a1
VS
1367 if ( !m_scheme )
1368 {
1369 m_scheme = new wxWin32ColourScheme;
1370 }
1e6feb95
VZ
1371 return m_scheme;
1372}
1373
1374// ============================================================================
1375// wxWin32ColourScheme
1376// ============================================================================
1377
1378wxColour wxWin32ColourScheme::GetBackground(wxWindow *win) const
1379{
1380 wxColour col;
1381 if ( win->UseBgCol() )
1382 {
1383 // use the user specified colour
1384 col = win->GetBackgroundColour();
1385 }
1386
230205ae 1387 if ( !win->ShouldInheritColours() )
1e6feb95
VZ
1388 {
1389 wxTextCtrl *text = wxDynamicCast(win, wxTextCtrl);
aeb3c1cb
JS
1390#if wxUSE_LISTBOX
1391 wxListBox* listBox = wxDynamicCast(win, wxListBox);
00e086a7 1392#endif
aeb3c1cb
JS
1393 if ( text
1394#if wxUSE_LISTBOX
1395 || listBox
00e086a7 1396#endif
aeb3c1cb 1397 )
1e6feb95 1398 {
aeb3c1cb 1399 if ( !win->IsEnabled() ) // not IsEditable()
1e6feb95 1400 col = Get(CONTROL);
aeb3c1cb
JS
1401 else
1402 {
1403 if ( !col.Ok() )
1404 {
1405 // doesn't depend on the state
1406 col = Get(WINDOW);
1407 }
1408 }
1e6feb95 1409 }
00e086a7 1410
aeb3c1cb
JS
1411 if (!col.Ok())
1412 col = Get(CONTROL); // Most controls should be this colour, not WINDOW
1e6feb95
VZ
1413 }
1414 else
1415 {
1416 int flags = win->GetStateFlags();
1417
1418 // the colour set by the user should be used for the normal state
1419 // and for the states for which we don't have any specific colours
072a81ba 1420 if ( !col.Ok() || (flags & wxCONTROL_PRESSED) != 0 )
1e6feb95
VZ
1421 {
1422 if ( wxDynamicCast(win, wxScrollBar) )
1423 col = Get(flags & wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
1424 : SCROLLBAR);
1425 else
1426 col = Get(CONTROL);
1427 }
1428 }
1429
1430 return col;
1431}
1432
1433wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const
1434{
1435 switch ( col )
1436 {
16bdba2c
VZ
1437 // use the system colours under Windows
1438#if defined(__WXMSW__)
1439 case WINDOW: return wxColour(GetSysColor(COLOR_WINDOW));
1440
1441 case CONTROL_PRESSED:
1442 case CONTROL_CURRENT:
1443 case CONTROL: return wxColour(GetSysColor(COLOR_BTNFACE));
1444
1445 case CONTROL_TEXT: return wxColour(GetSysColor(COLOR_BTNTEXT));
1446
5d3769f5
VZ
1447#if defined(COLOR_3DLIGHT)
1448 case SCROLLBAR: return wxColour(GetSysColor(COLOR_3DLIGHT));
1449#else
1450 case SCROLLBAR: return wxColour(0xe0e0e0);
1451#endif
1452 case SCROLLBAR_PRESSED: return wxColour(GetSysColor(COLOR_BTNTEXT));
16bdba2c
VZ
1453
1454 case HIGHLIGHT: return wxColour(GetSysColor(COLOR_HIGHLIGHT));
1455 case HIGHLIGHT_TEXT: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT));
1456
1457#if defined(COLOR_3DDKSHADOW)
1458 case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DDKSHADOW));
1459#else
a407ff6a 1460 case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DHADOW));
16bdba2c
VZ
1461#endif
1462
1463 case CONTROL_TEXT_DISABLED:
1464 case SHADOW_HIGHLIGHT: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT));
1465
1466 case SHADOW_IN: return wxColour(GetSysColor(COLOR_BTNFACE));
1467
1468 case CONTROL_TEXT_DISABLED_SHADOW:
1469 case SHADOW_OUT: return wxColour(GetSysColor(COLOR_BTNSHADOW));
71e03035 1470
24a23c35
VS
1471 case TITLEBAR: return wxColour(GetSysColor(COLOR_INACTIVECAPTION));
1472 case TITLEBAR_ACTIVE: return wxColour(GetSysColor(COLOR_ACTIVECAPTION));
6296744f
VS
1473 case TITLEBAR_TEXT: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
1474 case TITLEBAR_ACTIVE_TEXT: return wxColour(GetSysColor(COLOR_CAPTIONTEXT));
d1504049 1475
6296744f 1476 case DESKTOP: return wxColour(0x808000);
16bdba2c
VZ
1477#else // !__WXMSW__
1478 // use the standard Windows colours elsewhere
86313763
VZ
1479 case WINDOW: return *wxWHITE;
1480
1e6feb95
VZ
1481 case CONTROL_PRESSED:
1482 case CONTROL_CURRENT:
1483 case CONTROL: return wxColour(0xc0c0c0);
1484
1485 case CONTROL_TEXT: return *wxBLACK;
1486
1487 case SCROLLBAR: return wxColour(0xe0e0e0);
1488 case SCROLLBAR_PRESSED: return *wxBLACK;
1489
1490 case HIGHLIGHT: return wxColour(0x800000);
1491 case HIGHLIGHT_TEXT: return wxColour(0xffffff);
1492
1493 case SHADOW_DARK: return *wxBLACK;
1494
24a23c35
VS
1495 case CONTROL_TEXT_DISABLED:return wxColour(0xe0e0e0);
1496 case SHADOW_HIGHLIGHT: return wxColour(0xffffff);
1e6feb95
VZ
1497
1498 case SHADOW_IN: return wxColour(0xc0c0c0);
1499
1500 case CONTROL_TEXT_DISABLED_SHADOW:
1501 case SHADOW_OUT: return wxColour(0x7f7f7f);
24a23c35
VS
1502
1503 case TITLEBAR: return wxColour(0xaeaaae);
1504 case TITLEBAR_ACTIVE: return wxColour(0x820300);
6296744f
VS
1505 case TITLEBAR_TEXT: return wxColour(0xc0c0c0);
1506 case TITLEBAR_ACTIVE_TEXT:return *wxWHITE;
1507
1508 case DESKTOP: return wxColour(0x808000);
16bdba2c 1509#endif // __WXMSW__
1e6feb95 1510
a407ff6a
VZ
1511 case GAUGE: return Get(HIGHLIGHT);
1512
1e6feb95
VZ
1513 case MAX:
1514 default:
1515 wxFAIL_MSG(_T("invalid standard colour"));
1516 return *wxBLACK;
1517 }
1518}
1519
1520// ============================================================================
1521// wxWin32Renderer
1522// ============================================================================
1523
1524// ----------------------------------------------------------------------------
1525// construction
1526// ----------------------------------------------------------------------------
1527
1528wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme)
1529{
1530 // init data
1531 m_scheme = scheme;
1532 m_sizeScrollbarArrow = wxSize(16, 16);
1533
1534 // init colours and pens
1535 m_penBlack = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_DARK), 0, wxSOLID);
1536
1537 m_colDarkGrey = wxSCHEME_COLOUR(scheme, SHADOW_OUT);
1538 m_penDarkGrey = wxPen(m_colDarkGrey, 0, wxSOLID);
1539
1540 m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN), 0, wxSOLID);
1541
1542 m_colHighlight = wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT);
1543 m_penHighlight = wxPen(m_colHighlight, 0, wxSOLID);
71e03035 1544
a756f210 1545 m_titlebarFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
24a23c35 1546 m_titlebarFont.SetWeight(wxFONTWEIGHT_BOLD);
1e6feb95
VZ
1547
1548 // init the arrow bitmaps
1549 static const size_t ARROW_WIDTH = 7;
1550 static const size_t ARROW_LENGTH = 4;
1551
1552 wxMask *mask;
1553 wxMemoryDC dcNormal,
1554 dcDisabled,
1555 dcInverse;
1556 for ( size_t n = 0; n < Arrow_Max; n++ )
1557 {
1558 bool isVertical = n > Arrow_Right;
1559 int w, h;
1560 if ( isVertical )
1561 {
1562 w = ARROW_WIDTH;
1563 h = ARROW_LENGTH;
1564 }
1565 else
1566 {
1567 h = ARROW_WIDTH;
1568 w = ARROW_LENGTH;
1569 }
1570
1571 // disabled arrow is larger because of the shadow
1572 m_bmpArrows[Arrow_Normal][n].Create(w, h);
1573 m_bmpArrows[Arrow_Disabled][n].Create(w + 1, h + 1);
1574
1575 dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]);
1576 dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]);
1577
1578 dcNormal.SetBackground(*wxWHITE_BRUSH);
1579 dcDisabled.SetBackground(*wxWHITE_BRUSH);
1580 dcNormal.Clear();
1581 dcDisabled.Clear();
1582
1583 dcNormal.SetPen(m_penBlack);
1584 dcDisabled.SetPen(m_penDarkGrey);
1585
1586 // calculate the position of the point of the arrow
1587 wxCoord x1, y1;
1588 if ( isVertical )
1589 {
1590 x1 = (ARROW_WIDTH - 1)/2;
1591 y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1;
1592 }
1593 else // horizontal
1594 {
1595 x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1;
1596 y1 = (ARROW_WIDTH - 1)/2;
1597 }
1598
1599 wxCoord x2 = x1,
1600 y2 = y1;
1601
1602 if ( isVertical )
1603 x2++;
1604 else
1605 y2++;
1606
1607 for ( size_t i = 0; i < ARROW_LENGTH; i++ )
1608 {
1609 dcNormal.DrawLine(x1, y1, x2, y2);
1610 dcDisabled.DrawLine(x1, y1, x2, y2);
1611
1612 if ( isVertical )
1613 {
1614 x1--;
1615 x2++;
1616
1617 if ( n == Arrow_Up )
1618 {
1619 y1++;
1620 y2++;
1621 }
1622 else // down arrow
1623 {
1624 y1--;
1625 y2--;
1626 }
1627 }
1628 else // left or right arrow
1629 {
1630 y1--;
1631 y2++;
1632
1633 if ( n == Arrow_Left )
1634 {
1635 x1++;
1636 x2++;
1637 }
1638 else
1639 {
1640 x1--;
1641 x2--;
1642 }
1643 }
1644 }
1645
1646 // draw the shadow for the disabled one
1647 dcDisabled.SetPen(m_penHighlight);
1648 switch ( n )
1649 {
1650 case Arrow_Left:
1651 y1 += 2;
1652 dcDisabled.DrawLine(x1, y1, x2, y2);
1653 break;
1654
1655 case Arrow_Right:
1656 x1 = ARROW_LENGTH - 1;
1657 y1 = (ARROW_WIDTH - 1)/2 + 1;
1658 x2 = 0;
1659 y2 = ARROW_WIDTH;
1660 dcDisabled.DrawLine(x1, y1, x2, y2);
1661 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1662 break;
1663
1664 case Arrow_Up:
1665 x1 += 2;
1666 dcDisabled.DrawLine(x1, y1, x2, y2);
1667 break;
1668
1669 case Arrow_Down:
1670 x1 = ARROW_WIDTH - 1;
1671 y1 = 1;
1672 x2 = (ARROW_WIDTH - 1)/2;
1673 y2 = ARROW_LENGTH;
1674 dcDisabled.DrawLine(x1, y1, x2, y2);
1675 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1676 break;
1677
1678 }
1679
d6922577 1680 // create the inverted bitmap but only for the right arrow as we only
1e6feb95
VZ
1681 // use it for the menus
1682 if ( n == Arrow_Right )
1683 {
d6922577
JS
1684 m_bmpArrows[Arrow_Inverted][n].Create(w, h);
1685 dcInverse.SelectObject(m_bmpArrows[Arrow_Inverted][n]);
1e6feb95
VZ
1686 dcInverse.Clear();
1687 dcInverse.Blit(0, 0, w, h,
1688 &dcNormal, 0, 0,
1689 wxXOR);
1690 dcInverse.SelectObject(wxNullBitmap);
1691
d6922577
JS
1692 mask = new wxMask(m_bmpArrows[Arrow_Inverted][n], *wxBLACK);
1693 m_bmpArrows[Arrow_Inverted][n].SetMask(mask);
1e6feb95 1694
d6922577
JS
1695 m_bmpArrows[Arrow_InvertedDisabled][n].Create(w, h);
1696 dcInverse.SelectObject(m_bmpArrows[Arrow_InvertedDisabled][n]);
1e6feb95
VZ
1697 dcInverse.Clear();
1698 dcInverse.Blit(0, 0, w, h,
1699 &dcDisabled, 0, 0,
1700 wxXOR);
1701 dcInverse.SelectObject(wxNullBitmap);
1702
d6922577
JS
1703 mask = new wxMask(m_bmpArrows[Arrow_InvertedDisabled][n], *wxBLACK);
1704 m_bmpArrows[Arrow_InvertedDisabled][n].SetMask(mask);
1e6feb95
VZ
1705 }
1706
1707 dcNormal.SelectObject(wxNullBitmap);
1708 dcDisabled.SelectObject(wxNullBitmap);
1709
1710 mask = new wxMask(m_bmpArrows[Arrow_Normal][n], *wxWHITE);
1711 m_bmpArrows[Arrow_Normal][n].SetMask(mask);
1712 mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
1713 m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
1714
1715 m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
1716 }
71e03035 1717
24a23c35
VS
1718 // init the frame buttons bitmaps
1719 m_bmpFrameButtons[FrameButton_Close] = wxBitmap(frame_button_close_xpm);
1720 m_bmpFrameButtons[FrameButton_Minimize] = wxBitmap(frame_button_minimize_xpm);
1721 m_bmpFrameButtons[FrameButton_Maximize] = wxBitmap(frame_button_maximize_xpm);
1722 m_bmpFrameButtons[FrameButton_Restore] = wxBitmap(frame_button_restore_xpm);
1723 m_bmpFrameButtons[FrameButton_Help] = wxBitmap(frame_button_help_xpm);
1e6feb95
VZ
1724}
1725
1726// ----------------------------------------------------------------------------
1727// border stuff
1728// ----------------------------------------------------------------------------
1729
1730/*
1731 The raised border in Win32 looks like this:
1732
1733 IIIIIIIIIIIIIIIIIIIIIIB
1734 I GB
1735 I GB I = white (HILIGHT)
1736 I GB H = light grey (LIGHT)
1737 I GB G = dark grey (SHADOI)
1738 I GB B = black (DKSHADOI)
1739 I GB I = hIghlight (COLOR_3DHILIGHT)
1740 I GB
1741 IGGGGGGGGGGGGGGGGGGGGGB
1742 BBBBBBBBBBBBBBBBBBBBBBB
1743
1744 The sunken border looks like this:
1745
1746 GGGGGGGGGGGGGGGGGGGGGGI
1747 GBBBBBBBBBBBBBBBBBBBBHI
1748 GB HI
1749 GB HI
1750 GB HI
1751 GB HI
1752 GB HI
1753 GB HI
1754 GHHHHHHHHHHHHHHHHHHHHHI
1755 IIIIIIIIIIIIIIIIIIIIIII
1756
1757 The static border (used for the controls which don't get focus) is like
1758 this:
1759
1760 GGGGGGGGGGGGGGGGGGGGGGW
1761 G W
1762 G W
1763 G W
1764 G W
1765 G W
1766 G W
1767 G W
1768 WWWWWWWWWWWWWWWWWWWWWWW
1769
1770 The most complicated is the double border:
1771
1772 HHHHHHHHHHHHHHHHHHHHHHB
1773 HWWWWWWWWWWWWWWWWWWWWGB
1774 HWHHHHHHHHHHHHHHHHHHHGB
1775 HWH HGB
1776 HWH HGB
1777 HWH HGB
1778 HWH HGB
1779 HWHHHHHHHHHHHHHHHHHHHGB
1780 HGGGGGGGGGGGGGGGGGGGGGB
1781 BBBBBBBBBBBBBBBBBBBBBBB
1782
1783 And the simple border is, well, simple:
1784
1785 BBBBBBBBBBBBBBBBBBBBBBB
1786 B B
1787 B B
1788 B B
1789 B B
1790 B B
1791 B B
1792 B B
1793 B B
1794 BBBBBBBBBBBBBBBBBBBBBBB
1795*/
1796
1797void wxWin32Renderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1798{
1799 // draw
1800 dc.SetPen(pen);
1801 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1802 dc.DrawRectangle(*rect);
1803
1804 // adjust the rect
1805 rect->Inflate(-1);
1806}
1807
1808void wxWin32Renderer::DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1809{
1810 // draw the bottom and right sides
1811 dc.SetPen(pen);
1812 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1813 rect->GetRight() + 1, rect->GetBottom());
1814 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1815 rect->GetRight(), rect->GetBottom());
1816
1817 // adjust the rect
136d4499 1818 rect->Inflate(-1);
1e6feb95
VZ
1819}
1820
1821void wxWin32Renderer::DrawShadedRect(wxDC& dc, wxRect *rect,
1822 const wxPen& pen1, const wxPen& pen2)
1823{
1824 // draw the rectangle
1825 dc.SetPen(pen1);
1826 dc.DrawLine(rect->GetLeft(), rect->GetTop(),
1827 rect->GetLeft(), rect->GetBottom());
1828 dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
1829 rect->GetRight(), rect->GetTop());
1830 dc.SetPen(pen2);
1831 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1832 rect->GetRight(), rect->GetBottom());
1833 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1834 rect->GetRight() + 1, rect->GetBottom());
1835
1836 // adjust the rect
1837 rect->Inflate(-1);
1838}
1839
1840void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxRect *rect)
1841{
1842 DrawShadedRect(dc, rect, m_penHighlight, m_penBlack);
1843 DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
1844}
1845
1846void wxWin32Renderer::DrawSunkenBorder(wxDC& dc, wxRect *rect)
1847{
1848 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
1849 DrawShadedRect(dc, rect, m_penBlack, m_penLightGrey);
1850}
1851
1852void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
1853{
1854 if ( isPressed )
1855 {
1856 DrawRect(dc, rect, m_penDarkGrey);
1857
1858 // the arrow is usually drawn inside border of width 2 and is offset by
1859 // another pixel in both directions when it's pressed - as the border
1860 // in this case is more narrow as well, we have to adjust rect like
1861 // this:
1862 rect->Inflate(-1);
1863 rect->x++;
1864 rect->y++;
1865 }
1866 else
1867 {
1868 DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
1869 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
1870 }
1871}
1872
1873void wxWin32Renderer::DrawBorder(wxDC& dc,
1874 wxBorder border,
1875 const wxRect& rectTotal,
1876 int WXUNUSED(flags),
1877 wxRect *rectIn)
1878{
1879 int i;
1880
1881 wxRect rect = rectTotal;
1882
1883 switch ( border )
1884 {
1885 case wxBORDER_SUNKEN:
1886 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1887 {
1888 DrawSunkenBorder(dc, &rect);
1889 }
1890 break;
1891
1892 case wxBORDER_STATIC:
1893 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1894 break;
1895
1896 case wxBORDER_RAISED:
1897 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1898 {
1899 DrawRaisedBorder(dc, &rect);
1900 }
1901 break;
1902
1903 case wxBORDER_DOUBLE:
1904 DrawArrowBorder(dc, &rect);
1905 DrawRect(dc, &rect, m_penLightGrey);
1906 break;
1907
1908 case wxBORDER_SIMPLE:
1909 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1910 {
1911 DrawRect(dc, &rect, m_penBlack);
1912 }
1913 break;
1914
1915 default:
1916 wxFAIL_MSG(_T("unknown border type"));
1917 // fall through
1918
1919 case wxBORDER_DEFAULT:
1920 case wxBORDER_NONE:
1921 break;
1922 }
1923
1924 if ( rectIn )
1925 *rectIn = rect;
1926}
1927
1928wxRect wxWin32Renderer::GetBorderDimensions(wxBorder border) const
1929{
1930 wxCoord width;
1931 switch ( border )
1932 {
1933 case wxBORDER_RAISED:
1934 case wxBORDER_SUNKEN:
1935 width = BORDER_THICKNESS;
1936 break;
1937
1938 case wxBORDER_SIMPLE:
1939 case wxBORDER_STATIC:
1940 width = 1;
1941 break;
1942
1943 case wxBORDER_DOUBLE:
1944 width = 3;
1945 break;
1946
1947 default:
00e086a7 1948 {
372c2812
RR
1949 // char *crash = NULL;
1950 // *crash = 0;
1e6feb95
VZ
1951 wxFAIL_MSG(_T("unknown border type"));
1952 // fall through
372c2812 1953 }
1e6feb95
VZ
1954
1955 case wxBORDER_DEFAULT:
1956 case wxBORDER_NONE:
1957 width = 0;
1958 break;
1959 }
1960
1961 wxRect rect;
1962 rect.x =
1963 rect.y =
1964 rect.width =
1965 rect.height = width;
1966
1967 return rect;
1968}
1969
1970bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1971{
a290fa5a 1972 return true;
1e6feb95
VZ
1973}
1974
1975// ----------------------------------------------------------------------------
1976// borders
1977// ----------------------------------------------------------------------------
1978
1979void wxWin32Renderer::DrawTextBorder(wxDC& dc,
1980 wxBorder border,
1981 const wxRect& rect,
1982 int flags,
1983 wxRect *rectIn)
1984{
1985 // text controls are not special under windows
1986 DrawBorder(dc, border, rect, flags, rectIn);
1987}
1988
1989void wxWin32Renderer::DrawButtonBorder(wxDC& dc,
1990 const wxRect& rectTotal,
1991 int flags,
1992 wxRect *rectIn)
1993{
1994 wxRect rect = rectTotal;
1995
1996 if ( flags & wxCONTROL_PRESSED )
1997 {
1998 // button pressed: draw a double border around it
1999 DrawRect(dc, &rect, m_penBlack);
2000 DrawRect(dc, &rect, m_penDarkGrey);
2001 }
2002 else
2003 {
2004 // button not pressed
2005
2006 if ( flags & (wxCONTROL_FOCUSED | wxCONTROL_ISDEFAULT) )
2007 {
2008 // button either default or focused (or both): add an extra border around it
2009 DrawRect(dc, &rect, m_penBlack);
2010 }
2011
2012 // now draw a normal button
2013 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
2014 DrawHalfRect(dc, &rect, m_penDarkGrey);
2015 }
2016
2017 if ( rectIn )
2018 {
2019 *rectIn = rect;
2020 }
2021}
2022
2023// ----------------------------------------------------------------------------
2024// lines and frame
2025// ----------------------------------------------------------------------------
2026
2027void wxWin32Renderer::DrawHorizontalLine(wxDC& dc,
2028 wxCoord y, wxCoord x1, wxCoord x2)
2029{
2030 dc.SetPen(m_penDarkGrey);
2031 dc.DrawLine(x1, y, x2 + 1, y);
2032 dc.SetPen(m_penHighlight);
2033 y++;
2034 dc.DrawLine(x1, y, x2 + 1, y);
2035}
2036
2037void wxWin32Renderer::DrawVerticalLine(wxDC& dc,
2038 wxCoord x, wxCoord y1, wxCoord y2)
2039{
2040 dc.SetPen(m_penDarkGrey);
2041 dc.DrawLine(x, y1, x, y2 + 1);
2042 dc.SetPen(m_penHighlight);
2043 x++;
2044 dc.DrawLine(x, y1, x, y2 + 1);
2045}
2046
2047void wxWin32Renderer::DrawFrame(wxDC& dc,
2048 const wxString& label,
2049 const wxRect& rect,
2050 int flags,
2051 int alignment,
2052 int indexAccel)
2053{
2054 wxCoord height = 0; // of the label
2055 wxRect rectFrame = rect;
2056 if ( !label.empty() )
2057 {
2058 // the text should touch the top border of the rect, so the frame
2059 // itself should be lower
2060 dc.GetTextExtent(label, NULL, &height);
2061 rectFrame.y += height / 2;
2062 rectFrame.height -= height / 2;
2063
2064 // we have to draw each part of the frame individually as we can't
2065 // erase the background beyond the label as it might contain some
2066 // pixmap already, so drawing everything and then overwriting part of
2067 // the frame with label doesn't work
2068
2069 // TODO: the +5 and space insertion should be customizable
2070
2071 wxRect rectText;
2072 rectText.x = rectFrame.x + 5;
2073 rectText.y = rect.y;
2074 rectText.width = rectFrame.width - 7; // +2 border width
2075 rectText.height = height;
2076
2077 wxString label2;
2078 label2 << _T(' ') << label << _T(' ');
2079 if ( indexAccel != -1 )
2080 {
2081 // adjust it as we prepended a space
2082 indexAccel++;
2083 }
2084
2085 wxRect rectLabel;
2086 DrawLabel(dc, label2, rectText, flags, alignment, indexAccel, &rectLabel);
2087
2088 StandardDrawFrame(dc, rectFrame, rectLabel);
2089 }
2090 else
2091 {
2092 // just draw the complete frame
2093 DrawShadedRect(dc, &rectFrame, m_penDarkGrey, m_penHighlight);
2094 DrawShadedRect(dc, &rectFrame, m_penHighlight, m_penDarkGrey);
2095 }
2096}
2097
2098// ----------------------------------------------------------------------------
2099// label
2100// ----------------------------------------------------------------------------
2101
2102void wxWin32Renderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
2103{
2104 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
2105 // pixels each while we really need dots here... PS_ALTERNATE might
2106 // work, but it is for NT 5 only
2107#if 0
2108 DrawRect(dc, &rect, wxPen(*wxBLACK, 0, wxDOT));
2109#else
2110 // draw the pixels manually: note that to behave in the same manner as
2111 // DrawRect(), we must exclude the bottom and right borders from the
2112 // rectangle
2113 wxCoord x1 = rect.GetLeft(),
2114 y1 = rect.GetTop(),
2115 x2 = rect.GetRight(),
2116 y2 = rect.GetBottom();
2117
2118 dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID));
2119
2120 // this seems to be closer than what Windows does than wxINVERT although
2121 // I'm still not sure if it's correct
2122 dc.SetLogicalFunction(wxAND_REVERSE);
2123
2124 wxCoord z;
2125 for ( z = x1 + 1; z < x2; z += 2 )
2126 dc.DrawPoint(z, rect.GetTop());
2127
2128 wxCoord shift = z == x2 ? 0 : 1;
2129 for ( z = y1 + shift; z < y2; z += 2 )
2130 dc.DrawPoint(x2, z);
2131
2132 shift = z == y2 ? 0 : 1;
2133 for ( z = x2 - shift; z > x1; z -= 2 )
2134 dc.DrawPoint(z, y2);
2135
2136 shift = z == x1 ? 0 : 1;
2137 for ( z = y2 - shift; z > y1; z -= 2 )
2138 dc.DrawPoint(x1, z);
2139
2140 dc.SetLogicalFunction(wxCOPY);
2141#endif // 0/1
2142}
2143
2144void wxWin32Renderer::DrawLabelShadow(wxDC& dc,
2145 const wxString& label,
2146 const wxRect& rect,
2147 int alignment,
2148 int indexAccel)
2149{
2150 // draw shadow of the text
2151 dc.SetTextForeground(m_colHighlight);
2152 wxRect rectShadow = rect;
2153 rectShadow.x++;
2154 rectShadow.y++;
2155 dc.DrawLabel(label, rectShadow, alignment, indexAccel);
2156
2157 // make the text grey
2158 dc.SetTextForeground(m_colDarkGrey);
2159}
2160
2161void wxWin32Renderer::DrawLabel(wxDC& dc,
2162 const wxString& label,
2163 const wxRect& rect,
2164 int flags,
2165 int alignment,
2166 int indexAccel,
2167 wxRect *rectBounds)
2168{
2169 DoDrawLabel(dc, label, rect, flags, alignment, indexAccel, rectBounds);
2170}
2171
2172void wxWin32Renderer::DoDrawLabel(wxDC& dc,
2173 const wxString& label,
2174 const wxRect& rect,
2175 int flags,
2176 int alignment,
2177 int indexAccel,
2178 wxRect *rectBounds,
2179 const wxPoint& focusOffset)
2180{
2181 // the underscores are not drawn for focused controls in wxMSW
2182 if ( flags & wxCONTROL_FOCUSED )
2183 {
2184 indexAccel = -1;
2185 }
2186
2187 if ( flags & wxCONTROL_DISABLED )
2188 {
2189 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2190 // currently only can happen for a menu item and it seems that Windows
2191 // doesn't draw the shadow in this case, so we don't do it neither
2192 if ( flags & wxCONTROL_SELECTED )
2193 {
2194 // just make the label text greyed out
2195 dc.SetTextForeground(m_colDarkGrey);
2196 }
2197 else // draw normal disabled label
2198 {
2199 DrawLabelShadow(dc, label, rect, alignment, indexAccel);
2200 }
2201 }
2202
2203 wxRect rectLabel;
2204 dc.DrawLabel(label, wxNullBitmap, rect, alignment, indexAccel, &rectLabel);
2205
2206 if ( flags & wxCONTROL_DISABLED )
2207 {
2208 // restore the fg colour
2209 dc.SetTextForeground(*wxBLACK);
2210 }
2211
2212 if ( flags & wxCONTROL_FOCUSED )
2213 {
2214 if ( focusOffset.x || focusOffset.y )
2215 {
1e6feb95
VZ
2216 rectLabel.Inflate(focusOffset.x, focusOffset.y);
2217 }
2218
2219 DrawFocusRect(dc, rectLabel);
2220 }
2221
2222 if ( rectBounds )
2223 *rectBounds = rectLabel;
2224}
2225
2226void wxWin32Renderer::DrawButtonLabel(wxDC& dc,
2227 const wxString& label,
2228 const wxBitmap& image,
2229 const wxRect& rect,
2230 int flags,
2231 int alignment,
2232 int indexAccel,
2233 wxRect *rectBounds)
2234{
2235 // the underscores are not drawn for focused controls in wxMSW
2236 if ( flags & wxCONTROL_PRESSED )
2237 {
2238 indexAccel = -1;
2239 }
2240
2241 wxRect rectLabel = rect;
2242 if ( !label.empty() )
2243 {
2244 // shift the label if a button is pressed
2245 if ( flags & wxCONTROL_PRESSED )
2246 {
2247 rectLabel.x++;
2248 rectLabel.y++;
2249 }
2250
2251 if ( flags & wxCONTROL_DISABLED )
2252 {
2253 DrawLabelShadow(dc, label, rectLabel, alignment, indexAccel);
2254 }
2255
2256 // leave enough space for the focus rectangle
2257 if ( flags & wxCONTROL_FOCUSED )
2258 {
2259 rectLabel.Inflate(-2);
2260 }
2261 }
2262
2263 dc.DrawLabel(label, image, rectLabel, alignment, indexAccel, rectBounds);
2264
2265 if ( !label.empty() && (flags & wxCONTROL_FOCUSED) )
2266 {
2267 if ( flags & wxCONTROL_PRESSED )
2268 {
2269 // the focus rectangle is never pressed, so undo the shift done
2270 // above
2271 rectLabel.x--;
2272 rectLabel.y--;
2273 rectLabel.width--;
2274 rectLabel.height--;
2275 }
2276
2277 DrawFocusRect(dc, rectLabel);
2278 }
2279}
2280
2281// ----------------------------------------------------------------------------
2282// (check)listbox items
2283// ----------------------------------------------------------------------------
2284
2285void wxWin32Renderer::DrawItem(wxDC& dc,
2286 const wxString& label,
2287 const wxRect& rect,
2288 int flags)
2289{
2290 wxDCTextColourChanger colChanger(dc);
2291
2292 if ( flags & wxCONTROL_SELECTED )
2293 {
2294 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2295
2296 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2297 dc.SetBrush(wxBrush(colBg, wxSOLID));
2298 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2299 dc.DrawRectangle(rect);
2300 }
2301
2302 wxRect rectText = rect;
2303 rectText.x += 2;
2304 rectText.width -= 2;
2305 dc.DrawLabel(label, wxNullBitmap, rectText);
2306
2307 if ( flags & wxCONTROL_FOCUSED )
2308 {
2309 DrawFocusRect(dc, rect);
2310 }
2311}
2312
2313void wxWin32Renderer::DrawCheckItem(wxDC& dc,
2314 const wxString& label,
2315 const wxBitmap& bitmap,
2316 const wxRect& rect,
2317 int flags)
2318{
2319 wxBitmap bmp;
2320 if ( bitmap.Ok() )
2321 {
2322 bmp = bitmap;
2323 }
2324 else // use default bitmap
2325 {
e3400e2e
VZ
2326 IndicatorStatus i = flags & wxCONTROL_CHECKED
2327 ? IndicatorStatus_Checked
2328 : IndicatorStatus_Unchecked;
2329
2330 if ( !m_bmpCheckBitmaps[i].Ok() )
2331 {
2332 m_bmpCheckBitmaps[i] = wxBitmap(xpmChecked[i]);
2333 }
2334
2335 bmp = m_bmpCheckBitmaps[i];
1e6feb95
VZ
2336 }
2337
2338 dc.DrawBitmap(bmp, rect.x, rect.y + (rect.height - bmp.GetHeight()) / 2 - 1,
a290fa5a 2339 true /* use mask */);
1e6feb95
VZ
2340
2341 wxRect rectLabel = rect;
2342 int bmpWidth = bmp.GetWidth();
2343 rectLabel.x += bmpWidth;
2344 rectLabel.width -= bmpWidth;
2345
2346 DrawItem(dc, label, rectLabel, flags);
2347}
2348
2349// ----------------------------------------------------------------------------
2350// check/radio buttons
2351// ----------------------------------------------------------------------------
2352
2353wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags)
2354{
2355 IndicatorState indState;
2356 if ( flags & wxCONTROL_SELECTED )
2357 indState = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
2358 : IndicatorState_Selected;
2359 else if ( flags & wxCONTROL_DISABLED )
2360 indState = IndicatorState_Disabled;
2361 else if ( flags & wxCONTROL_PRESSED )
2362 indState = IndicatorState_Pressed;
2363 else
2364 indState = IndicatorState_Normal;
2365
2366 IndicatorStatus indStatus = flags & wxCONTROL_CHECKED
2367 ? IndicatorStatus_Checked
415a0ff1
WS
2368 : ( flags & wxCONTROL_UNDETERMINED
2369 ? IndicatorStatus_Undeterminated
2370 : IndicatorStatus_Unchecked );
1e6feb95 2371
e3400e2e
VZ
2372 wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus];
2373 if ( !bmp.Ok() )
54a96d02 2374 {
e3400e2e
VZ
2375 const char **xpm = xpmIndicators[indType][indState][indStatus];
2376 if ( xpm )
2377 {
2378 // create and cache it
2379 bmp = wxBitmap(xpm);
2380 m_bmpIndicators[indType][indState][indStatus] = bmp;
2381 }
54a96d02 2382 }
e3400e2e
VZ
2383
2384 return bmp;
1e6feb95
VZ
2385}
2386
2387void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc,
2388 const wxString& label,
2389 const wxBitmap& bitmap,
2390 const wxRect& rect,
2391 int flags,
2392 wxAlignment align,
2393 int indexAccel,
2394 wxCoord focusOffsetY)
2395{
2396 // calculate the position of the bitmap and of the label
2397 wxCoord heightBmp = bitmap.GetHeight();
2398 wxCoord xBmp,
2399 yBmp = rect.y + (rect.height - heightBmp) / 2;
2400
2401 wxRect rectLabel;
2402 dc.GetMultiLineTextExtent(label, NULL, &rectLabel.height);
2403 rectLabel.y = rect.y + (rect.height - rectLabel.height) / 2;
2404
2405 // align label vertically with the bitmap - looks nicer like this
2406 rectLabel.y -= (rectLabel.height - heightBmp) % 2;
2407
2408 // calc horz position
2409 if ( align == wxALIGN_RIGHT )
2410 {
2411 xBmp = rect.GetRight() - bitmap.GetWidth();
2412 rectLabel.x = rect.x + 3;
2413 rectLabel.SetRight(xBmp);
2414 }
2415 else // normal (checkbox to the left of the text) case
2416 {
2417 xBmp = rect.x;
2418 rectLabel.x = xBmp + bitmap.GetWidth() + 5;
2419 rectLabel.SetRight(rect.GetRight());
2420 }
2421
a290fa5a 2422 dc.DrawBitmap(bitmap, xBmp, yBmp, true /* use mask */);
1e6feb95
VZ
2423
2424 DoDrawLabel(
2425 dc, label, rectLabel,
2426 flags,
2427 wxALIGN_LEFT | wxALIGN_TOP,
2428 indexAccel,
2429 NULL, // we don't need bounding rect
2430 // use custom vert focus rect offset
2431 wxPoint(FOCUS_RECT_OFFSET_X, focusOffsetY)
2432 );
2433}
2434
2435void wxWin32Renderer::DrawRadioButton(wxDC& dc,
2436 const wxString& label,
2437 const wxBitmap& bitmap,
2438 const wxRect& rect,
2439 int flags,
2440 wxAlignment align,
2441 int indexAccel)
2442{
cc4bc3a0
VZ
2443 wxBitmap bmp;
2444 if ( bitmap.Ok() )
2445 bmp = bitmap;
54a96d02 2446 else
cc4bc3a0
VZ
2447 bmp = GetRadioBitmap(flags);
2448
2449 DrawCheckOrRadioButton(dc, label,
2450 bmp,
1e6feb95 2451 rect, flags, align, indexAccel,
cc4bc3a0 2452 FOCUS_RECT_OFFSET_Y); // default focus rect offset
1e6feb95
VZ
2453}
2454
2455void wxWin32Renderer::DrawCheckButton(wxDC& dc,
2456 const wxString& label,
2457 const wxBitmap& bitmap,
2458 const wxRect& rect,
2459 int flags,
2460 wxAlignment align,
2461 int indexAccel)
2462{
cc4bc3a0
VZ
2463 wxBitmap bmp;
2464 if ( bitmap.Ok() )
2465 bmp = bitmap;
54a96d02 2466 else
cc4bc3a0
VZ
2467 bmp = GetCheckBitmap(flags);
2468
2469 DrawCheckOrRadioButton(dc, label,
2470 bmp,
2471 rect, flags, align, indexAccel,
2472 0); // no focus rect offset for checkboxes
1e6feb95
VZ
2473}
2474
3216dbf5
VZ
2475void wxWin32Renderer::DrawToolBarButton(wxDC& dc,
2476 const wxString& label,
2477 const wxBitmap& bitmap,
2478 const wxRect& rectOrig,
a8f4cabe
JS
2479 int flags,
2480 long style)
3216dbf5 2481{
a8f4cabe 2482 if (style == wxTOOL_STYLE_BUTTON)
3216dbf5
VZ
2483 {
2484 wxRect rect = rectOrig;
2485 rect.Deflate(BORDER_THICKNESS);
2486
2487 if ( flags & wxCONTROL_PRESSED )
2488 {
2489 DrawBorder(dc, wxBORDER_SUNKEN, rect, flags);
2490 }
2491 else if ( flags & wxCONTROL_CURRENT )
2492 {
2493 DrawBorder(dc, wxBORDER_RAISED, rect, flags);
2494 }
2495
2496 dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
2497 }
a8f4cabe 2498 else if (style == wxTOOL_STYLE_SEPARATOR)
3216dbf5 2499 {
2d3cddaf
VZ
2500 // leave a small gap aroudn the line, also account for the toolbar
2501 // border itself
2502 DrawVerticalLine(dc, rectOrig.x + rectOrig.width/2,
2503 rectOrig.y + 2*BORDER_THICKNESS,
2504 rectOrig.GetBottom() - BORDER_THICKNESS);
3216dbf5 2505 }
a8f4cabe 2506 // don't draw wxTOOL_STYLE_CONTROL
3216dbf5
VZ
2507}
2508
1e6feb95
VZ
2509// ----------------------------------------------------------------------------
2510// text control
2511// ----------------------------------------------------------------------------
2512
2513void wxWin32Renderer::DrawTextLine(wxDC& dc,
2514 const wxString& text,
2515 const wxRect& rect,
2516 int selStart,
2517 int selEnd,
2518 int flags)
2519{
2520 // nothing special to do here
2521 StandardDrawTextLine(dc, text, rect, selStart, selEnd, flags);
2522}
2523
61fef19b
VZ
2524void
2525wxWin32Renderer::DrawLineWrapMark(wxDC& WXUNUSED(dc),
2526 const wxRect& WXUNUSED(rect))
1e6feb95
VZ
2527{
2528 // we don't draw them
2529}
2530
2531// ----------------------------------------------------------------------------
2532// notebook
2533// ----------------------------------------------------------------------------
2534
2535void wxWin32Renderer::DrawTab(wxDC& dc,
2536 const wxRect& rectOrig,
2537 wxDirection dir,
2538 const wxString& label,
2539 const wxBitmap& bitmap,
2540 int flags,
2541 int indexAccel)
2542{
00e086a7
WS
2543 #define SELECT_FOR_VERTICAL(X,Y) ( isVertical ? Y : X )
2544 #define REVERSE_FOR_VERTICAL(X,Y) \
2545 SELECT_FOR_VERTICAL(X,Y) \
2546 , \
2547 SELECT_FOR_VERTICAL(Y,X)
2548
1e6feb95
VZ
2549 wxRect rect = rectOrig;
2550
00e086a7
WS
2551 bool isVertical = ( dir == wxLEFT ) || ( dir == wxRIGHT );
2552
1e6feb95
VZ
2553 // the current tab is drawn indented (to the top for default case) and
2554 // bigger than the other ones
2555 const wxSize indent = GetTabIndent();
2556 if ( flags & wxCONTROL_SELECTED )
2557 {
7166a05d
WS
2558 rect.Inflate( SELECT_FOR_VERTICAL( indent.x , 0),
2559 SELECT_FOR_VERTICAL( 0, indent.y ));
1e6feb95
VZ
2560 switch ( dir )
2561 {
2562 default:
2563 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2564 // fall through
2565
2566 case wxTOP:
1e6feb95 2567 rect.y -= indent.y;
00e086a7 2568 // fall through
1e6feb95 2569 case wxBOTTOM:
1e6feb95
VZ
2570 rect.height += indent.y;
2571 break;
2572
2573 case wxLEFT:
00e086a7
WS
2574 rect.x -= indent.x;
2575 // fall through
1e6feb95 2576 case wxRIGHT:
00e086a7 2577 rect.width += indent.x;
1e6feb95
VZ
2578 break;
2579 }
2580 }
2581
2582 // draw the text, image and the focus around them (if necessary)
00e086a7
WS
2583 wxRect rectLabel( REVERSE_FOR_VERTICAL(rect.x,rect.y),
2584 REVERSE_FOR_VERTICAL(rect.width,rect.height)
2585 );
1e6feb95 2586 rectLabel.Deflate(1, 1);
00e086a7
WS
2587 if ( isVertical )
2588 {
2589 // draw it horizontally into memory and rotate for screen
2590 wxMemoryDC dcMem;
2591 wxBitmap bitmapRotated,
2592 bitmapMem( rectLabel.x + rectLabel.width,
2593 rectLabel.y + rectLabel.height );
2594 dcMem.SelectObject(bitmapMem);
2595 dcMem.SetBackground(dc.GetBackground());
2596 dcMem.SetFont(dc.GetFont());
2597 dcMem.SetTextForeground(dc.GetTextForeground());
2598 dcMem.Clear();
2599 bitmapRotated = wxBitmap( wxImage( bitmap.ConvertToImage() ).Rotate90(dir==wxLEFT) );
2600 DrawButtonLabel(dcMem, label, bitmapRotated, rectLabel,
2601 flags, wxALIGN_CENTRE, indexAccel);
2602 dcMem.SelectObject(wxNullBitmap);
2603 bitmapMem = bitmapMem.GetSubBitmap(rectLabel);
2604 bitmapMem = wxBitmap(wxImage(bitmapMem.ConvertToImage()).Rotate90(dir==wxRIGHT));
2605 dc.DrawBitmap(bitmapMem, rectLabel.y, rectLabel.x, false);
2606 }
2607 else
2608 {
2609 DrawButtonLabel(dc, label, bitmap, rectLabel,
2610 flags, wxALIGN_CENTRE, indexAccel);
2611 }
1e6feb95
VZ
2612
2613 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2614 static const wxCoord CUTOFF = 2; // radius of the rounded corner
00e086a7
WS
2615 wxCoord x = SELECT_FOR_VERTICAL(rect.x,rect.y),
2616 y = SELECT_FOR_VERTICAL(rect.y,rect.x),
2617 x2 = SELECT_FOR_VERTICAL(rect.GetRight(),rect.GetBottom()),
2618 y2 = SELECT_FOR_VERTICAL(rect.GetBottom(),rect.GetRight());
1e6feb95
VZ
2619
2620 // FIXME: all this code will break if the tab indent or the border width,
2621 // it is tied to the fact that both of them are equal to 2
2622 switch ( dir )
2623 {
2624 default:
00e086a7
WS
2625 // default is top
2626 case wxLEFT:
2627 // left orientation looks like top but IsVertical makes x and y reversed
1e6feb95 2628 case wxTOP:
00e086a7 2629 // top is not vertical so use coordinates in written order
1e6feb95 2630 dc.SetPen(m_penHighlight);
00e086a7
WS
2631 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y2),
2632 REVERSE_FOR_VERTICAL(x, y + CUTOFF));
2633 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y + CUTOFF),
2634 REVERSE_FOR_VERTICAL(x + CUTOFF, y));
2635 dc.DrawLine(REVERSE_FOR_VERTICAL(x + CUTOFF, y),
2636 REVERSE_FOR_VERTICAL(x2 - CUTOFF + 1, y));
1e6feb95
VZ
2637
2638 dc.SetPen(m_penBlack);
00e086a7
WS
2639 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2),
2640 REVERSE_FOR_VERTICAL(x2, y + CUTOFF));
2641 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y + CUTOFF),
2642 REVERSE_FOR_VERTICAL(x2 - CUTOFF, y));
1e6feb95
VZ
2643
2644 dc.SetPen(m_penDarkGrey);
00e086a7
WS
2645 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y2),
2646 REVERSE_FOR_VERTICAL(x2 - 1, y + CUTOFF - 1));
1e6feb95
VZ
2647
2648 if ( flags & wxCONTROL_SELECTED )
2649 {
2650 dc.SetPen(m_penLightGrey);
2651
2652 // overwrite the part of the border below this tab
00e086a7
WS
2653 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 + 1),
2654 REVERSE_FOR_VERTICAL(x2 - 1, y2 + 1));
1e6feb95
VZ
2655
2656 // and the shadow of the tab to the left of us
00e086a7
WS
2657 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y + CUTOFF + 1),
2658 REVERSE_FOR_VERTICAL(x + 1, y2 + 1));
1e6feb95
VZ
2659 }
2660 break;
2661
00e086a7
WS
2662 case wxRIGHT:
2663 // right orientation looks like bottom but IsVertical makes x and y reversed
1e6feb95 2664 case wxBOTTOM:
00e086a7 2665 // bottom is not vertical so use coordinates in written order
1e6feb95
VZ
2666 dc.SetPen(m_penHighlight);
2667 // we need to continue one pixel further to overwrite the corner of
2668 // the border for the selected tab
00e086a7
WS
2669 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0)),
2670 REVERSE_FOR_VERTICAL(x, y2 - CUTOFF));
2671 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y2 - CUTOFF),
2672 REVERSE_FOR_VERTICAL(x + CUTOFF, y2));
1e6feb95
VZ
2673
2674 dc.SetPen(m_penBlack);
00e086a7
WS
2675 dc.DrawLine(REVERSE_FOR_VERTICAL(x + CUTOFF, y2),
2676 REVERSE_FOR_VERTICAL(x2 - CUTOFF + 1, y2));
2677 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y),
2678 REVERSE_FOR_VERTICAL(x2, y2 - CUTOFF));
2679 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2 - CUTOFF),
2680 REVERSE_FOR_VERTICAL(x2 - CUTOFF, y2));
1e6feb95
VZ
2681
2682 dc.SetPen(m_penDarkGrey);
00e086a7
WS
2683 dc.DrawLine(REVERSE_FOR_VERTICAL(x + CUTOFF, y2 - 1),
2684 REVERSE_FOR_VERTICAL(x2 - CUTOFF + 1, y2 - 1));
2685 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y),
2686 REVERSE_FOR_VERTICAL(x2 - 1, y2 - CUTOFF + 1));
1e6feb95
VZ
2687
2688 if ( flags & wxCONTROL_SELECTED )
2689 {
2690 dc.SetPen(m_penLightGrey);
2691
2692 // overwrite the part of the (double!) border above this tab
00e086a7
WS
2693 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 1),
2694 REVERSE_FOR_VERTICAL(x2 - 1, y - 1));
2695 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 2),
2696 REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1e6feb95
VZ
2697
2698 // and the shadow of the tab to the left of us
00e086a7
WS
2699 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 - CUTOFF),
2700 REVERSE_FOR_VERTICAL(x + 1, y - 1));
1e6feb95
VZ
2701 }
2702 break;
1e6feb95 2703 }
00e086a7
WS
2704
2705 #undef SELECT_FOR_VERTICAL
2706 #undef REVERSE_FOR_VERTICAL
1e6feb95
VZ
2707}
2708
2709// ----------------------------------------------------------------------------
2710// slider
2711// ----------------------------------------------------------------------------
2712
61fef19b
VZ
2713wxSize
2714wxWin32Renderer::GetSliderThumbSize(const wxRect& WXUNUSED(rect),
2715 int lenThumb,
2716 wxOrientation orient) const
1e6feb95
VZ
2717{
2718 wxSize size;
6766e5d1
JS
2719 wxCoord width = wxMax (lenThumb, SLIDER_THUMB_LENGTH) / 2;
2720 wxCoord height = wxMax (lenThumb, SLIDER_THUMB_LENGTH);
1e6feb95 2721
00e086a7 2722 if (orient == wxHORIZONTAL)
1e6feb95 2723 {
6766e5d1
JS
2724 size.x = width;
2725 size.y = height;
1e6feb95 2726 }
6766e5d1
JS
2727 else
2728 { // == wxVERTICAL
2729 size.x = height;
2730 size.y = width;
1e6feb95
VZ
2731 }
2732
2733 return size;
2734}
2735
2736wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
6766e5d1
JS
2737 int lenThumb,
2738 wxOrientation orient,
2739 long style) const
1e6feb95 2740{
6766e5d1
JS
2741 bool transpose = (orient == wxVERTICAL);
2742 bool left = ((style & wxSL_AUTOTICKS) != 0) &
2743 (((style & wxSL_TOP) != 0) & !transpose |
2744 ((style & wxSL_LEFT) != 0) & transpose |
2745 ((style & wxSL_BOTH) != 0));
2746 bool right = ((style & wxSL_AUTOTICKS) != 0) &
2747 (((style & wxSL_BOTTOM) != 0) & !transpose |
2748 ((style & wxSL_RIGHT) != 0) & transpose |
2749 ((style & wxSL_BOTH) != 0));
1e6feb95
VZ
2750
2751 wxRect rect = rectOrig;
2752
6766e5d1 2753 wxSize sizeThumb = GetSliderThumbSize (rect, lenThumb, orient);
1e6feb95 2754
6766e5d1
JS
2755 if (orient == wxHORIZONTAL) {
2756 rect.x += SLIDER_MARGIN;
00e086a7 2757 if (left & right)
6766e5d1
JS
2758 {
2759 rect.y += wxMax ((rect.height - 2*BORDER_THICKNESS) / 2, sizeThumb.y/2);
2760 }
00e086a7 2761 else if (left)
6766e5d1
JS
2762 {
2763 rect.y += wxMax ((rect.height - 2*BORDER_THICKNESS - sizeThumb.y/2), sizeThumb.y/2);
2764 }
2765 else
2766 {
2767 rect.y += sizeThumb.y/2;
2768 }
2769 rect.width -= 2*SLIDER_MARGIN;
2770 rect.height = 2*BORDER_THICKNESS;
1e6feb95 2771 }
6766e5d1
JS
2772 else
2773 { // == wxVERTICAL
2774 rect.y += SLIDER_MARGIN;
00e086a7 2775 if (left & right)
6766e5d1
JS
2776 {
2777 rect.x += wxMax ((rect.width - 2*BORDER_THICKNESS) / 2, sizeThumb.x/2);
2778 }
00e086a7 2779 else if (left)
6766e5d1
JS
2780 {
2781 rect.x += wxMax ((rect.width - 2*BORDER_THICKNESS - sizeThumb.x/2), sizeThumb.x/2);
2782 }
2783 else
2784 {
2785 rect.x += sizeThumb.x/2;
2786 }
1e6feb95 2787 rect.width = 2*BORDER_THICKNESS;
6766e5d1 2788 rect.height -= 2*SLIDER_MARGIN;
1e6feb95
VZ
2789 }
2790
2791 return rect;
2792}
2793
2794void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
2795 const wxRect& rectOrig,
6766e5d1 2796 int lenThumb,
1e6feb95
VZ
2797 wxOrientation orient,
2798 int flags,
6766e5d1 2799 long style,
1e6feb95
VZ
2800 wxRect *rectShaft)
2801{
6766e5d1
JS
2802 /* show shaft geometry
2803
2804 shaft
2805 +-------------+
2806 | |
2807 | XXX | <-- x1
2808 | XXX |
2809 | XXX |
2810 | XXX |
2811 | XXX | <-- x2
2812 | |
2813 +-------------+
2814
2815 ^ ^
2816 | |
2817 y1 y2
2818 */
2819
2820 if (flags & wxCONTROL_FOCUSED) {
1e6feb95
VZ
2821 DrawFocusRect(dc, rectOrig);
2822 }
2823
6766e5d1 2824 wxRect rect = GetSliderShaftRect(rectOrig, lenThumb, orient, style);
1e6feb95 2825
6766e5d1 2826 if (rectShaft) *rectShaft = rect;
1e6feb95
VZ
2827
2828 DrawSunkenBorder(dc, &rect);
2829}
2830
2831void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
2832 const wxRect& rect,
2833 wxOrientation orient,
6766e5d1
JS
2834 int flags,
2835 long style)
1e6feb95 2836{
6766e5d1
JS
2837 /* show thumb geometry
2838
2839 H <--- y1
2840 H H B
2841 H H B
2842 H H B <--- y3
2843 H D B
2844 H D B
2845 H D B
d6922577 2846 H D B where H is highlight colour
6766e5d1
JS
2847 H D B D dark grey
2848 H D B B black
2849 H D B
2850 H D B
2851 H D B <--- y4
2852 H D B
2853 H D B
2854 B <--- y2
2855
2856 ^ ^ ^
2857 | | |
2858 x1 x3 x2
1e6feb95
VZ
2859
2860 The interior of this shape is filled with the hatched brush if the thumb
2861 is pressed.
2862 */
2863
2864 DrawBackground(dc, wxNullColour, rect, flags);
2865
6766e5d1
JS
2866 bool transpose = (orient == wxVERTICAL);
2867 bool left = ((style & wxSL_AUTOTICKS) != 0) &
2868 (((style & wxSL_TOP) != 0) & !transpose |
2869 ((style & wxSL_LEFT) != 0) & transpose) &
2870 ((style & wxSL_BOTH) == 0);
2871 bool right = ((style & wxSL_AUTOTICKS) != 0) &
2872 (((style & wxSL_BOTTOM) != 0) & !transpose |
2873 ((style & wxSL_RIGHT) != 0) & transpose) &
2874 ((style & wxSL_BOTH) == 0);
2875
2876 wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
2877 wxCoord c = ((transpose ? rect.height : rect.width) - 2*sizeArrow);
2878
2879 wxCoord x1, x2, x3, y1, y2, y3, y4;
2880 x1 = (transpose ? rect.y : rect.x);
2881 x2 = (transpose ? rect.GetBottom() : rect.GetRight());
2882 x3 = (x1-1+c) + sizeArrow;
2883 y1 = (transpose ? rect.x : rect.y);
2884 y2 = (transpose ? rect.GetRight() : rect.GetBottom());
2885 y3 = (left ? (y1-1+c) + sizeArrow : y1);
2886 y4 = (right ? (y2+1-c) - sizeArrow : y2);
1e6feb95 2887
6766e5d1
JS
2888 dc.SetPen(m_penBlack);
2889 if (left) {
2890 DrawLine(dc, x3+1-c, y1, x2, y3, transpose);
2891 }
2892 DrawLine(dc, x2, y3, x2, y4, transpose);
00e086a7 2893 if (right)
1e6feb95 2894 {
6766e5d1 2895 DrawLine(dc, x3+1-c, y2, x2, y4, transpose);
1e6feb95
VZ
2896 }
2897 else
2898 {
6766e5d1 2899 DrawLine(dc, x1, y2, x2, y2, transpose);
1e6feb95
VZ
2900 }
2901
1e6feb95 2902 dc.SetPen(m_penDarkGrey);
6766e5d1
JS
2903 DrawLine(dc, x2-1, y3+1, x2-1, y4-1, transpose);
2904 if (right) {
2905 DrawLine(dc, x3+1-c, y2-1, x2-1, y4, transpose);
2906 }
2907 else
2908 {
2909 DrawLine(dc, x1+1, y2-1, x2-1, y2-1, transpose);
2910 }
1e6feb95 2911
6766e5d1 2912 dc.SetPen(m_penHighlight);
00e086a7 2913 if (left)
6766e5d1
JS
2914 {
2915 DrawLine(dc, x1, y3, x3, y1, transpose);
2916 DrawLine(dc, x3+1-c, y1+1, x2-1, y3, transpose);
2917 }
2918 else
2919 {
2920 DrawLine(dc, x1, y1, x2, y1, transpose);
2921 }
2922 DrawLine(dc, x1, y3, x1, y4, transpose);
00e086a7 2923 if (right)
1e6feb95 2924 {
6766e5d1
JS
2925 DrawLine(dc, x1, y4, x3+c, y2+c, transpose);
2926 }
2927
2928 if (flags & wxCONTROL_PRESSED) {
1e6feb95
VZ
2929 // TODO: MSW fills the entire area inside, not just the rect
2930 wxRect rectInt = rect;
00e086a7 2931 if ( transpose )
6766e5d1
JS
2932 {
2933 rectInt.SetLeft(y3);
2934 rectInt.SetRight(y4);
2935 }
1e6feb95 2936 else
6766e5d1
JS
2937 {
2938 rectInt.SetTop(y3);
2939 rectInt.SetBottom(y4);
2940 }
1e6feb95
VZ
2941 rectInt.Deflate(2);
2942
63f06c22 2943#if !defined(__WXMGL__)
1e6feb95
VZ
2944 static const char *stipple_xpm[] = {
2945 /* columns rows colors chars-per-pixel */
2946 "2 2 2 1",
2947 " c None",
2948 "w c white",
2949 /* pixels */
2950 "w ",
2951 " w",
2952 };
63f06c22
VS
2953#else
2954 // VS: MGL can only do 8x8 stipple brushes
2955 static const char *stipple_xpm[] = {
2956 /* columns rows colors chars-per-pixel */
2957 "8 8 2 1",
2958 " c None",
2959 "w c white",
2960 /* pixels */
2961 "w w w w ",
2962 " w w w w",
2963 "w w w w ",
2964 " w w w w",
2965 "w w w w ",
2966 " w w w w",
2967 "w w w w ",
2968 " w w w w",
2969 };
2970#endif
1e6feb95
VZ
2971 dc.SetBrush(wxBrush(stipple_xpm));
2972
2973 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
2974 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
2975 dc.SetPen(*wxTRANSPARENT_PEN);
2976 dc.DrawRectangle(rectInt);
2977 }
2978}
2979
2980void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
2981 const wxRect& rect,
6766e5d1 2982 int lenThumb,
1e6feb95
VZ
2983 wxOrientation orient,
2984 int start,
2985 int end,
2986 int step,
61fef19b 2987 int WXUNUSED(flags),
6766e5d1 2988 long style)
1e6feb95 2989{
6766e5d1
JS
2990 /* show ticks geometry
2991
2992 left right
2993 ticks shaft ticks
2994 ---- XX ---- <-- x1
2995 ---- XX ----
2996 ---- XX ----
2997 ---- XX ---- <-- x2
2998
2999 ^ ^ ^ ^
3000 | | | |
3001 y3 y1 y2 y4
3002 */
1e6feb95 3003
6766e5d1
JS
3004 // empty slider?
3005 if (end == start) return;
3006
3007 bool transpose = (orient == wxVERTICAL);
3008 bool left = ((style & wxSL_AUTOTICKS) != 0) &
3009 (((style & wxSL_TOP) != 0) & !transpose |
3010 ((style & wxSL_LEFT) != 0) & transpose |
3011 ((style & wxSL_BOTH) != 0));
3012 bool right = ((style & wxSL_AUTOTICKS) != 0) &
3013 (((style & wxSL_BOTTOM) != 0) & !transpose |
3014 ((style & wxSL_RIGHT) != 0) & transpose |
3015 ((style & wxSL_BOTH) != 0));
3016
3017 // default thumb size
3018 wxSize sizeThumb = GetSliderThumbSize (rect, 0, orient);
3019 wxCoord defaultLen = (transpose ? sizeThumb.x : sizeThumb.y);
3020
3021 // normal thumb size
3022 sizeThumb = GetSliderThumbSize (rect, lenThumb, orient);
3023 wxCoord widthThumb = (transpose ? sizeThumb.y : sizeThumb.x);
3024
3025 wxRect rectShaft = GetSliderShaftRect (rect, lenThumb, orient, style);
3026
3027 wxCoord x1, x2, y1, y2, y3, y4 , len;
3028 x1 = (transpose ? rectShaft.y : rectShaft.x) + widthThumb/2;
3029 x2 = (transpose ? rectShaft.GetBottom() : rectShaft.GetRight()) - widthThumb/2;
3030 y1 = (transpose ? rectShaft.x : rectShaft.y) - defaultLen/2;
3031 y2 = (transpose ? rectShaft.GetRight() : rectShaft.GetBottom()) + defaultLen/2;
3032 y3 = (transpose ? rect.x : rect.y);
3033 y4 = (transpose ? rect.GetRight() : rect.GetBottom());
3034 len = x2 - x1;
1e6feb95
VZ
3035
3036 dc.SetPen(m_penBlack);
3037
3038 int range = end - start;
6766e5d1 3039 for ( int n = 0; n < range; n += step ) {
1e6feb95
VZ
3040 wxCoord x = x1 + (len*n) / range;
3041
6766e5d1
JS
3042 if (left & (y1 > y3)) {
3043 DrawLine(dc, x, y1, x, y3, orient == wxVERTICAL);
3044 }
3045 if (right & (y4 > y2)) {
3046 DrawLine(dc, x, y2, x, y4, orient == wxVERTICAL);
3047 }
1e6feb95 3048 }
1e6feb95 3049 // always draw the line at the end position
6766e5d1
JS
3050 if (left & (y1 > y3)) {
3051 DrawLine(dc, x2, y1, x2, y3, orient == wxVERTICAL);
3052 }
3053 if (right & (y4 > y2)) {
3054 DrawLine(dc, x2, y2, x2, y4, orient == wxVERTICAL);
3055 }
1e6feb95
VZ
3056}
3057
3058// ----------------------------------------------------------------------------
3059// menu and menubar
3060// ----------------------------------------------------------------------------
3061
3062// wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
3063class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo
3064{
3065public:
3066 virtual wxSize GetSize() const { return m_size; }
3067
3068 wxCoord GetLabelOffset() const { return m_ofsLabel; }
3069 wxCoord GetAccelOffset() const { return m_ofsAccel; }
3070
3071 wxCoord GetItemHeight() const { return m_heightItem; }
3072
3073private:
3074 // the total size of the menu
3075 wxSize m_size;
3076
3077 // the offset of the start of the menu item label
3078 wxCoord m_ofsLabel;
3079
3080 // the offset of the start of the accel label
3081 wxCoord m_ofsAccel;
3082
3083 // the height of a normal (not separator) item
3084 wxCoord m_heightItem;
3085
71e03035
VZ
3086 friend wxMenuGeometryInfo *
3087 wxWin32Renderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
1e6feb95
VZ
3088};
3089
3090// FIXME: all constants are hardcoded but shouldn't be
3091static const wxCoord MENU_LEFT_MARGIN = 9;
3092static const wxCoord MENU_RIGHT_MARGIN = 18;
3093static const wxCoord MENU_VERT_MARGIN = 3;
3094
3095// the margin around bitmap/check marks (on each side)
3096static const wxCoord MENU_BMP_MARGIN = 2;
3097
3098// the margin between the labels and accel strings
3099static const wxCoord MENU_ACCEL_MARGIN = 8;
3100
3101// the separator height in pixels: in fact, strangely enough, the real height
3102// is 2 but Windows adds one extra pixel in the bottom margin, so take it into
3103// account here
3104static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
3105
3106// the size of the standard checkmark bitmap
3107static const wxCoord MENU_CHECK_SIZE = 9;
3108
3109void wxWin32Renderer::DrawMenuBarItem(wxDC& dc,
3110 const wxRect& rectOrig,
3111 const wxString& label,
3112 int flags,
3113 int indexAccel)
3114{
3115 wxRect rect = rectOrig;
3116 rect.height--;
3117
3118 wxDCTextColourChanger colChanger(dc);
3119
3120 if ( flags & wxCONTROL_SELECTED )
3121 {
3122 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
3123
3124 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
3125 dc.SetBrush(wxBrush(colBg, wxSOLID));
3126 dc.SetPen(wxPen(colBg, 0, wxSOLID));
3127 dc.DrawRectangle(rect);
3128 }
3129
3130 // don't draw the focus rect around menu bar items
3131 DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
3132 wxALIGN_CENTRE, indexAccel);
3133}
3134
3135void wxWin32Renderer::DrawMenuItem(wxDC& dc,
3136 wxCoord y,
3137 const wxMenuGeometryInfo& gi,
3138 const wxString& label,
3139 const wxString& accel,
3140 const wxBitmap& bitmap,
3141 int flags,
3142 int indexAccel)
3143{
3144 const wxWin32MenuGeometryInfo& geometryInfo =
3145 (const wxWin32MenuGeometryInfo&)gi;
3146
3147 wxRect rect;
3148 rect.x = 0;
3149 rect.y = y;
3150 rect.width = geometryInfo.GetSize().x;
3151 rect.height = geometryInfo.GetItemHeight();
3152
3153 // draw the selected item specially
3154 wxDCTextColourChanger colChanger(dc);
3155 if ( flags & wxCONTROL_SELECTED )
3156 {
3157 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
3158
3159 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
3160 dc.SetBrush(wxBrush(colBg, wxSOLID));
3161 dc.SetPen(wxPen(colBg, 0, wxSOLID));
3162 dc.DrawRectangle(rect);
3163 }
3164
3165 // draw the bitmap: use the bitmap provided or the standard checkmark for
3166 // the checkable items
3167 wxBitmap bmp = bitmap;
3168 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKED) )
3169 {
3170 bmp = GetIndicator(IndicatorType_Menu, flags);
3171 }
3172
3173 if ( bmp.Ok() )
3174 {
3175 rect.SetRight(geometryInfo.GetLabelOffset());
3176 wxControlRenderer::DrawBitmap(dc, bmp, rect);
3177 }
3178
3179 // draw the label
3180 rect.x = geometryInfo.GetLabelOffset();
3181 rect.SetRight(geometryInfo.GetAccelOffset());
3182
3183 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
3184
3185 // draw the accel string
3186 rect.x = geometryInfo.GetAccelOffset();
3187 rect.SetRight(geometryInfo.GetSize().x);
3188
3189 // NB: no accel index here
3190 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
3191
3192 // draw the submenu indicator
3193 if ( flags & wxCONTROL_ISSUBMENU )
3194 {
3195 rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
3196 rect.width = MENU_RIGHT_MARGIN;
3197
3198 wxArrowStyle arrowStyle;
3199 if ( flags & wxCONTROL_DISABLED )
d6922577 3200 arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InvertedDisabled
1e6feb95
VZ
3201 : Arrow_Disabled;
3202 else if ( flags & wxCONTROL_SELECTED )
d6922577 3203 arrowStyle = Arrow_Inverted;
1e6feb95
VZ
3204 else
3205 arrowStyle = Arrow_Normal;
3206
3207 DrawArrow(dc, rect, Arrow_Right, arrowStyle);
3208 }
3209}
3210
3211void wxWin32Renderer::DrawMenuSeparator(wxDC& dc,
3212 wxCoord y,
3213 const wxMenuGeometryInfo& geomInfo)
3214{
3215 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
3216}
3217
3218wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& sizeText) const
3219{
3220 wxSize size = sizeText;
3221
3222 // FIXME: menubar height is configurable under Windows
3223 size.x += 12;
3224 size.y += 6;
3225
3226 return size;
3227}
3228
3229wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win,
3230 const wxMenu& menu) const
3231{
3232 // prepare the dc: for now we draw all the items with the system font
3233 wxClientDC dc(win);
a756f210 3234 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
1e6feb95
VZ
3235
3236 // the height of a normal item
3237 wxCoord heightText = dc.GetCharHeight();
3238
3239 // the total height
3240 wxCoord height = 0;
3241
3242 // the max length of label and accel strings: the menu width is the sum of
3243 // them, even if they're for different items (as the accels should be
3244 // aligned)
3245 //
3246 // the max length of the bitmap is never 0 as Windows always leaves enough
3247 // space for a check mark indicator
3248 wxCoord widthLabelMax = 0,
3249 widthAccelMax = 0,
3250 widthBmpMax = MENU_LEFT_MARGIN;
3251
ac32ba44 3252 for ( wxMenuItemList::compatibility_iterator node = menu.GetMenuItems().GetFirst();
1e6feb95
VZ
3253 node;
3254 node = node->GetNext() )
3255 {
3256 // height of this item
3257 wxCoord h;
3258
3259 wxMenuItem *item = node->GetData();
3260 if ( item->IsSeparator() )
3261 {
3262 h = MENU_SEPARATOR_HEIGHT;
3263 }
3264 else // not separator
3265 {
3266 h = heightText;
3267
3268 wxCoord widthLabel;
3269 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
3270 if ( widthLabel > widthLabelMax )
3271 {
3272 widthLabelMax = widthLabel;
3273 }
3274
3275 wxCoord widthAccel;
3276 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
3277 if ( widthAccel > widthAccelMax )
3278 {
3279 widthAccelMax = widthAccel;
3280 }
3281
3282 const wxBitmap& bmp = item->GetBitmap();
3283 if ( bmp.Ok() )
3284 {
3285 wxCoord widthBmp = bmp.GetWidth();
3286 if ( widthBmp > widthBmpMax )
3287 widthBmpMax = widthBmp;
3288 }
3289 //else if ( item->IsCheckable() ): no need to check for this as
3290 // MENU_LEFT_MARGIN is big enough to show the check mark
3291 }
3292
3293 h += 2*MENU_VERT_MARGIN;
3294
3295 // remember the item position and height
3296 item->SetGeometry(height, h);
3297
3298 height += h;
3299 }
3300
3301 // bundle the metrics into a struct and return it
3302 wxWin32MenuGeometryInfo *gi = new wxWin32MenuGeometryInfo;
3303
3304 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
3305 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
3306 if ( widthAccelMax > 0 )
3307 {
3308 // if we actually have any accesl, add a margin
3309 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
3310 }
3311
3312 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
3313
3314 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
3315 gi->m_size.y = height;
3316
3317 return gi;
3318}
3319
71e03035
VZ
3320// ----------------------------------------------------------------------------
3321// status bar
3322// ----------------------------------------------------------------------------
3379ed37 3323
71e03035
VZ
3324static const wxCoord STATBAR_BORDER_X = 2;
3325static const wxCoord STATBAR_BORDER_Y = 2;
3379ed37 3326
71e03035 3327wxSize wxWin32Renderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const
3379ed37 3328{
71e03035
VZ
3329 if ( borderBetweenFields )
3330 *borderBetweenFields = 2;
3379ed37 3331
71e03035 3332 return wxSize(STATBAR_BORDER_X, STATBAR_BORDER_Y);
3379ed37
VZ
3333}
3334
71e03035
VZ
3335void wxWin32Renderer::DrawStatusField(wxDC& dc,
3336 const wxRect& rect,
3337 const wxString& label,
c2919ab3 3338 int flags, int style /*=0*/)
3379ed37 3339{
71e03035 3340 wxRect rectIn;
3379ed37 3341
71e03035
VZ
3342 if ( flags & wxCONTROL_ISDEFAULT )
3343 {
3344 // draw the size grip: it is a normal rect except that in the lower
3345 // right corner we have several bands which may be used for dragging
3346 // the status bar corner
3347 //
3348 // each band consists of 4 stripes: m_penHighlight, double
3349 // m_penDarkGrey and transparent one
3350 wxCoord x2 = rect.GetRight(),
3351 y2 = rect.GetBottom();
3379ed37 3352
71e03035 3353 // draw the upper left part of the rect normally
c2919ab3
VZ
3354 if (style != wxSB_FLAT)
3355 {
3356 if (style == wxSB_RAISED)
3357 dc.SetPen(m_penHighlight);
3358 else
3359 dc.SetPen(m_penDarkGrey);
3360 dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2);
3361 dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop());
3362 }
71e03035
VZ
3363
3364 // draw the grey stripes of the grip
3365 size_t n;
3366 wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1;
3367 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
3368 {
3369 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
3370 dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1);
3371 }
3372
3373 // draw the white stripes
3374 dc.SetPen(m_penHighlight);
3375 ofs = WIDTH_STATUSBAR_GRIP_BAND + 1;
3376 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
3377 {
3378 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
3379 }
3380
3381 // draw the remaining rect boundaries
c2919ab3
VZ
3382 if (style != wxSB_FLAT)
3383 {
3384 if (style == wxSB_RAISED)
3385 dc.SetPen(m_penDarkGrey);
3386 else
3387 dc.SetPen(m_penHighlight);
3388 ofs -= WIDTH_STATUSBAR_GRIP_BAND;
3389 dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1);
3390 dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2);
3391 }
71e03035
VZ
3392
3393 rectIn = rect;
3394 rectIn.Deflate(1);
3395
3396 rectIn.width -= STATUSBAR_GRIP_SIZE;
3397 }
3398 else // normal pane
3399 {
c2919ab3
VZ
3400 if (style == wxSB_RAISED)
3401 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
3402 else if (style != wxSB_FLAT)
3403 DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
71e03035
VZ
3404 }
3405
3406 rectIn.Deflate(STATBAR_BORDER_X, STATBAR_BORDER_Y);
3407
3408 wxDCClipper clipper(dc, rectIn);
3409 DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3410}
3379ed37 3411
1e6feb95
VZ
3412// ----------------------------------------------------------------------------
3413// combobox
3414// ----------------------------------------------------------------------------
3415
3416void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal,
61fef19b 3417 wxBitmap * WXUNUSED(bmpFocus),
1e6feb95
VZ
3418 wxBitmap *bmpPressed,
3419 wxBitmap *bmpDisabled)
3420{
3421 static const wxCoord widthCombo = 16;
3422 static const wxCoord heightCombo = 17;
3423
3424 wxMemoryDC dcMem;
3425
3426 if ( bmpNormal )
3427 {
3428 bmpNormal->Create(widthCombo, heightCombo);
3429 dcMem.SelectObject(*bmpNormal);
3430 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3431 Arrow_Down, Arrow_Normal);
3432 }
3433
3434 if ( bmpPressed )
3435 {
3436 bmpPressed->Create(widthCombo, heightCombo);
3437 dcMem.SelectObject(*bmpPressed);
3438 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3439 Arrow_Down, Arrow_Pressed);
3440 }
3441
3442 if ( bmpDisabled )
3443 {
3444 bmpDisabled->Create(widthCombo, heightCombo);
3445 dcMem.SelectObject(*bmpDisabled);
3446 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3447 Arrow_Down, Arrow_Disabled);
3448 }
3449}
3450
3451// ----------------------------------------------------------------------------
3452// background
3453// ----------------------------------------------------------------------------
3454
3455void wxWin32Renderer::DoDrawBackground(wxDC& dc,
3456 const wxColour& col,
193e19cf 3457 const wxRect& rect,
61fef19b 3458 wxWindow * WXUNUSED(window))
1e6feb95
VZ
3459{
3460 wxBrush brush(col, wxSOLID);
3461 dc.SetBrush(brush);
3462 dc.SetPen(*wxTRANSPARENT_PEN);
3463 dc.DrawRectangle(rect);
3464}
3465
3466void wxWin32Renderer::DrawBackground(wxDC& dc,
3467 const wxColour& col,
3468 const wxRect& rect,
61fef19b
VZ
3469 int WXUNUSED(flags),
3470 wxWindow *window)
1e6feb95
VZ
3471{
3472 // just fill it with the given or default bg colour
3473 wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL);
193e19cf 3474 DoDrawBackground(dc, colBg, rect, window );
1e6feb95
VZ
3475}
3476
3477// ----------------------------------------------------------------------------
3478// scrollbar
3479// ----------------------------------------------------------------------------
3480
3481void wxWin32Renderer::DrawArrow(wxDC& dc,
3482 wxDirection dir,
3483 const wxRect& rect,
3484 int flags)
3485{
3486 // get the bitmap for this arrow
3487 wxArrowDirection arrowDir;
3488 switch ( dir )
3489 {
3490 case wxLEFT: arrowDir = Arrow_Left; break;
3491 case wxRIGHT: arrowDir = Arrow_Right; break;
3492 case wxUP: arrowDir = Arrow_Up; break;
3493 case wxDOWN: arrowDir = Arrow_Down; break;
3494
3495 default:
3496 wxFAIL_MSG(_T("unknown arrow direction"));
3497 return;
3498 }
3499
3500 wxArrowStyle arrowStyle;
3501 if ( flags & wxCONTROL_PRESSED )
3502 {
3503 // can't be pressed and disabled
3504 arrowStyle = Arrow_Pressed;
3505 }
3506 else
3507 {
3508 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
3509 }
3510
3511 DrawArrowButton(dc, rect, arrowDir, arrowStyle);
3512}
3513
3514void wxWin32Renderer::DrawArrow(wxDC& dc,
3515 const wxRect& rect,
3516 wxArrowDirection arrowDir,
3517 wxArrowStyle arrowStyle)
3518{
3519 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
3520
3521 // under Windows the arrows always have the same size so just centre it in
3522 // the provided rectangle
3523 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
3524 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
3525
3526 // Windows does it like this...
3527 if ( arrowDir == Arrow_Left )
3528 x--;
3529
3530 // draw it
a290fa5a 3531 dc.DrawBitmap(bmp, x, y, true /* use mask */);
1e6feb95
VZ
3532}
3533
3534void wxWin32Renderer::DrawArrowButton(wxDC& dc,
3535 const wxRect& rectAll,
3536 wxArrowDirection arrowDir,
3537 wxArrowStyle arrowStyle)
3538{
3539 wxRect rect = rectAll;
3540 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3541 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
3542 DrawArrow(dc, rect, arrowDir, arrowStyle);
3543}
3544
3545void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
61fef19b 3546 wxOrientation WXUNUSED(orient),
1e6feb95 3547 const wxRect& rect,
61fef19b 3548 int WXUNUSED(flags))
1e6feb95
VZ
3549{
3550 // we don't use the flags, the thumb never changes appearance
3551 wxRect rectThumb = rect;
3552 DrawArrowBorder(dc, &rectThumb);
3553 DrawBackground(dc, wxNullColour, rectThumb);
3554}
3555
3556void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
61fef19b 3557 wxOrientation WXUNUSED(orient),
1e6feb95
VZ
3558 const wxRect& rectBar,
3559 int flags)
3560{
3561 wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
3562 ? wxColourScheme::SCROLLBAR_PRESSED
3563 : wxColourScheme::SCROLLBAR;
3564 DoDrawBackground(dc, m_scheme->Get(col), rectBar);
3565}
3566
3567void wxWin32Renderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
3568{
3569 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3570}
3571
3572wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar,
3573 wxScrollBar::Element elem,
3574 int thumbPos) const
3575{
3576 return StandardGetScrollbarRect(scrollbar, elem,
3577 thumbPos, m_sizeScrollbarArrow);
3578}
3579
3580wxCoord wxWin32Renderer::GetScrollbarSize(const wxScrollBar *scrollbar)
3581{
3582 return StandardScrollBarSize(scrollbar, m_sizeScrollbarArrow);
3583}
3584
3585wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
3586 const wxPoint& pt) const
3587{
3588 return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow);
3589}
3590
3591wxCoord wxWin32Renderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
3592 int thumbPos)
3593{
3594 return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow);
3595}
3596
3597int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar,
3598 wxCoord coord)
3599{
3600 return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow);
3601}
3602
24a23c35
VS
3603// ----------------------------------------------------------------------------
3604// top level windows
3605// ----------------------------------------------------------------------------
3606
813edf09
VS
3607int wxWin32Renderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
3608{
3609 wxRect client = GetFrameClientArea(rect, flags);
71e03035 3610
813edf09
VS
3611 if ( client.Inside(pt) )
3612 return wxHT_TOPLEVEL_CLIENT_AREA;
71e03035 3613
813edf09
VS
3614 if ( flags & wxTOPLEVEL_TITLEBAR )
3615 {
3616 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3617
3618 if ( flags & wxTOPLEVEL_ICON )
3619 {
3620 if ( wxRect(client.GetPosition(), GetFrameIconSize()).Inside(pt) )
3621 return wxHT_TOPLEVEL_ICON;
3622 }
71e03035 3623
813edf09
VS
3624 wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
3625 client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
3626 FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
71e03035 3627
813edf09
VS
3628 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3629 {
3630 if ( btnRect.Inside(pt) )
3631 return wxHT_TOPLEVEL_BUTTON_CLOSE;
3632 btnRect.x -= FRAME_BUTTON_WIDTH + 2;
3633 }
3634 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3635 {
3636 if ( btnRect.Inside(pt) )
3637 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
3638 btnRect.x -= FRAME_BUTTON_WIDTH;
3639 }
3640 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3641 {
3642 if ( btnRect.Inside(pt) )
3643 return wxHT_TOPLEVEL_BUTTON_RESTORE;
3644 btnRect.x -= FRAME_BUTTON_WIDTH;
3645 }
3646 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3647 {
3648 if ( btnRect.Inside(pt) )
3649 return wxHT_TOPLEVEL_BUTTON_ICONIZE;
3650 btnRect.x -= FRAME_BUTTON_WIDTH;
3651 }
3652 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3653 {
3654 if ( btnRect.Inside(pt) )
3655 return wxHT_TOPLEVEL_BUTTON_HELP;
3656 btnRect.x -= FRAME_BUTTON_WIDTH;
3657 }
3658
b22d16ad 3659 if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
813edf09
VS
3660 return wxHT_TOPLEVEL_TITLEBAR;
3661 }
3662
3663 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3664 {
3665 // we are certainly at one of borders, lets decide which one:
71e03035 3666
813edf09
VS
3667 int border = 0;
3668 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
b22d16ad 3669 if ( pt.x < client.x )
813edf09 3670 border |= wxHT_TOPLEVEL_BORDER_W;
b22d16ad 3671 else if ( pt.x >= client.width + client.x )
813edf09 3672 border |= wxHT_TOPLEVEL_BORDER_E;
b22d16ad 3673 if ( pt.y < client.y )
813edf09 3674 border |= wxHT_TOPLEVEL_BORDER_N;
b22d16ad 3675 else if ( pt.y >= client.height + client.y )
813edf09
VS
3676 border |= wxHT_TOPLEVEL_BORDER_S;
3677 return border;
3678 }
71e03035 3679
813edf09
VS
3680 return wxHT_NOWHERE;
3681}
3682
24a23c35
VS
3683void wxWin32Renderer::DrawFrameTitleBar(wxDC& dc,
3684 const wxRect& rect,
3685 const wxString& title,
3686 const wxIcon& icon,
3687 int flags,
813edf09
VS
3688 int specialButton,
3689 int specialButtonFlags)
24a23c35
VS
3690{
3691 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3692 {
3693 DrawFrameBorder(dc, rect, flags);
3694 }
3695 if ( flags & wxTOPLEVEL_TITLEBAR )
3696 {
3697 DrawFrameBackground(dc, rect, flags);
3698 if ( flags & wxTOPLEVEL_ICON )
3699 DrawFrameIcon(dc, rect, icon, flags);
3700 DrawFrameTitle(dc, rect, title, flags);
71e03035 3701
24a23c35
VS
3702 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3703 wxCoord x,y;
813edf09 3704 x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
24a23c35 3705 y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
71e03035 3706
813edf09 3707 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
24a23c35 3708 {
813edf09
VS
3709 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
3710 (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
3711 specialButtonFlags : 0);
24a23c35
VS
3712 x -= FRAME_BUTTON_WIDTH + 2;
3713 }
813edf09 3714 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
24a23c35 3715 {
813edf09
VS
3716 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
3717 (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
3718 specialButtonFlags : 0);
24a23c35
VS
3719 x -= FRAME_BUTTON_WIDTH;
3720 }
813edf09 3721 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
24a23c35 3722 {
813edf09
VS
3723 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
3724 (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
3725 specialButtonFlags : 0);
24a23c35
VS
3726 x -= FRAME_BUTTON_WIDTH;
3727 }
813edf09 3728 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
24a23c35 3729 {
813edf09
VS
3730 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
3731 (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
3732 specialButtonFlags : 0);
24a23c35
VS
3733 x -= FRAME_BUTTON_WIDTH;
3734 }
813edf09 3735 if ( flags & wxTOPLEVEL_BUTTON_HELP )
24a23c35 3736 {
813edf09
VS
3737 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
3738 (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
3739 specialButtonFlags : 0);
24a23c35
VS
3740 }
3741 }
3742}
3743
3744void wxWin32Renderer::DrawFrameBorder(wxDC& dc,
3745 const wxRect& rect,
3746 int flags)
3747{
3748 if ( !(flags & wxTOPLEVEL_BORDER) ) return;
71e03035 3749
24a23c35 3750 wxRect r(rect);
71e03035 3751
24a23c35
VS
3752 DrawShadedRect(dc, &r, m_penLightGrey, m_penBlack);
3753 DrawShadedRect(dc, &r, m_penHighlight, m_penDarkGrey);
3754 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3755 if ( flags & wxTOPLEVEL_RESIZEABLE )
3756 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3757}
3758
3759void wxWin32Renderer::DrawFrameBackground(wxDC& dc,
3760 const wxRect& rect,
3761 int flags)
3762{
3763 if ( !(flags & wxTOPLEVEL_TITLEBAR) ) return;
3764
71e03035 3765 wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
24a23c35
VS
3766 wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE) :
3767 wxSCHEME_COLOUR(m_scheme, TITLEBAR);
3768
3769 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3770 r.height = FRAME_TITLEBAR_HEIGHT;
71e03035 3771
24a23c35
VS
3772 DrawBackground(dc, col, r);
3773}
3774
3775void wxWin32Renderer::DrawFrameTitle(wxDC& dc,
3776 const wxRect& rect,
3777 const wxString& title,
3778 int flags)
3779{
6296744f
VS
3780 wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
3781 wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE_TEXT) :
3782 wxSCHEME_COLOUR(m_scheme, TITLEBAR_TEXT);
3783
24a23c35
VS
3784 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3785 r.height = FRAME_TITLEBAR_HEIGHT;
3786 if ( flags & wxTOPLEVEL_ICON )
e7dda1ff 3787 {
24a23c35 3788 r.x += FRAME_TITLEBAR_HEIGHT;
e7dda1ff
VS
3789 r.width -= FRAME_TITLEBAR_HEIGHT + 2;
3790 }
24a23c35 3791 else
e7dda1ff 3792 {
24a23c35 3793 r.x += 1;
e7dda1ff
VS
3794 r.width -= 3;
3795 }
3796
3797 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3798 r.width -= FRAME_BUTTON_WIDTH + 2;
3799 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3800 r.width -= FRAME_BUTTON_WIDTH;
3801 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3802 r.width -= FRAME_BUTTON_WIDTH;
3803 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3804 r.width -= FRAME_BUTTON_WIDTH;
3805 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3806 r.width -= FRAME_BUTTON_WIDTH;
71e03035 3807
24a23c35 3808 dc.SetFont(m_titlebarFont);
6296744f 3809 dc.SetTextForeground(col);
d1504049 3810
e7dda1ff
VS
3811 wxCoord textW;
3812 dc.GetTextExtent(title, &textW, NULL);
3813 if ( textW > r.width )
3814 {
3815 // text is too big, let's shorten it and add "..." after it:
3816 size_t len = title.length();
3817 wxCoord WSoFar, letterW;
3818
3819 dc.GetTextExtent(wxT("..."), &WSoFar, NULL);
3820 if ( WSoFar > r.width )
3821 {
3822 // not enough space to draw anything
3823 return;
3824 }
3825
3826 wxString s;
3827 s.Alloc(len);
3828 for (size_t i = 0; i < len; i++)
3829 {
3830 dc.GetTextExtent(title[i], &letterW, NULL);
3831 if ( letterW + WSoFar > r.width )
3832 break;
3833 WSoFar += letterW;
3834 s << title[i];
3835 }
3836 s << wxT("...");
d1504049 3837 dc.DrawLabel(s, wxNullBitmap, r,
e7dda1ff
VS
3838 wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3839 }
3840 else
d1504049 3841 dc.DrawLabel(title, wxNullBitmap, r,
e7dda1ff 3842 wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
24a23c35
VS
3843}
3844
3845void wxWin32Renderer::DrawFrameIcon(wxDC& dc,
3846 const wxRect& rect,
3847 const wxIcon& icon,
3848 int flags)
3849{
3deeefeb
VS
3850 if ( icon.Ok() )
3851 {
3852 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3853 dc.DrawIcon(icon, r.x, r.y);
3854 }
24a23c35
VS
3855}
3856
3857void wxWin32Renderer::DrawFrameButton(wxDC& dc,
3858 wxCoord x, wxCoord y,
3859 int button,
2e9f62da 3860 int flags)
24a23c35
VS
3861{
3862 wxRect r(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
813edf09 3863
24a23c35
VS
3864 size_t idx = 0;
3865 switch (button)
3866 {
813edf09
VS
3867 case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
3868 case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
3869 case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
3870 case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
3871 case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
24a23c35
VS
3872 default:
3873 wxFAIL_MSG(wxT("incorrect button specification"));
3874 }
71e03035
VZ
3875
3876 if ( flags & wxCONTROL_PRESSED )
813edf09
VS
3877 {
3878 DrawShadedRect(dc, &r, m_penBlack, m_penHighlight);
3879 DrawShadedRect(dc, &r, m_penDarkGrey, m_penLightGrey);
3880 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
a290fa5a 3881 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x+1, r.y+1, true);
813edf09
VS
3882 }
3883 else
3884 {
3885 DrawShadedRect(dc, &r, m_penHighlight, m_penBlack);
3886 DrawShadedRect(dc, &r, m_penLightGrey, m_penDarkGrey);
3887 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
a290fa5a 3888 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x, r.y, true);
813edf09 3889 }
24a23c35
VS
3890}
3891
3892
3893wxRect wxWin32Renderer::GetFrameClientArea(const wxRect& rect,
3894 int flags) const
3895{
3896 wxRect r(rect);
3897
3898 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3899 {
71e03035 3900 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
24a23c35
VS
3901 RESIZEABLE_FRAME_BORDER_THICKNESS :
3902 FRAME_BORDER_THICKNESS;
3903 r.Inflate(-border);
3904 }
3905 if ( flags & wxTOPLEVEL_TITLEBAR )
3906 {
3907 r.y += FRAME_TITLEBAR_HEIGHT;
3908 r.height -= FRAME_TITLEBAR_HEIGHT;
3909 }
3910
3911 return r;
3912}
3913
3914wxSize wxWin32Renderer::GetFrameTotalSize(const wxSize& clientSize,
3915 int flags) const
3916{
3917 wxSize s(clientSize);
3918
3919 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3920 {
71e03035 3921 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
24a23c35
VS
3922 RESIZEABLE_FRAME_BORDER_THICKNESS :
3923 FRAME_BORDER_THICKNESS;
3924 s.x += 2*border;
3925 s.y += 2*border;
3926 }
3927 if ( flags & wxTOPLEVEL_TITLEBAR )
3928 s.y += FRAME_TITLEBAR_HEIGHT;
3929
3930 return s;
3931}
3932
e7dda1ff
VS
3933wxSize wxWin32Renderer::GetFrameMinSize(int flags) const
3934{
8b5d5223 3935 wxSize s;
e7dda1ff
VS
3936
3937 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3938 {
3939 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3940 RESIZEABLE_FRAME_BORDER_THICKNESS :
3941 FRAME_BORDER_THICKNESS;
3942 s.x += 2*border;
3943 s.y += 2*border;
3944 }
3945
3946 if ( flags & wxTOPLEVEL_TITLEBAR )
3947 {
3948 s.y += FRAME_TITLEBAR_HEIGHT;
3949
3950 if ( flags & wxTOPLEVEL_ICON )
3951 s.x += FRAME_TITLEBAR_HEIGHT + 2;
3952 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3953 s.x += FRAME_BUTTON_WIDTH + 2;
3954 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3955 s.x += FRAME_BUTTON_WIDTH;
3956 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3957 s.x += FRAME_BUTTON_WIDTH;
3958 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3959 s.x += FRAME_BUTTON_WIDTH;
3960 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3961 s.x += FRAME_BUTTON_WIDTH;
3962 }
3963
3964 return s;
3965}
3966
24a23c35
VS
3967wxSize wxWin32Renderer::GetFrameIconSize() const
3968{
3969 return wxSize(16, 16);
3970}
3971
3972
63f06c22
VS
3973// ----------------------------------------------------------------------------
3974// standard icons
3975// ----------------------------------------------------------------------------
3976
13b22a67 3977/* Copyright (c) Julian Smart */
63f06c22 3978static char *error_xpm[]={
13b22a67
JS
3979/* columns rows colors chars-per-pixel */
3980"32 32 70 1",
3981"- c #BF0101",
3982"b c #361F1F",
3983"& c #C08484",
3984"X c #BF3333",
3985"# c #C08181",
3986"% c #C01111",
3987"d c #C51515",
3988"s c #551818",
3989"O c #C07E7E",
3990": c #C00E0E",
3991"u c #E28A8A",
3992"2 c #C81F1F",
3993"8 c #FFFFFF",
3994"p c #E59494",
3995"< c #BB0101",
3996"y c #DA6A6A",
3997"A c #4C4C4C",
3998"9 c #F7DFDF",
3999"@ c #BF5353",
4000"w c #FAE9E9",
4001"F c #272727",
4002"5 c #D24A4A",
4003". c #C06363",
4004"n c #BF8282",
4005"7 c #F2C9C9",
4006"t c #C09292",
4007"M c #3E3E3E",
4008"x c #4D4D4D",
4009"4 c #CA2A2A",
4010"h c #E79F9F",
4011"* c #C05454",
4012"D c #711212",
4013"V c #737373",
4014"$ c #BF3232",
4015"N c #900B0B",
4016"6 c #BD0303",
4017"3 c #DF7F7F",
4018"K c #6F1212",
4019"C c #BD0000",
4020"m c #950909",
4021"P c #8A8A8A",
4022"j c #D75F5F",
4023" c None",
4024"e c #F4D4D4",
4025"S c #BF2020",
4026"L c #747474",
4027"G c #842C2C",
4028"c c #ECB4B4",
4029"l c #2E2121",
4030"g c #BF7E7E",
4031"k c #9B0808",
4032"= c #BF0505",
4033"a c #B10303",
4034"q c #7E2020",
4035"1 c #642222",
4036"J c #676767",
4037"B c #322020",
4038"; c #C00303",
4039"i c #242424",
4040"o c #C00000",
4041"> c #BF1F1F",
4042", c #842B2B",
4043"f c #701212",
4044"0 c #BE0000",
4045"r c #960909",
4046"H c #686868",
4047"v c #BC0000",
4048"Z c #671414",
4049"+ c #C02020",
4050"z c #CD3535",
4051/* pixels */
4052" ",
4053" ",
4054" .XoooOO ",
4055" .+ooooooooo@# ",
4056" $oooooooooooo%& ",
4057" *=-ooooooooooooo;: ",
4058" *oooooooooooooooooo> ",
4059" =ooooooooooooooooooo, ",
4060" $-ooooooooooooooooooo<1 ",
4061" .oooooo2334ooo533oooooo6 ",
4062" +ooooooo789oo2883oooooo0q ",
4063" oooooooo2w83o78eoooooooor ",
4064" toooooooooy88u884oooooooori ",
4065" Xooooooooooe888poooooooooas ",
4066" ooooooooooo4889doooooooooof ",
4067" ooooooooooo588w2oooooooooofi ",
4068" oooooooooodw8887oooooooooofi ",
4069" goooooooooh8w588jooooooookli ",
4070" tooooooooz885op8wdooooooorix ",
4071" oooooood98cood98cooooooori ",
4072" @oooooop8w2ooo5885ooooovbi ",
4073" n%ooooooooooooooooooooomiM ",
4074" &;oooooooooooooooooooNBiV ",
4075" :ooooooooooooooooooCZiA ",
4076" nSooooooooooooooooCDiF ",
4077" nG<oooooooooooooNZiiH ",
4078" 160ooooooooovmBiFH ",
4079" nqrraoookrrbiiA ",
4080" nJisKKKliiiML ",
4081" nPiiix ",
4082" ",
4083" "
4084};
63f06c22 4085
13b22a67 4086/* Copyright (c) Julian Smart */
63f06c22 4087static char *info_xpm[]={
13b22a67
JS
4088/* columns rows colors chars-per-pixel */
4089"32 32 17 1",
4090"* c #A1A3FB",
4091"X c #FFFFFF",
4092"O c #191EF4",
4093"= c #777AF9",
4094": c #4D51F7",
4095" c None",
4096"- c #2328F5",
4097"+ c #4247F6",
4098"; c #C1C2FC",
4099". c #C0C0C0",
4100"& c #E0E1FE",
4101"% c #242424",
4102"> c #2D32F5",
4103"o c #CBCCFD",
4104"# c #0309F3",
4105"@ c #8C8FFA",
4106"$ c #EAEBFE",
4107/* pixels */
4108" ....... ",
4109" ...XXXXXXX... ",
4110" ..XXXXXXXXXXXXX.. ",
4111" .XXXXXXXXXXXXXXXXX. ",
4112" .XXXXXXXXoO+XXXXXXXX. ",
4113" .XXXXXXXXX@#OXXXXXXXXX. ",
4114" .XXXXXXXXXX$@oXXXXXXXXXX. ",
4115" .XXXXXXXXXXXXXXXXXXXXXXX.% ",
4116" .XXXXXXXXX&*=-XXXXXXXXXX.%% ",
4117".XXXXXXXXXX;:#>XXXXXXXXXXX.% ",
4118".XXXXXXXXXXX;#+XXXXXXXXXXX.% ",
4119".XXXXXXXXXXX;#+XXXXXXXXXXX.%% ",
4120" .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
4121" .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
4122" .XXXXXXXXXX;#+XXXXXXXXXX.%% ",
4123" .XXXXXXXX*-##+XXXXXXXX.%%% ",
4124" .XXXXXXXXXXXXXXXXXXX.%%%% ",
4125" .XXXXXXXXXXXXXXXXX.%%%% ",
4126" ..XXXXXXXXXXXXX..%%%% ",
4127" %...XXXXXXXX..%%%%% ",
4128" %%%..XXXXXX.%%%%% ",
4129" %%%.XXXXX.%%% ",
4130" %.XXXX.%% ",
4131" .XXX.%% ",
4132" .XX.%% ",
4133" .X.%% ",
4134" ..%% ",
4135" .%% ",
4136" %% ",
4137" % ",
4138" ",
4139" "
4140};
63f06c22 4141
13b22a67 4142/* Copyright (c) Julian Smart */
63f06c22 4143static char *question_xpm[]={
13b22a67
JS
4144/* columns rows colors chars-per-pixel */
4145"32 32 16 1",
4146"O c #A3A3FF",
4147"X c #FFFFFF",
4148"% c #CACAFF",
4149"- c #4141FF",
4150"= c #6060FF",
4151"* c #2B2BFF",
4152"@ c #B5B5FF",
4153" c None",
4154"# c #1616FF",
4155"+ c #8181FF",
4156"$ c #0000FF",
4157". c #C0C0C0",
4158"; c #5555FF",
4159": c #242424",
4160"o c #E7E7FF",
4161"& c #7575FF",
4162/* pixels */
4163" ....... ",
4164" ...XXXXXXX... ",
4165" ..XXXXXXXXXXXXX.. ",
4166" .XXXXXXoO++@XXXXXX. ",
4167" .XXXXXXO#$$$$#%XXXXX. ",
4168" .XXXXXX@$$#&&#$#oXXXXX. ",
4169" .XXXXXXX*$$%XX%$$=XXXXXX. ",
4170" .XXXXXXX+-;XXXX$$-XXXXXX.: ",
4171" .XXXXXXXXXXXXX+$$&XXXXXX.:: ",
4172".XXXXXXXXXXXXo;$$*oXXXXXXX.: ",
4173".XXXXXXXXXXXo*$$*oXXXXXXXX.: ",
4174".XXXXXXXXXXX+$$*oXXXXXXXXX.:: ",
4175" .XXXXXXXXXX-$$oXXXXXXXXX.::: ",
4176" .XXXXXXXXXXX--XXXXXXXXXX.::: ",
4177" .XXXXXXXXXXXXXXXXXXXXXXX.:: ",
4178" .XXXXXXXXX-$$XXXXXXXXX.::: ",
4179" .XXXXXXXX-$$XXXXXXXX.:::: ",
4180" .XXXXXXXO++XXXXXXX.:::: ",
4181" ..XXXXXXXXXXXXX..:::: ",
4182" :...XXXXXXXX..::::: ",
4183" :::..XXXXXX.::::: ",
4184" :::.XXXXX.::: ",
4185" :.XXXX.:: ",
4186" .XXX.:: ",
4187" .XX.:: ",
4188" .X.:: ",
4189" ..:: ",
4190" .:: ",
4191" :: ",
4192" : ",
4193" ",
4194" "
4195};
63f06c22 4196
13b22a67 4197/* Copyright (c) Julian Smart */
63f06c22 4198static char *warning_xpm[]={
13b22a67
JS
4199/* columns rows colors chars-per-pixel */
4200"32 32 9 1",
4201"@ c Black",
4202"o c #A6A800",
4203"+ c #8A8C00",
4204"$ c #B8BA00",
4205" c None",
4206"O c #6E7000",
4207"X c #DCDF00",
4208". c #C00000",
4209"# c #373800",
4210/* pixels */
4211" ",
4212" ",
4213" ",
4214" . ",
4215" ... ",
4216" ... ",
4217" ..... ",
4218" ...X.. ",
4219" ..XXX.. ",
4220" ...XXX... ",
4221" ..XXXXX.. ",
4222" ..XXXXXX... ",
4223" ...XXoO+XX.. ",
4224" ..XXXO@#XXX.. ",
4225" ..XXXXO@#XXX... ",
4226" ...XXXXO@#XXXX.. ",
4227" ..XXXXXO@#XXXX... ",
4228" ...XXXXXo@OXXXXX.. ",
4229" ...XXXXXXo@OXXXXXX.. ",
4230" ..XXXXXXX$@OXXXXXX... ",
4231" ...XXXXXXXX@XXXXXXXX.. ",
4232" ...XXXXXXXXXXXXXXXXXX... ",
4233" ..XXXXXXXXXXOXXXXXXXXX.. ",
4234" ...XXXXXXXXXO@#XXXXXXXXX.. ",
4235" ..XXXXXXXXXXX#XXXXXXXXXX... ",
4236" ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
4237" ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
4238" .............................. ",
4239" .............................. ",
4240" ",
4241" ",
4242" "
4243};
4244
63f06c22 4245
536b70ac
VS
4246wxBitmap wxWin32ArtProvider::CreateBitmap(const wxArtID& id,
4247 const wxArtClient& WXUNUSED(client),
4248 const wxSize& WXUNUSED(size))
4249{
4250 if ( id == wxART_INFORMATION )
4251 return wxBitmap(info_xpm);
4252 if ( id == wxART_ERROR )
4253 return wxBitmap(error_xpm);
4254 if ( id == wxART_WARNING )
4255 return wxBitmap(warning_xpm);
4256 if ( id == wxART_QUESTION )
4257 return wxBitmap(question_xpm);
4258 return wxNullBitmap;
63f06c22
VS
4259}
4260
24a23c35 4261
1e6feb95
VZ
4262// ----------------------------------------------------------------------------
4263// text control geometry
4264// ----------------------------------------------------------------------------
4265
4266static inline int GetTextBorderWidth()
4267{
4268 return 1;
4269}
4270
61fef19b
VZ
4271wxRect
4272wxWin32Renderer::GetTextTotalArea(const wxTextCtrl * WXUNUSED(text),
4273 const wxRect& rect) const
1e6feb95
VZ
4274{
4275 wxRect rectTotal = rect;
4276
4277 wxCoord widthBorder = GetTextBorderWidth();
1e6feb95
VZ
4278 rectTotal.Inflate(widthBorder);
4279
4280 // this is what Windows does
4281 rectTotal.height++;
4282
4283 return rectTotal;
4284}
4285
61fef19b
VZ
4286wxRect
4287wxWin32Renderer::GetTextClientArea(const wxTextCtrl * WXUNUSED(text),
4288 const wxRect& rect,
4289 wxCoord *extraSpaceBeyond) const
1e6feb95
VZ
4290{
4291 wxRect rectText = rect;
4292
4293 // undo GetTextTotalArea()
4294 if ( rectText.height > 0 )
4295 rectText.height--;
4296
4297 wxCoord widthBorder = GetTextBorderWidth();
1e6feb95
VZ
4298 rectText.Inflate(-widthBorder);
4299
4300 if ( extraSpaceBeyond )
4301 *extraSpaceBeyond = 0;
4302
4303 return rectText;
4304}
4305
4306// ----------------------------------------------------------------------------
4307// size adjustments
4308// ----------------------------------------------------------------------------
4309
4310void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
4311{
4312#if wxUSE_SCROLLBAR
4313 if ( wxDynamicCast(window, wxScrollBar) )
4314 {
4315 // we only set the width of vert scrollbars and height of the
4316 // horizontal ones
4317 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
4318 size->y = m_sizeScrollbarArrow.y;
4319 else
4320 size->x = m_sizeScrollbarArrow.x;
4321
4322 // skip border width adjustments, they don't make sense for us
4323 return;
4324 }
4325#endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
4326
06aa40d9
WS
4327#if wxUSE_BMPBUTTON
4328 if ( wxDynamicCast(window, wxBitmapButton) )
4329 {
4330 // do nothing
4331 } else
4332#endif // wxUSE_BMPBUTTON
1e6feb95
VZ
4333#if wxUSE_BUTTON
4334 if ( wxDynamicCast(window, wxButton) )
4335 {
1b465102
VZ
4336 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
4337 {
4338 // TODO: don't harcode all this
4339 size->x += 3*window->GetCharWidth();
4340
4341 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
4342 if ( size->y < heightBtn - 8 )
4343 size->y = heightBtn;
4344 else
4345 size->y += 9;
4346 }
1e6feb95 4347
6766e5d1
JS
4348 // for compatibility with other ports, the buttons default size is never
4349 // less than the standard one, but not when display not PDAs.
4350 if (wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA)
4351 {
a290fa5a 4352 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
6766e5d1 4353 {
a290fa5a 4354 wxSize szDef = wxButton::GetDefaultSize();
6766e5d1
JS
4355 if ( size->x < szDef.x )
4356 size->x = szDef.x;
4357 }
4358 }
4359
1e6feb95
VZ
4360 // no border width adjustments for buttons
4361 return;
4362 }
4363#endif // wxUSE_BUTTON
4364
4365 // take into account the border width
4366 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
4367 size->x += rectBorder.x + rectBorder.width;
4368 size->y += rectBorder.y + rectBorder.height;
4369}
4370
4371// ============================================================================
4372// wxInputHandler
4373// ============================================================================
4374
4375// ----------------------------------------------------------------------------
4376// wxWin32InputHandler
4377// ----------------------------------------------------------------------------
4378
4379wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer)
4380{
4381 m_renderer = renderer;
4382}
4383
61fef19b
VZ
4384bool wxWin32InputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
4385 const wxKeyEvent& WXUNUSED(event),
4386 bool WXUNUSED(pressed))
1e6feb95 4387{
a290fa5a 4388 return false;
1e6feb95
VZ
4389}
4390
67e49a98 4391bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
4392 const wxMouseEvent& event)
4393{
211cc8dc 4394 // clicking on the control gives it focus
71e03035 4395 if ( event.ButtonDown() )
211cc8dc 4396 {
71e03035 4397 wxWindow *win = control->GetInputWindow();
d1504049 4398
9b8270da
RR
4399 if (( wxWindow::FindFocus() != control->GetInputWindow() ) &&
4400 ( win->AcceptsFocus() ) )
71e03035
VZ
4401 {
4402 win->SetFocus();
211cc8dc 4403
a290fa5a 4404 return true;
71e03035 4405 }
211cc8dc
VS
4406 }
4407
a290fa5a 4408 return false;
1e6feb95
VZ
4409}
4410
4411// ----------------------------------------------------------------------------
4412// wxWin32ScrollBarInputHandler
4413// ----------------------------------------------------------------------------
4414
4415wxWin32ScrollBarInputHandler::
4416wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
4417 wxInputHandler *handler)
4418 : wxStdScrollBarInputHandler(renderer, handler)
4419{
a290fa5a 4420 m_scrollPaused = false;
1e6feb95
VZ
4421 m_interval = 0;
4422}
4423
4424bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
4425 const wxControlAction& action)
4426{
4427 // stop if went beyond the position of the original click (this can only
4428 // happen when we scroll by pages)
a290fa5a 4429 bool stop = false;
1e6feb95
VZ
4430 if ( action == wxACTION_SCROLL_PAGE_DOWN )
4431 {
4432 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
4433 != wxHT_SCROLLBAR_BAR_2;
4434 }
4435 else if ( action == wxACTION_SCROLL_PAGE_UP )
4436 {
4437 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
4438 != wxHT_SCROLLBAR_BAR_1;
4439 }
4440
4441 if ( stop )
4442 {
4443 StopScrolling(scrollbar);
4444
4445 scrollbar->Refresh();
4446
a290fa5a 4447 return false;
1e6feb95
VZ
4448 }
4449
4450 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
4451}
4452
67e49a98 4453bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
4454 const wxMouseEvent& event)
4455{
4456 // remember the current state
4457 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
4458
4459 // do process the message
4460 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
4461
4462 // analyse the changes
4463 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
4464 {
4465 // we just started dragging the thumb, remember its initial position to
4466 // be able to restore it if the drag is cancelled later
affe4044 4467 m_eventStartDrag = event;
1e6feb95
VZ
4468 }
4469
4470 return rc;
4471}
4472
67e49a98 4473bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
1e6feb95
VZ
4474 const wxMouseEvent& event)
4475{
4476 // we don't highlight scrollbar elements, so there is no need to process
4477 // mouse move events normally - only do it while mouse is captured (i.e.
4478 // when we're dragging the thumb or pressing on something)
4479 if ( !m_winCapture )
a290fa5a 4480 return false;
1e6feb95
VZ
4481
4482 if ( event.Entering() )
4483 {
4484 // we're not interested in this at all
a290fa5a 4485 return false;
1e6feb95
VZ
4486 }
4487
67e49a98 4488 wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
1e6feb95
VZ
4489 wxHitTest ht;
4490 if ( m_scrollPaused )
4491 {
4492 // check if the mouse returned to its original location
4493
4494 if ( event.Leaving() )
4495 {
4496 // it surely didn't
a290fa5a 4497 return false;
1e6feb95
VZ
4498 }
4499
4500 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
4501 if ( ht == m_htLast )
4502 {
4503 // yes it did, resume scrolling
a290fa5a 4504 m_scrollPaused = false;
1e6feb95
VZ
4505 if ( m_timerScroll )
4506 {
4507 // we were scrolling by line/page, restart timer
4508 m_timerScroll->Start(m_interval);
4509
a290fa5a 4510 Press(scrollbar, true);
1e6feb95
VZ
4511 }
4512 else // we were dragging the thumb
4513 {
4514 // restore its last location
4515 HandleThumbMove(scrollbar, m_eventLastDrag);
4516 }
4517
a290fa5a 4518 return true;
1e6feb95
VZ
4519 }
4520 }
4521 else // normal case, scrolling hasn't been paused
4522 {
4523 // if we're scrolling the scrollbar because the arrow or the shaft was
4524 // pressed, check that the mouse stays on the same scrollbar element
4525
a17a79ba
RR
4526#if 0
4527 // Always let thumb jump back if we leave the scrollbar
1e6feb95
VZ
4528 if ( event.Moving() )
4529 {
4530 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
4531 }
4532 else // event.Leaving()
4533 {
4534 ht = wxHT_NOWHERE;
4535 }
a17a79ba
RR
4536#else
4537 // Jump back only if we get far away from it
4538 wxPoint pos = event.GetPosition();
4539 if (scrollbar->HasFlag( wxVERTICAL ))
4540 {
4175e952 4541 if (pos.x > -40 && pos.x < scrollbar->GetSize().x+40)
a17a79ba
RR
4542 pos.x = 5;
4543 }
4544 else
4545 {
4175e952 4546 if (pos.y > -40 && pos.y < scrollbar->GetSize().y+40)
a17a79ba
RR
4547 pos.y = 5;
4548 }
4549 ht = m_renderer->HitTestScrollbar(scrollbar, pos );
4550#endif
1e6feb95
VZ
4551
4552 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4553 // is still ok - we only want to catch the case when the mouse leaves
4554 // the scrollbar here
4555 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
4556 {
4557 ht = wxHT_SCROLLBAR_THUMB;
4558 }
4559
4560 if ( ht != m_htLast )
4561 {
4562 // what were we doing? 2 possibilities: either an arrow/shaft was
4563 // pressed in which case we have a timer and so we just stop it or
4564 // we were dragging the thumb
4565 if ( m_timerScroll )
4566 {
4567 // pause scrolling
4568 m_interval = m_timerScroll->GetInterval();
4569 m_timerScroll->Stop();
a290fa5a 4570 m_scrollPaused = true;
1e6feb95
VZ
4571
4572 // unpress the arrow
a290fa5a 4573 Press(scrollbar, false);
1e6feb95
VZ
4574 }
4575 else // we were dragging the thumb
4576 {
4577 // remember the current thumb position to be able to restore it
4578 // if the mouse returns to it later
affe4044 4579 m_eventLastDrag = event;
1e6feb95
VZ
4580
4581 // and restore the original position (before dragging) of the
4582 // thumb for now
4583 HandleThumbMove(scrollbar, m_eventStartDrag);
4584 }
4585
a290fa5a 4586 return true;
1e6feb95
VZ
4587 }
4588 }
4589
4590 return wxStdScrollBarInputHandler::HandleMouseMove(control, event);
4591}
4592
4593// ----------------------------------------------------------------------------
4594// wxWin32CheckboxInputHandler
4595// ----------------------------------------------------------------------------
4596
67e49a98 4597bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
4598 const wxKeyEvent& event,
4599 bool pressed)
4600{
4601 if ( pressed )
4602 {
4603 wxControlAction action;
4604 int keycode = event.GetKeyCode();
4605 switch ( keycode )
4606 {
4607 case WXK_SPACE:
4608 action = wxACTION_CHECKBOX_TOGGLE;
4609 break;
4610
4611 case WXK_SUBTRACT:
4612 case WXK_NUMPAD_SUBTRACT:
4613 action = wxACTION_CHECKBOX_CHECK;
4614 break;
4615
4616 case WXK_ADD:
4617 case WXK_NUMPAD_ADD:
4618 case WXK_NUMPAD_EQUAL:
4619 action = wxACTION_CHECKBOX_CLEAR;
4620 break;
4621 }
4622
a290fa5a 4623 if ( !action.IsEmpty() )
1e6feb95
VZ
4624 {
4625 control->PerformAction(action);
4626
a290fa5a 4627 return true;
1e6feb95
VZ
4628 }
4629 }
4630
a290fa5a 4631 return false;
1e6feb95
VZ
4632}
4633
4634// ----------------------------------------------------------------------------
4635// wxWin32TextCtrlInputHandler
4636// ----------------------------------------------------------------------------
4637
67e49a98 4638bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
4639 const wxKeyEvent& event,
4640 bool pressed)
4641{
4642 // handle only MSW-specific text bindings here, the others are handled in
4643 // the base class
4644 if ( pressed )
4645 {
4646 int keycode = event.GetKeyCode();
4647
4648 wxControlAction action;
4649 if ( keycode == WXK_DELETE && event.ShiftDown() )
4650 {
4651 action = wxACTION_TEXT_CUT;
4652 }
4653 else if ( keycode == WXK_INSERT )
4654 {
4655 if ( event.ControlDown() )
4656 action = wxACTION_TEXT_COPY;
4657 else if ( event.ShiftDown() )
4658 action = wxACTION_TEXT_PASTE;
4659 }
4660
4661 if ( action != wxACTION_NONE )
4662 {
4663 control->PerformAction(action);
4664
a290fa5a 4665 return true;
1e6feb95
VZ
4666 }
4667 }
4668
4669 return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed);
4670}
4671
71e03035
VZ
4672// ----------------------------------------------------------------------------
4673// wxWin32StatusBarInputHandler
4674// ----------------------------------------------------------------------------
4675
4676wxWin32StatusBarInputHandler::
4677wxWin32StatusBarInputHandler(wxInputHandler *handler)
4678 : wxStdInputHandler(handler)
4679{
a290fa5a 4680 m_isOnGrip = false;
71e03035
VZ
4681}
4682
4683bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar,
4684 const wxPoint& pt) const
4685{
4686 if ( statbar->HasFlag(wxST_SIZEGRIP) &&
d1504049 4687 statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
71e03035 4688 {
d1504049
VZ
4689 wxTopLevelWindow *
4690 parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow);
71e03035 4691
a290fa5a 4692 wxCHECK_MSG( parentTLW, false,
d1504049
VZ
4693 _T("the status bar should be a child of a TLW") );
4694
4695 // a maximized window can't be resized anyhow
4696 if ( !parentTLW->IsMaximized() )
4697 {
4698 // VZ: I think that the standard Windows behaviour is to only
4699 // show the resizing cursor when the mouse is on top of the
4700 // grip itself but apparently different Windows versions behave
4701 // differently (?) and it seems a better UI to allow resizing
4702 // the status bar even when the mouse is above the grip
4703 wxSize sizeSbar = statbar->GetSize();
4704
4705 int diff = sizeSbar.x - pt.x;
4706 return diff >= 0 && diff < (wxCoord)STATUSBAR_GRIP_SIZE;
4707 }
71e03035
VZ
4708 }
4709
a290fa5a 4710 return false;
71e03035
VZ
4711}
4712
4713bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
4714 const wxMouseEvent& event)
4715{
4716 if ( event.Button(1) )
4717 {
4718 if ( event.ButtonDown(1) )
4719 {
4720 wxWindow *statbar = consumer->GetInputWindow();
4721
4722 if ( IsOnGrip(statbar, event.GetPosition()) )
4723 {
4724 wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
4725 wxTopLevelWindow);
4726 if ( tlw )
4727 {
4728 tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
4729 wxHT_TOPLEVEL_BORDER_SE);
4730
4731 statbar->SetCursor(m_cursorOld);
4732
a290fa5a 4733 return true;
71e03035
VZ
4734 }
4735 }
4736 }
4737 }
4738
4739 return wxStdInputHandler::HandleMouse(consumer, event);
4740}
4741
4742bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
4743 const wxMouseEvent& event)
4744{
4745 wxWindow *statbar = consumer->GetInputWindow();
4746
4747 bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
4748 if ( isOnGrip != m_isOnGrip )
4749 {
4750 m_isOnGrip = isOnGrip;
4751 if ( isOnGrip )
4752 {
4753 m_cursorOld = statbar->GetCursor();
4754 statbar->SetCursor(wxCURSOR_SIZENWSE);
4755 }
4756 else
4757 {
4758 statbar->SetCursor(m_cursorOld);
4759 }
4760 }
4761
4762 return wxStdInputHandler::HandleMouseMove(consumer, event);
4763}
4764
768f0c5a
VS
4765// ----------------------------------------------------------------------------
4766// wxWin32FrameInputHandler
4767// ----------------------------------------------------------------------------
4768
8f71aafa
VS
4769class wxWin32SystemMenuEvtHandler : public wxEvtHandler
4770{
4771public:
2279b45a 4772 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
00e086a7 4773
2279b45a
VS
4774 void Attach(wxInputConsumer *consumer);
4775 void Detach();
00e086a7 4776
8f71aafa
VS
4777private:
4778 DECLARE_EVENT_TABLE()
4779 void OnSystemMenu(wxCommandEvent &event);
4780 void OnCloseFrame(wxCommandEvent &event);
4781 void OnClose(wxCloseEvent &event);
00e086a7 4782
8f71aafa
VS
4783 wxWin32FrameInputHandler *m_inputHnd;
4784 wxTopLevelWindow *m_wnd;
0b4f47a3 4785#if wxUSE_ACCEL
8f71aafa 4786 wxAcceleratorTable m_oldAccelTable;
0b4f47a3 4787#endif
8f71aafa
VS
4788};
4789
4790wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler(
2279b45a 4791 wxWin32FrameInputHandler *handler)
8f71aafa
VS
4792{
4793 m_inputHnd = handler;
2279b45a
VS
4794 m_wnd = NULL;
4795}
4796
4797void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
4798{
4799 wxASSERT_MSG( m_wnd == NULL, _T("can't attach the handler twice!") );
4800
8f71aafa
VS
4801 m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
4802 m_wnd->PushEventHandler(this);
00e086a7 4803
0b4f47a3 4804#if wxUSE_ACCEL
00e086a7 4805 // VS: This code relies on using generic implementation of
8f71aafa
VS
4806 // wxAcceleratorTable in wxUniv!
4807 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
4808 m_oldAccelTable = table;
4809 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
4810 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
4811 m_wnd->SetAcceleratorTable(table);
0b4f47a3 4812#endif
8f71aafa
VS
4813}
4814
2279b45a 4815void wxWin32SystemMenuEvtHandler::Detach()
8f71aafa
VS
4816{
4817 if ( m_wnd )
4818 {
0b4f47a3 4819#if wxUSE_ACCEL
8f71aafa 4820 m_wnd->SetAcceleratorTable(m_oldAccelTable);
0b4f47a3 4821#endif
00e086a7 4822 m_wnd->RemoveEventHandler(this);
2279b45a 4823 m_wnd = NULL;
8f71aafa
VS
4824 }
4825}
4826
4827BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
4828 EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
4829 EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
4830 EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
4831END_EVENT_TABLE()
4832
4833void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
4834{
4835 int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) &&
4836 !m_wnd->IsMaximized()) ?
4837 RESIZEABLE_FRAME_BORDER_THICKNESS :
4838 FRAME_BORDER_THICKNESS;
4839 wxPoint pt = m_wnd->GetClientAreaOrigin();
4840 pt.x = -pt.x + border;
4841 pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT;
4842
0b4f47a3 4843#if wxUSE_ACCEL
8f71aafa
VS
4844 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
4845 m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
0b4f47a3
DS
4846#endif
4847
8f71aafa 4848 m_inputHnd->PopupSystemMenu(m_wnd, pt);
0b4f47a3
DS
4849
4850#if wxUSE_ACCEL
8f71aafa 4851 m_wnd->SetAcceleratorTable(table);
0b4f47a3 4852#endif
8f71aafa
VS
4853}
4854
4855void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
4856{
4857 m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
4858 wxTOPLEVEL_BUTTON_CLOSE);
4859}
4860
4861void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
4862{
4863 m_wnd = NULL;
4864 event.Skip();
4865}
4866
4867
2279b45a
VS
4868wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
4869 : wxStdFrameInputHandler(handler)
8f71aafa 4870{
2279b45a
VS
4871 m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
4872}
4873
4874wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
4875{
4876 if ( m_menuHandler )
8f71aafa 4877 {
2279b45a
VS
4878 m_menuHandler->Detach();
4879 delete m_menuHandler;
4880 }
4881}
4882
4883bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
4884 const wxMouseEvent& event)
4885{
4886 if ( event.LeftDClick() || event.LeftDown() || event.RightDown() )
4887 {
4888 wxTopLevelWindow *tlw =
4889 wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
4890
4891 long hit = tlw->HitTest(event.GetPosition());
4892
4893 if ( event.LeftDClick() && hit == wxHT_TOPLEVEL_TITLEBAR )
8f71aafa 4894 {
2279b45a
VS
4895 tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
4896 tlw->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4897 : wxTOPLEVEL_BUTTON_MAXIMIZE);
a290fa5a 4898 return true;
8f71aafa 4899 }
2279b45a 4900 else if ( tlw->GetWindowStyle() & wxSYSTEM_MENU )
8f71aafa 4901 {
2279b45a 4902 if ( (event.LeftDown() && hit == wxHT_TOPLEVEL_ICON) ||
00e086a7
WS
4903 (event.RightDown() &&
4904 (hit == wxHT_TOPLEVEL_TITLEBAR ||
2279b45a 4905 hit == wxHT_TOPLEVEL_ICON)) )
8f71aafa 4906 {
2279b45a 4907 PopupSystemMenu(tlw, event.GetPosition());
a290fa5a 4908 return true;
8f71aafa 4909 }
2279b45a
VS
4910 }
4911 }
4912
4913 return wxStdFrameInputHandler::HandleMouse(consumer, event);
4914}
8f71aafa 4915
00e086a7 4916void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window,
2279b45a
VS
4917 const wxPoint& pos) const
4918{
4919 wxMenu *menu = new wxMenu;
4920
4921 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
4922 menu->Append(wxID_RESTORE_FRAME , _("&Restore"));
4923 menu->Append(wxID_MOVE_FRAME , _("&Move"));
4924 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
4925 menu->Append(wxID_RESIZE_FRAME , _("&Size"));
4926 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME) )
4927 menu->Append(wxID_ICONIZE_FRAME , _("Mi&nimize"));
4928 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
4929 menu->Append(wxID_MAXIMIZE_FRAME , _("Ma&ximize"));
4930 menu->AppendSeparator();
4931 menu->Append(wxID_CLOSE_FRAME, _("Close\tAlt-F4"));
00e086a7 4932
2279b45a
VS
4933 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
4934 {
4935 if ( window->IsMaximized() )
4936 {
a290fa5a
WS
4937 menu->Enable(wxID_MAXIMIZE_FRAME, false);
4938 menu->Enable(wxID_MOVE_FRAME, false);
2279b45a 4939 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
a290fa5a 4940 menu->Enable(wxID_RESIZE_FRAME, false);
2279b45a
VS
4941 }
4942 else
a290fa5a 4943 menu->Enable(wxID_RESTORE_FRAME, false);
2279b45a
VS
4944 }
4945
4946 window->PopupMenu(menu, pos);
4947 delete menu;
4948}
4949
00e086a7 4950bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
2279b45a
VS
4951 bool activated)
4952{
4953 if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
4954 {
4955 // always detach if active frame changed:
4956 m_menuHandler->Detach();
4957
4958 if ( activated )
4959 {
4960 m_menuHandler->Attach(consumer);
8f71aafa
VS
4961 }
4962 }
4963
4964 return wxStdFrameInputHandler::HandleActivation(consumer, activated);
4965}