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