]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/win32.cpp
Applied better/Win98-proof method of getting edit window
[wxWidgets.git] / src / univ / themes / win32.cpp
CommitLineData
00e086a7 1///////////////////////////////////////////////////////////////////////////////
3b3dc801 2// Name: src/univ/themes/win32.cpp
1e6feb95
VZ
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
e7637222
VS
27#include "wx/univ/theme.h"
28
29#if wxUSE_THEME_WIN32
4353a8df 30
1e6feb95
VZ
31#ifndef WX_PRECOMP
32 #include "wx/timer.h"
33 #include "wx/intl.h"
34 #include "wx/dc.h"
35 #include "wx/window.h"
36
37 #include "wx/dcmemory.h"
23205be8 38 #include "wx/dcclient.h"
1e6feb95
VZ
39
40 #include "wx/button.h"
51e298bb 41 #include "wx/bmpbuttn.h"
1e6feb95
VZ
42 #include "wx/listbox.h"
43 #include "wx/checklst.h"
8cb172b4 44 #include "wx/combobox.h"
1e6feb95
VZ
45 #include "wx/scrolbar.h"
46 #include "wx/slider.h"
47 #include "wx/textctrl.h"
3216dbf5 48 #include "wx/toolbar.h"
c2919ab3 49 #include "wx/statusbr.h"
b72a54d1
MB
50
51 #ifdef __WXMSW__
52 // for COLOR_* constants
53 #include "wx/msw/private.h"
54 #endif
3b3dc801 55 #include "wx/menu.h"
9eddec69 56 #include "wx/settings.h"
1832043f 57 #include "wx/toplevel.h"
155ecd4c 58 #include "wx/image.h"
1e6feb95
VZ
59#endif // WX_PRECOMP
60
61#include "wx/notebook.h"
62#include "wx/spinbutt.h"
536b70ac 63#include "wx/artprov.h"
43be3c33
JS
64#ifdef wxUSE_TOGGLEBTN
65#include "wx/tglbtn.h"
66#endif // wxUSE_TOGGLEBTN
1e6feb95
VZ
67
68#include "wx/univ/scrtimer.h"
147b8a4a 69#include "wx/univ/stdrend.h"
9467bdb7 70#include "wx/univ/inpcons.h"
1e6feb95
VZ
71#include "wx/univ/inphand.h"
72#include "wx/univ/colschem.h"
1e6feb95
VZ
73
74// ----------------------------------------------------------------------------
75// constants
76// ----------------------------------------------------------------------------
77
78static const int BORDER_THICKNESS = 2;
79
71e03035
VZ
80static const size_t NUM_STATUSBAR_GRIP_BANDS = 3;
81static const size_t WIDTH_STATUSBAR_GRIP_BAND = 4;
82static const size_t STATUSBAR_GRIP_SIZE =
83 WIDTH_STATUSBAR_GRIP_BAND*NUM_STATUSBAR_GRIP_BANDS;
84
6766e5d1
JS
85static const wxCoord SLIDER_MARGIN = 6; // margin around slider
86static const wxCoord SLIDER_THUMB_LENGTH = 18;
87static const wxCoord SLIDER_TICK_LENGTH = 6;
88
1e6feb95
VZ
89// wxWin32Renderer: draw the GUI elements in Win32 style
90// ----------------------------------------------------------------------------
91
147b8a4a 92class wxWin32Renderer : public wxStdRenderer
1e6feb95
VZ
93{
94public:
1e6feb95
VZ
95 // ctor
96 wxWin32Renderer(const wxColourScheme *scheme);
97
147b8a4a 98 // reimplement the renderer methods which are different for this theme
1e6feb95
VZ
99 virtual void DrawLabel(wxDC& dc,
100 const wxString& label,
101 const wxRect& rect,
102 int flags = 0,
103 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
104 int indexAccel = -1,
105 wxRect *rectBounds = NULL);
106 virtual void DrawButtonLabel(wxDC& dc,
107 const wxString& label,
108 const wxBitmap& image,
109 const wxRect& rect,
110 int flags = 0,
111 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
112 int indexAccel = -1,
113 wxRect *rectBounds = NULL);
1e6feb95
VZ
114 virtual void DrawButtonBorder(wxDC& dc,
115 const wxRect& rect,
116 int flags = 0,
147b8a4a 117 wxRect *rectIn = NULL);
0428ac8c 118
1e6feb95
VZ
119 virtual void DrawArrow(wxDC& dc,
120 wxDirection dir,
121 const wxRect& rect,
122 int flags = 0);
1e6feb95
VZ
123 virtual void DrawScrollbarThumb(wxDC& dc,
124 wxOrientation orient,
125 const wxRect& rect,
126 int flags = 0);
127 virtual void DrawScrollbarShaft(wxDC& dc,
128 wxOrientation orient,
129 const wxRect& rect,
130 int flags = 0);
147b8a4a 131
9a6384ca 132#if wxUSE_TOOLBAR
3216dbf5
VZ
133 virtual void DrawToolBarButton(wxDC& dc,
134 const wxString& label,
135 const wxBitmap& bitmap,
136 const wxRect& rect,
a8f4cabe 137 int flags = 0,
370efbe7
WS
138 long style = 0,
139 int tbarStyle = 0);
9a6384ca 140#endif // wxUSE_TOOLBAR
147b8a4a 141
c4036939 142#if wxUSE_NOTEBOOK
1e6feb95
VZ
143 virtual void DrawTab(wxDC& dc,
144 const wxRect& rect,
145 wxDirection dir,
146 const wxString& label,
147 const wxBitmap& bitmap = wxNullBitmap,
148 int flags = 0,
149 int indexAccel = -1);
c4036939 150#endif // wxUSE_NOTEBOOK
1e6feb95 151
9a6384ca 152#if wxUSE_SLIDER
1e6feb95
VZ
153 virtual void DrawSliderShaft(wxDC& dc,
154 const wxRect& rect,
6766e5d1 155 int lenThumb,
1e6feb95
VZ
156 wxOrientation orient,
157 int flags = 0,
6766e5d1 158 long style = 0,
1e6feb95
VZ
159 wxRect *rectShaft = NULL);
160 virtual void DrawSliderThumb(wxDC& dc,
161 const wxRect& rect,
162 wxOrientation orient,
6766e5d1
JS
163 int flags = 0,
164 long style = 0);
1e6feb95
VZ
165 virtual void DrawSliderTicks(wxDC& dc,
166 const wxRect& rect,
6766e5d1 167 int lenThumb,
1e6feb95
VZ
168 wxOrientation orient,
169 int start,
170 int end,
171 int step = 1,
6766e5d1
JS
172 int flags = 0,
173 long style = 0);
9a6384ca 174#endif // wxUSE_SLIDER
1e6feb95 175
9a6384ca 176#if wxUSE_MENUS
1e6feb95
VZ
177 virtual void DrawMenuBarItem(wxDC& dc,
178 const wxRect& rect,
179 const wxString& label,
180 int flags = 0,
181 int indexAccel = -1);
182 virtual void DrawMenuItem(wxDC& dc,
183 wxCoord y,
184 const wxMenuGeometryInfo& geometryInfo,
185 const wxString& label,
186 const wxString& accel,
187 const wxBitmap& bitmap = wxNullBitmap,
188 int flags = 0,
189 int indexAccel = -1);
190 virtual void DrawMenuSeparator(wxDC& dc,
191 wxCoord y,
192 const wxMenuGeometryInfo& geomInfo);
9a6384ca 193#endif // wxUSE_MENUS
71e03035 194
9a6384ca 195#if wxUSE_STATUSBAR
71e03035
VZ
196 virtual void DrawStatusField(wxDC& dc,
197 const wxRect& rect,
198 const wxString& label,
c2919ab3 199 int flags = 0, int style = 0);
9a6384ca 200#endif // wxUSE_STATUSBAR
71e03035 201
1e6feb95 202 virtual void GetComboBitmaps(wxBitmap *bmpNormal,
1b465102 203 wxBitmap *bmpFocus,
1e6feb95
VZ
204 wxBitmap *bmpPressed,
205 wxBitmap *bmpDisabled);
206
207 virtual void AdjustSize(wxSize *size, const wxWindow *window);
1e6feb95
VZ
208 virtual bool AreScrollbarsInsideBorder() const;
209
210 virtual wxSize GetScrollbarArrowSize() const
211 { return m_sizeScrollbarArrow; }
9a6384ca 212
1e6feb95
VZ
213 virtual wxSize GetCheckBitmapSize() const
214 { return wxSize(13, 13); }
215 virtual wxSize GetRadioBitmapSize() const
216 { return wxSize(12, 12); }
217 virtual wxCoord GetCheckItemMargin() const
218 { return 0; }
219
dd267523 220#if wxUSE_TOOLBAR
3216dbf5
VZ
221 virtual wxSize GetToolBarButtonSize(wxCoord *separator) const
222 { if ( separator ) *separator = 5; return wxSize(16, 15); }
223 virtual wxSize GetToolBarMargin() const
34d26f42 224 { return wxSize(4, 4); }
dd267523 225#endif // wxUSE_TOOLBAR
3216dbf5 226
9a6384ca 227#if wxUSE_TEXTCTRL
1e6feb95 228 virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
3216dbf5 229 const wxRect& rect) const;
1e6feb95
VZ
230 virtual wxRect GetTextClientArea(const wxTextCtrl *text,
231 const wxRect& rect,
3216dbf5 232 wxCoord *extraSpaceBeyond) const;
9a6384ca 233#endif // wxUSE_TEXTCTRL
1e6feb95 234
c4036939 235#if wxUSE_NOTEBOOK
1e6feb95
VZ
236 virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
237 virtual wxSize GetTabPadding() const { return wxSize(6, 5); }
c4036939 238#endif // wxUSE_NOTEBOOK
1e6feb95 239
9a6384ca
WS
240#if wxUSE_SLIDER
241
6766e5d1
JS
242 virtual wxCoord GetSliderDim() const { return SLIDER_THUMB_LENGTH + 2*BORDER_THICKNESS; }
243 virtual wxCoord GetSliderTickLen() const { return SLIDER_TICK_LENGTH; }
1e6feb95 244 virtual wxRect GetSliderShaftRect(const wxRect& rect,
6766e5d1
JS
245 int lenThumb,
246 wxOrientation orient,
247 long style = 0) const;
1e6feb95 248 virtual wxSize GetSliderThumbSize(const wxRect& rect,
6766e5d1 249 int lenThumb,
1e6feb95 250 wxOrientation orient) const;
9a6384ca
WS
251#endif // wxUSE_SLIDER
252
1e6feb95
VZ
253 virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
254
9a6384ca 255#if wxUSE_MENUS
1e6feb95
VZ
256 virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const;
257 virtual wxMenuGeometryInfo *GetMenuGeometry(wxWindow *win,
258 const wxMenu& menu) const;
9a6384ca 259#endif // wxUSE_MENUS
71e03035 260
1e6feb95 261protected:
6229b92f 262 // overridden wxStdRenderer methods
147b8a4a
VZ
263 virtual void DrawFrameWithLabel(wxDC& dc,
264 const wxString& label,
265 const wxRect& rectFrame,
266 const wxRect& rectText,
267 int flags,
268 int alignment,
269 int indexAccel);
1e6feb95 270
6229b92f
VZ
271 virtual void DrawCheckItemBitmap(wxDC& dc,
272 const wxBitmap& bitmap,
273 const wxRect& rect,
274 int flags);
275
1e6feb95
VZ
276
277 // draw the border used for scrollbar arrows
a290fa5a 278 void DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed = false);
1e6feb95
VZ
279
280 // public DrawArrow()s helper
281 void DrawArrow(wxDC& dc, const wxRect& rect,
0428ac8c 282 ArrowDirection arrowDir, ArrowStyle arrowStyle);
1e6feb95
VZ
283
284 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
285 void DrawArrowButton(wxDC& dc, const wxRect& rect,
0428ac8c
VZ
286 ArrowDirection arrowDir,
287 ArrowStyle arrowStyle);
1e6feb95 288
1e6feb95
VZ
289 // draw a normal or transposed line (useful for using the same code fo both
290 // horizontal and vertical widgets)
291 void DrawLine(wxDC& dc,
292 wxCoord x1, wxCoord y1,
293 wxCoord x2, wxCoord y2,
a290fa5a 294 bool transpose = false)
1e6feb95
VZ
295 {
296 if ( transpose )
297 dc.DrawLine(y1, x1, y2, x2);
298 else
299 dc.DrawLine(x1, y1, x2, y2);
300 }
301
302 // get the standard check/radio button bitmap
303 wxBitmap GetIndicator(IndicatorType indType, int flags);
6229b92f 304 virtual wxBitmap GetCheckBitmap(int flags)
1e6feb95 305 { return GetIndicator(IndicatorType_Check, flags); }
6229b92f 306 virtual wxBitmap GetRadioBitmap(int flags)
1e6feb95
VZ
307 { return GetIndicator(IndicatorType_Radio, flags); }
308
249803fb
VZ
309 virtual wxBitmap GetFrameButtonBitmap(FrameButtonType type);
310
4462f911
VZ
311#if wxUSE_SLIDER
312 // Fill the arguments with true or false if this slider has labels on
313 // left/right side (or top/bottom for horizontal sliders) respectively
314 static
315 void GetSliderLabelsSides(wxOrientation orient, long style,
316 bool *left, bool *right)
317 {
318 // should we draw ticks at all?
319 if ( !(style & wxSL_AUTOTICKS) )
320 {
321 *left =
322 *right = false;
323 return;
324 }
325
326 // should we draw them on both sides?
327 if ( style & wxSL_BOTH )
328 {
329 *left =
330 *right = true;
331 return;
332 }
333
334 // we draw them on one side only, determine which one
335 if ( ((style & wxSL_TOP) && (orient == wxHORIZONTAL)) ||
336 ((style & wxSL_LEFT) && (orient == wxVERTICAL)) )
337 {
338 *left = true;
339 *right = false;
340 }
341 else if ( ((style & wxSL_BOTTOM) && (orient == wxHORIZONTAL)) ||
342 ((style & wxSL_RIGHT) && (orient == wxVERTICAL)) )
343 {
344 *left = false;
345 *right = true;
346 }
347 else
348 {
349 wxFAIL_MSG( "inconsistent wxSlider flags" );
350
351 *left =
352 *right = false;
353 }
354 }
355#endif // wxUSE_SLIDER
356
1e6feb95 357private:
1e6feb95
VZ
358 // the sizing parameters (TODO make them changeable)
359 wxSize m_sizeScrollbarArrow;
360
6229b92f 361 // the checked and unchecked bitmaps for DrawCheckItemBitmap()
e3400e2e
VZ
362 wxBitmap m_bmpCheckBitmaps[IndicatorStatus_Max];
363
364 // the bitmaps returned by GetIndicator()
365 wxBitmap m_bmpIndicators[IndicatorType_Max]
147b8a4a 366 [IndicatorState_MaxMenu]
e3400e2e
VZ
367 [IndicatorStatus_Max];
368
249803fb
VZ
369 // titlebar icons:
370 wxBitmap m_bmpFrameButtons[FrameButton_Max];
371
372 // standard defaults for the above bitmaps
147b8a4a
VZ
373 static const char **ms_xpmChecked[IndicatorStatus_Max];
374 static const char **ms_xpmIndicators[IndicatorType_Max]
375 [IndicatorState_MaxMenu]
376 [IndicatorStatus_Max];
249803fb 377 static const char **ms_xpmFrameButtons[FrameButton_Max];
1e6feb95
VZ
378
379 // first row is for the normal state, second - for the disabled
380 wxBitmap m_bmpArrows[Arrow_StateMax][Arrow_Max];
381};
382
383// ----------------------------------------------------------------------------
384// wxWin32InputHandler and derived classes: process the keyboard and mouse
385// messages according to Windows standards
386// ----------------------------------------------------------------------------
387
388class wxWin32InputHandler : public wxInputHandler
389{
390public:
9467bdb7 391 wxWin32InputHandler() { }
1e6feb95 392
67e49a98 393 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
394 const wxKeyEvent& event,
395 bool pressed);
67e49a98 396 virtual bool HandleMouse(wxInputConsumer *control,
1e6feb95 397 const wxMouseEvent& event);
1e6feb95
VZ
398};
399
9a6384ca 400#if wxUSE_SCROLLBAR
1e6feb95
VZ
401class wxWin32ScrollBarInputHandler : public wxStdScrollBarInputHandler
402{
403public:
9467bdb7 404 wxWin32ScrollBarInputHandler(wxRenderer *renderer,
1e6feb95
VZ
405 wxInputHandler *handler);
406
9467bdb7
VZ
407 virtual bool HandleMouse(wxInputConsumer *control,
408 const wxMouseEvent& event);
409 virtual bool HandleMouseMove(wxInputConsumer *control,
410 const wxMouseEvent& event);
1e6feb95
VZ
411
412 virtual bool OnScrollTimer(wxScrollBar *scrollbar,
413 const wxControlAction& action);
414
415protected:
61fef19b
VZ
416 virtual void Highlight(wxScrollBar * WXUNUSED(scrollbar),
417 bool WXUNUSED(doIt))
1e6feb95
VZ
418 {
419 // we don't highlight anything
420 }
421
422 // the first and last event which caused the thumb to move
423 wxMouseEvent m_eventStartDrag,
424 m_eventLastDrag;
425
426 // have we paused the scrolling because the mouse moved?
427 bool m_scrollPaused;
428
429 // we remember the interval of the timer to be able to restart it
430 int m_interval;
431};
9a6384ca 432#endif // wxUSE_SCROLLBAR
1e6feb95 433
9a6384ca 434#if wxUSE_CHECKBOX
9467bdb7 435class wxWin32CheckboxInputHandler : public wxStdInputHandler
1e6feb95
VZ
436{
437public:
438 wxWin32CheckboxInputHandler(wxInputHandler *handler)
9467bdb7 439 : wxStdInputHandler(handler) { }
1e6feb95 440
67e49a98 441 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
442 const wxKeyEvent& event,
443 bool pressed);
444};
9a6384ca 445#endif // wxUSE_CHECKBOX
1e6feb95 446
9a6384ca 447#if wxUSE_TEXTCTRL
9467bdb7 448class wxWin32TextCtrlInputHandler : public wxStdInputHandler
1e6feb95
VZ
449{
450public:
451 wxWin32TextCtrlInputHandler(wxInputHandler *handler)
9467bdb7 452 : wxStdInputHandler(handler) { }
1e6feb95 453
67e49a98 454 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
455 const wxKeyEvent& event,
456 bool pressed);
457};
9a6384ca 458#endif // wxUSE_TEXTCTRL
1e6feb95 459
71e03035
VZ
460class wxWin32StatusBarInputHandler : public wxStdInputHandler
461{
462public:
463 wxWin32StatusBarInputHandler(wxInputHandler *handler);
464
465 virtual bool HandleMouse(wxInputConsumer *consumer,
466 const wxMouseEvent& event);
467
468 virtual bool HandleMouseMove(wxInputConsumer *consumer,
469 const wxMouseEvent& event);
470
471protected:
472 // is the given point over the statusbar grip?
473 bool IsOnGrip(wxWindow *statbar, const wxPoint& pt) const;
474
475private:
476 // the cursor we had replaced with the resize one
477 wxCursor m_cursorOld;
478
479 // was the mouse over the grip last time we checked?
480 bool m_isOnGrip;
481};
482
8f71aafa
VS
483class wxWin32SystemMenuEvtHandler;
484
9467bdb7 485class wxWin32FrameInputHandler : public wxStdInputHandler
768f0c5a
VS
486{
487public:
2279b45a 488 wxWin32FrameInputHandler(wxInputHandler *handler);
d3c7fc99 489 virtual ~wxWin32FrameInputHandler();
768f0c5a
VS
490
491 virtual bool HandleMouse(wxInputConsumer *control,
492 const wxMouseEvent& event);
8f71aafa
VS
493
494 virtual bool HandleActivation(wxInputConsumer *consumer, bool activated);
00e086a7 495
9a6384ca 496#if wxUSE_MENUS
249803fb 497 void PopupSystemMenu(wxTopLevelWindow *window) const;
9a6384ca 498#endif // wxUSE_MENUS
8f71aafa
VS
499
500private:
501 // was the mouse over the grip last time we checked?
502 wxWin32SystemMenuEvtHandler *m_menuHandler;
768f0c5a
VS
503};
504
1e6feb95
VZ
505// ----------------------------------------------------------------------------
506// wxWin32ColourScheme: uses (default) Win32 colours
507// ----------------------------------------------------------------------------
508
509class wxWin32ColourScheme : public wxColourScheme
510{
511public:
512 virtual wxColour Get(StdColour col) const;
513 virtual wxColour GetBackground(wxWindow *win) const;
514};
515
536b70ac
VS
516// ----------------------------------------------------------------------------
517// wxWin32ArtProvider
518// ----------------------------------------------------------------------------
519
520class wxWin32ArtProvider : public wxArtProvider
521{
522protected:
523 virtual wxBitmap CreateBitmap(const wxArtID& id,
524 const wxArtClient& client,
525 const wxSize& size);
526};
527
1e6feb95
VZ
528// ----------------------------------------------------------------------------
529// wxWin32Theme
530// ----------------------------------------------------------------------------
531
d5d29b8a 532WX_DEFINE_ARRAY_PTR(wxInputHandler *, wxArrayHandlers);
1e6feb95
VZ
533
534class wxWin32Theme : public wxTheme
535{
536public:
537 wxWin32Theme();
538 virtual ~wxWin32Theme();
539
240889a1 540 virtual wxRenderer *GetRenderer();
536b70ac 541 virtual wxArtProvider *GetArtProvider();
9467bdb7
VZ
542 virtual wxInputHandler *GetInputHandler(const wxString& control,
543 wxInputConsumer *consumer);
1e6feb95
VZ
544 virtual wxColourScheme *GetColourScheme();
545
546private:
1e6feb95 547 wxWin32Renderer *m_renderer;
00e086a7 548
536b70ac 549 wxWin32ArtProvider *m_artProvider;
1e6feb95
VZ
550
551 // the names of the already created handlers and the handlers themselves
552 // (these arrays are synchronized)
553 wxSortedArrayString m_handlerNames;
554 wxArrayHandlers m_handlers;
555
1e6feb95
VZ
556 wxWin32ColourScheme *m_scheme;
557
558 WX_DECLARE_THEME(win32)
559};
560
561// ----------------------------------------------------------------------------
562// standard bitmaps
563// ----------------------------------------------------------------------------
564
24a23c35 565// frame buttons bitmaps
24a23c35
VS
566static const char *frame_button_close_xpm[] = {
567"12 10 2 1",
cc4bc3a0 568" c None",
249803fb 569"X c black",
24a23c35 570" ",
249803fb
VZ
571" XX XX ",
572" XX XX ",
573" XXXX ",
574" XX ",
575" XXXX ",
576" XX XX ",
577" XX XX ",
24a23c35
VS
578" ",
579" "};
580
581static const char *frame_button_help_xpm[] = {
582"12 10 2 1",
cc4bc3a0 583" c None",
249803fb
VZ
584"X c #000000",
585" XXXX ",
586" XX XX ",
587" XX XX ",
588" XX ",
589" XX ",
590" XX ",
24a23c35 591" ",
249803fb
VZ
592" XX ",
593" XX ",
24a23c35
VS
594" "};
595
596static const char *frame_button_maximize_xpm[] = {
597"12 10 2 1",
cc4bc3a0 598" c None",
249803fb
VZ
599"X c #000000",
600" XXXXXXXXX ",
601" XXXXXXXXX ",
602" X X ",
603" X X ",
604" X X ",
605" X X ",
606" X X ",
607" X X ",
608" XXXXXXXXX ",
24a23c35
VS
609" "};
610
611static const char *frame_button_minimize_xpm[] = {
612"12 10 2 1",
cc4bc3a0 613" c None",
249803fb 614"X c #000000",
24a23c35
VS
615" ",
616" ",
617" ",
618" ",
619" ",
620" ",
621" ",
249803fb
VZ
622" XXXXXX ",
623" XXXXXX ",
24a23c35
VS
624" "};
625
626static const char *frame_button_restore_xpm[] = {
627"12 10 2 1",
cc4bc3a0 628" c None",
249803fb
VZ
629"X c #000000",
630" XXXXXX ",
631" XXXXXX ",
632" X X ",
633" XXXXXX X ",
634" XXXXXX X ",
635" X XXX ",
636" X X ",
637" X X ",
638" XXXXXX ",
24a23c35
VS
639" "};
640
249803fb
VZ
641const char **wxWin32Renderer::ms_xpmFrameButtons[FrameButton_Max] =
642{
643 frame_button_close_xpm,
644 frame_button_minimize_xpm,
645 frame_button_maximize_xpm,
646 frame_button_restore_xpm,
647 frame_button_help_xpm,
648};
649
1e6feb95
VZ
650// menu bitmaps
651
652static const char *checked_menu_xpm[] = {
653/* columns rows colors chars-per-pixel */
654"9 9 2 1",
655"w c None",
656"b c black",
657/* pixels */
658"wwwwwwwww",
659"wwwwwwwbw",
660"wwwwwwbbw",
661"wbwwwbbbw",
662"wbbwbbbww",
663"wbbbbbwww",
664"wwbbbwwww",
665"wwwbwwwww",
666"wwwwwwwww"
667};
668
669static const char *selected_checked_menu_xpm[] = {
670/* columns rows colors chars-per-pixel */
671"9 9 2 1",
672"w c None",
673"b c white",
674/* pixels */
675"wwwwwwwww",
676"wwwwwwwbw",
677"wwwwwwbbw",
678"wbwwwbbbw",
679"wbbwbbbww",
680"wbbbbbwww",
681"wwbbbwwww",
682"wwwbwwwww",
683"wwwwwwwww"
684};
685
686static const char *disabled_checked_menu_xpm[] = {
687/* columns rows colors chars-per-pixel */
688"9 9 3 1",
689"w c None",
690"b c #7f7f7f",
691"W c #e0e0e0",
692/* pixels */
693"wwwwwwwww",
694"wwwwwwwbw",
695"wwwwwwbbW",
696"wbwwwbbbW",
697"wbbwbbbWW",
698"wbbbbbWWw",
699"wwbbbWWww",
700"wwwbWWwww",
701"wwwwWwwww"
702};
703
704static const char *selected_disabled_checked_menu_xpm[] = {
705/* columns rows colors chars-per-pixel */
706"9 9 2 1",
707"w c None",
708"b c #7f7f7f",
709/* pixels */
710"wwwwwwwww",
711"wwwwwwwbw",
712"wwwwwwbbw",
713"wbwwwbbbw",
714"wbbwbbbww",
715"wbbbbbwww",
716"wwbbbwwww",
717"wwwbwwwww",
718"wwwwwwwww"
719};
720
721// checkbox and radiobox bitmaps below
722
723static const char *checked_xpm[] = {
724/* columns rows colors chars-per-pixel */
725"13 13 5 1",
726"w c white",
727"b c black",
728"d c #7f7f7f",
729"g c #c0c0c0",
730"h c #e0e0e0",
731/* pixels */
732"ddddddddddddh",
733"dbbbbbbbbbbgh",
734"dbwwwwwwwwwgh",
735"dbwwwwwwwbwgh",
736"dbwwwwwwbbwgh",
737"dbwbwwwbbbwgh",
738"dbwbbwbbbwwgh",
739"dbwbbbbbwwwgh",
740"dbwwbbbwwwwgh",
741"dbwwwbwwwwwgh",
742"dbwwwwwwwwwgh",
743"dgggggggggggh",
744"hhhhhhhhhhhhh"
745};
746
747static const char *pressed_checked_xpm[] = {
748/* columns rows colors chars-per-pixel */
749"13 13 4 1",
750"b c black",
751"d c #7f7f7f",
752"g c #c0c0c0",
753"h c #e0e0e0",
754/* pixels */
755"ddddddddddddh",
756"dbbbbbbbbbbgh",
757"dbggggggggggh",
758"dbgggggggbggh",
759"dbggggggbbggh",
760"dbgbgggbbbggh",
761"dbgbbgbbbgggh",
762"dbgbbbbbggggh",
763"dbggbbbgggggh",
764"dbgggbggggggh",
765"dbggggggggggh",
766"dgggggggggggh",
767"hhhhhhhhhhhhh"
768};
769
770static const char *pressed_disabled_checked_xpm[] = {
771/* columns rows colors chars-per-pixel */
772"13 13 4 1",
773"b c black",
774"d c #7f7f7f",
775"g c #c0c0c0",
776"h c #e0e0e0",
777/* pixels */
778"ddddddddddddh",
779"dbbbbbbbbbbgh",
780"dbggggggggggh",
781"dbgggggggdggh",
782"dbggggggddggh",
783"dbgdgggdddggh",
784"dbgddgdddgggh",
785"dbgdddddggggh",
786"dbggdddgggggh",
787"dbgggdggggggh",
788"dbggggggggggh",
789"dgggggggggggh",
790"hhhhhhhhhhhhh"
791};
792
793static const char *checked_item_xpm[] = {
794/* columns rows colors chars-per-pixel */
795"13 13 3 1",
796"w c white",
797"b c black",
798"d c #808080",
799/* pixels */
800"wwwwwwwwwwwww",
801"wdddddddddddw",
802"wdwwwwwwwwwdw",
803"wdwwwwwwwbwdw",
804"wdwwwwwwbbwdw",
805"wdwbwwwbbbwdw",
806"wdwbbwbbbwwdw",
807"wdwbbbbbwwwdw",
808"wdwwbbbwwwwdw",
809"wdwwwbwwwwwdw",
810"wdwwwwwwwwwdw",
811"wdddddddddddw",
812"wwwwwwwwwwwww"
813};
814
815static const char *unchecked_xpm[] = {
816/* columns rows colors chars-per-pixel */
817"13 13 5 1",
818"w c white",
819"b c black",
820"d c #7f7f7f",
821"g c #c0c0c0",
822"h c #e0e0e0",
823/* pixels */
824"ddddddddddddh",
825"dbbbbbbbbbbgh",
826"dbwwwwwwwwwgh",
827"dbwwwwwwwwwgh",
828"dbwwwwwwwwwgh",
829"dbwwwwwwwwwgh",
830"dbwwwwwwwwwgh",
831"dbwwwwwwwwwgh",
832"dbwwwwwwwwwgh",
833"dbwwwwwwwwwgh",
834"dbwwwwwwwwwgh",
835"dgggggggggggh",
836"hhhhhhhhhhhhh"
837};
838
839static const char *pressed_unchecked_xpm[] = {
840/* columns rows colors chars-per-pixel */
841"13 13 4 1",
842"b c black",
843"d c #7f7f7f",
844"g c #c0c0c0",
845"h c #e0e0e0",
846/* pixels */
847"ddddddddddddh",
848"dbbbbbbbbbbgh",
849"dbggggggggggh",
850"dbggggggggggh",
851"dbggggggggggh",
852"dbggggggggggh",
853"dbggggggggggh",
854"dbggggggggggh",
855"dbggggggggggh",
856"dbggggggggggh",
857"dbggggggggggh",
858"dbggggggggggh",
859"hhhhhhhhhhhhh"
860};
861
862static const char *unchecked_item_xpm[] = {
863/* columns rows colors chars-per-pixel */
864"13 13 2 1",
865"w c white",
866"d c #808080",
867/* pixels */
868"wwwwwwwwwwwww",
869"wdddddddddddw",
870"wdwwwwwwwwwdw",
871"wdwwwwwwwwwdw",
872"wdwwwwwwwwwdw",
873"wdwwwwwwwwwdw",
874"wdwwwwwwwwwdw",
875"wdwwwwwwwwwdw",
876"wdwwwwwwwwwdw",
877"wdwwwwwwwwwdw",
878"wdwwwwwwwwwdw",
879"wdddddddddddw",
880"wwwwwwwwwwwww"
881};
882
415a0ff1
WS
883static const char *undetermined_xpm[] = {
884/* columns rows colors chars-per-pixel */
885"13 13 5 1",
886"A c #030303",
887"B c #838383",
888"C c #C3C3C3",
889"D c #FBFBFB",
890"E c #DBDBDB",
891/* pixels */
892"BBBBBBBBBBBBD",
893"BAAAAAAAAAAED",
894"BACDCDCDCDCED",
895"BADCDCDCDBDED",
896"BACDCDCDBBCED",
897"BADBDCEBBBDED",
898"BACBBDBBBDCED",
899"BADBBBBBDCDED",
900"BACDBBBDCDCED",
901"BADCDBDCDCDED",
902"BACDCDCDCDCED",
903"BEEEEEEEEEEED",
904"DDDDDDDDDDDDD"
905};
906
907static const char *pressed_undetermined_xpm[] = {
908/* columns rows colors chars-per-pixel */
909"13 13 5 1",
910"A c #040404",
911"B c #848484",
912"C c #C4C4C4",
913"D c #FCFCFC",
914"E c #DCDCDC",
915/* pixels */
916"BBBBBBBBBBBBD",
917"BAAAAAAAAAAED",
918"BACCCCCCCCCCD",
919"BACCCCCCCACED",
920"BACCCCCCAACED",
921"BACACCCAAACED",
922"BACAACAAACCED",
923"BACAAAAACCCED",
924"BACCAAACCCCCD",
925"BACCCACCCCCED",
926"BACCCCCCCCCED",
927"BEEEEEEEEEEED",
928"DDDDDDDDDDDDD"
929};
930
1e6feb95
VZ
931static const char *checked_radio_xpm[] = {
932/* columns rows colors chars-per-pixel */
933"12 12 6 1",
934" c None",
935"w c white",
936"b c black",
937"d c #7f7f7f",
938"g c #c0c0c0",
939"h c #e0e0e0",
940/* pixels */
941" dddd ",
942" ddbbbbdd ",
943" dbbwwwwbbh ",
944" dbwwwwwwgh ",
945"dbwwwbbwwwgh",
946"dbwwbbbbwwgh",
947"dbwwbbbbwwgh",
948"dbwwwbbwwwgh",
949" dbwwwwwwgh ",
950" dggwwwwggh ",
951" hhgggghh ",
952" hhhh "
953};
954
955static const char *pressed_checked_radio_xpm[] = {
956/* columns rows colors chars-per-pixel */
957"12 12 6 1",
958" c None",
959"w c white",
960"b c black",
961"d c #7f7f7f",
962"g c #c0c0c0",
963"h c #e0e0e0",
964/* pixels */
965" dddd ",
966" ddbbbbdd ",
967" dbbggggbbh ",
968" dbgggggggh ",
969"dbgggbbggggh",
970"dbggbbbbgggh",
971"dbggbbbbgggh",
972"dbgggbbggggh",
973" dbgggggggh ",
974" dggggggggh ",
975" hhgggghh ",
976" hhhh "
977};
978
979static const char *pressed_disabled_checked_radio_xpm[] = {
980/* columns rows colors chars-per-pixel */
981"12 12 6 1",
982" c None",
983"w c white",
984"b c black",
985"d c #7f7f7f",
986"g c #c0c0c0",
987"h c #e0e0e0",
988/* pixels */
989" dddd ",
990" ddbbbbdd ",
991" dbbggggbbh ",
992" dbgggggggh ",
993"dbgggddggggh",
994"dbggddddgggh",
995"dbggddddgggh",
996"dbgggddggggh",
997" dbgggggggh ",
998" dggggggggh ",
999" hhgggghh ",
1000" hhhh ",
1001};
1002
1003static const char *unchecked_radio_xpm[] = {
1004/* columns rows colors chars-per-pixel */
1005"12 12 6 1",
1006" c None",
1007"w c white",
1008"b c black",
1009"d c #7f7f7f",
1010"g c #c0c0c0",
1011"h c #e0e0e0",
1012/* pixels */
1013" dddd ",
1014" ddbbbbdd ",
1015" dbbwwwwbbh ",
1016" dbwwwwwwgh ",
1017"dbwwwwwwwwgh",
1018"dbwwwwwwwwgh",
1019"dbwwwwwwwwgh",
1020"dbwwwwwwwwgh",
1021" dbwwwwwwgh ",
1022" dggwwwwggh ",
1023" hhgggghh ",
1024" hhhh "
1025};
1026
1027static const char *pressed_unchecked_radio_xpm[] = {
1028/* columns rows colors chars-per-pixel */
1029"12 12 6 1",
1030" c None",
1031"w c white",
1032"b c black",
1033"d c #7f7f7f",
1034"g c #c0c0c0",
1035"h c #e0e0e0",
1036/* pixels */
1037" dddd ",
1038" ddbbbbdd ",
1039" dbbggggbbh ",
1040" dbgggggggh ",
1041"dbgggggggggh",
1042"dbgggggggggh",
1043"dbgggggggggh",
1044"dbgggggggggh",
1045" dbgggggggh ",
1046" dggggggggh ",
1047" hhgggghh ",
1048" hhhh "
1049};
1050
147b8a4a
VZ
1051const char **wxWin32Renderer::ms_xpmIndicators[IndicatorType_Max]
1052 [IndicatorState_MaxMenu]
1053 [IndicatorStatus_Max] =
1e6feb95
VZ
1054{
1055 // checkboxes first
1056 {
1057 // normal state
415a0ff1 1058 { checked_xpm, unchecked_xpm, undetermined_xpm },
1e6feb95
VZ
1059
1060 // pressed state
415a0ff1 1061 { pressed_checked_xpm, pressed_unchecked_xpm, pressed_undetermined_xpm },
1e6feb95
VZ
1062
1063 // disabled state
415a0ff1 1064 { pressed_disabled_checked_xpm, pressed_unchecked_xpm, pressed_disabled_checked_xpm },
1e6feb95
VZ
1065 },
1066
1067 // radio
1068 {
1069 // normal state
415a0ff1 1070 { checked_radio_xpm, unchecked_radio_xpm, NULL },
1e6feb95
VZ
1071
1072 // pressed state
415a0ff1 1073 { pressed_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL },
1e6feb95
VZ
1074
1075 // disabled state
415a0ff1 1076 { pressed_disabled_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL },
1e6feb95
VZ
1077 },
1078
1079 // menu
1080 {
1081 // normal state
415a0ff1 1082 { checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1083
1084 // selected state
415a0ff1 1085 { selected_checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1086
1087 // disabled state
415a0ff1 1088 { disabled_checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1089
1090 // disabled selected state
415a0ff1 1091 { selected_disabled_checked_menu_xpm, NULL, NULL },
1e6feb95
VZ
1092 }
1093};
1094
147b8a4a 1095const char **wxWin32Renderer::ms_xpmChecked[IndicatorStatus_Max] =
e3400e2e
VZ
1096{
1097 checked_item_xpm,
1098 unchecked_item_xpm
1099};
1100
1e6feb95
VZ
1101// ============================================================================
1102// implementation
1103// ============================================================================
1104
1105WX_IMPLEMENT_THEME(wxWin32Theme, win32, wxTRANSLATE("Win32 theme"));
1106
1107// ----------------------------------------------------------------------------
1108// wxWin32Theme
1109// ----------------------------------------------------------------------------
1110
1111wxWin32Theme::wxWin32Theme()
1112{
240889a1
VS
1113 m_scheme = NULL;
1114 m_renderer = NULL;
9ef3ebfb 1115 m_artProvider = NULL;
1e6feb95
VZ
1116}
1117
1118wxWin32Theme::~wxWin32Theme()
1119{
1e6feb95
VZ
1120 delete m_renderer;
1121 delete m_scheme;
571d2e0f 1122 delete m_artProvider;
1e6feb95
VZ
1123}
1124
240889a1
VS
1125wxRenderer *wxWin32Theme::GetRenderer()
1126{
1127 if ( !m_renderer )
1128 {
1129 m_renderer = new wxWin32Renderer(GetColourScheme());
1130 }
1131
1132 return m_renderer;
1133}
1134
536b70ac
VS
1135wxArtProvider *wxWin32Theme::GetArtProvider()
1136{
1137 if ( !m_artProvider )
1138 {
1139 m_artProvider = new wxWin32ArtProvider;
1140 }
1141
1142 return m_artProvider;
1143}
1144
9467bdb7
VZ
1145wxInputHandler *
1146wxWin32Theme::GetInputHandler(const wxString& control,
1147 wxInputConsumer *consumer)
1e6feb95 1148{
9a6384ca 1149 wxInputHandler *handler = NULL;
1e6feb95
VZ
1150 int n = m_handlerNames.Index(control);
1151 if ( n == wxNOT_FOUND )
1152 {
9467bdb7
VZ
1153 static wxWin32InputHandler s_handlerDef;
1154
1155 wxInputHandler * const
1156 handlerStd = consumer->DoGetStdInputHandler(&s_handlerDef);
1157
1e6feb95 1158 // create a new handler
9467bdb7 1159 if ( control == wxINP_HANDLER_TOPLEVEL )
9a6384ca 1160 {
9467bdb7
VZ
1161 static wxWin32FrameInputHandler s_handler(handlerStd);
1162
1163 handler = &s_handler;
9a6384ca 1164 }
1e6feb95
VZ
1165#if wxUSE_CHECKBOX
1166 else if ( control == wxINP_HANDLER_CHECKBOX )
9467bdb7
VZ
1167 {
1168 static wxWin32CheckboxInputHandler s_handler(handlerStd);
1169
1170 handler = &s_handler;
1171 }
1e6feb95 1172#endif // wxUSE_CHECKBOX
9467bdb7
VZ
1173#if wxUSE_SCROLLBAR
1174 else if ( control == wxINP_HANDLER_SCROLLBAR )
1175 {
1176 static wxWin32ScrollBarInputHandler
1177 s_handler(GetRenderer(), handlerStd);
1178
1179 handler = &s_handler;
1180 }
1181#endif // wxUSE_SCROLLBAR
71e03035
VZ
1182#if wxUSE_STATUSBAR
1183 else if ( control == wxINP_HANDLER_STATUSBAR )
9467bdb7
VZ
1184 {
1185 static wxWin32StatusBarInputHandler s_handler(handlerStd);
1186
1187 handler = &s_handler;
1188 }
71e03035 1189#endif // wxUSE_STATUSBAR
9467bdb7
VZ
1190#if wxUSE_TEXTCTRL
1191 else if ( control == wxINP_HANDLER_TEXTCTRL )
1192 {
1193 static wxWin32TextCtrlInputHandler s_handler(handlerStd);
9a6384ca 1194
9467bdb7
VZ
1195 handler = &s_handler;
1196 }
1197#endif // wxUSE_TEXTCTRL
1198 else // no special handler for this control
1199 {
1200 handler = handlerStd;
1201 }
1e6feb95
VZ
1202
1203 n = m_handlerNames.Add(control);
1204 m_handlers.Insert(handler, n);
1205 }
1206 else // we already have it
1207 {
1208 handler = m_handlers[n];
1209 }
1210
1211 return handler;
1212}
1213
1214wxColourScheme *wxWin32Theme::GetColourScheme()
1215{
240889a1
VS
1216 if ( !m_scheme )
1217 {
1218 m_scheme = new wxWin32ColourScheme;
1219 }
1e6feb95
VZ
1220 return m_scheme;
1221}
1222
1223// ============================================================================
1224// wxWin32ColourScheme
1225// ============================================================================
1226
1227wxColour wxWin32ColourScheme::GetBackground(wxWindow *win) const
1228{
1229 wxColour col;
1230 if ( win->UseBgCol() )
1231 {
1232 // use the user specified colour
1233 col = win->GetBackgroundColour();
1234 }
1235
230205ae 1236 if ( !win->ShouldInheritColours() )
1e6feb95 1237 {
9a6384ca 1238#if wxUSE_TEXTCTRL
1e6feb95 1239 wxTextCtrl *text = wxDynamicCast(win, wxTextCtrl);
9a6384ca 1240#endif // wxUSE_TEXTCTRL
aeb3c1cb
JS
1241#if wxUSE_LISTBOX
1242 wxListBox* listBox = wxDynamicCast(win, wxListBox);
9a6384ca
WS
1243#endif // wxUSE_LISTBOX
1244
1245#if wxUSE_TEXTCTRL
aeb3c1cb
JS
1246 if ( text
1247#if wxUSE_LISTBOX
1248 || listBox
00e086a7 1249#endif
aeb3c1cb 1250 )
1e6feb95 1251 {
aeb3c1cb 1252 if ( !win->IsEnabled() ) // not IsEditable()
1e6feb95 1253 col = Get(CONTROL);
aeb3c1cb
JS
1254 else
1255 {
1256 if ( !col.Ok() )
1257 {
1258 // doesn't depend on the state
1259 col = Get(WINDOW);
1260 }
1261 }
1e6feb95 1262 }
9a6384ca 1263#endif // wxUSE_TEXTCTRL
00e086a7 1264
aeb3c1cb
JS
1265 if (!col.Ok())
1266 col = Get(CONTROL); // Most controls should be this colour, not WINDOW
1e6feb95
VZ
1267 }
1268 else
1269 {
1270 int flags = win->GetStateFlags();
1271
1272 // the colour set by the user should be used for the normal state
1273 // and for the states for which we don't have any specific colours
072a81ba 1274 if ( !col.Ok() || (flags & wxCONTROL_PRESSED) != 0 )
1e6feb95 1275 {
9a6384ca 1276#if wxUSE_SCROLLBAR
1e6feb95
VZ
1277 if ( wxDynamicCast(win, wxScrollBar) )
1278 col = Get(flags & wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
1279 : SCROLLBAR);
1280 else
9a6384ca 1281#endif // wxUSE_SCROLLBAR
1e6feb95
VZ
1282 col = Get(CONTROL);
1283 }
1284 }
1285
1286 return col;
1287}
1288
1289wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const
1290{
1291 switch ( col )
1292 {
16bdba2c
VZ
1293 // use the system colours under Windows
1294#if defined(__WXMSW__)
1295 case WINDOW: return wxColour(GetSysColor(COLOR_WINDOW));
1296
1297 case CONTROL_PRESSED:
1298 case CONTROL_CURRENT:
1299 case CONTROL: return wxColour(GetSysColor(COLOR_BTNFACE));
1300
1301 case CONTROL_TEXT: return wxColour(GetSysColor(COLOR_BTNTEXT));
1302
5d3769f5
VZ
1303#if defined(COLOR_3DLIGHT)
1304 case SCROLLBAR: return wxColour(GetSysColor(COLOR_3DLIGHT));
1305#else
1306 case SCROLLBAR: return wxColour(0xe0e0e0);
1307#endif
1308 case SCROLLBAR_PRESSED: return wxColour(GetSysColor(COLOR_BTNTEXT));
16bdba2c
VZ
1309
1310 case HIGHLIGHT: return wxColour(GetSysColor(COLOR_HIGHLIGHT));
1311 case HIGHLIGHT_TEXT: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT));
1312
1313#if defined(COLOR_3DDKSHADOW)
1314 case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DDKSHADOW));
1315#else
a407ff6a 1316 case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DHADOW));
16bdba2c
VZ
1317#endif
1318
1319 case CONTROL_TEXT_DISABLED:
1320 case SHADOW_HIGHLIGHT: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT));
1321
1322 case SHADOW_IN: return wxColour(GetSysColor(COLOR_BTNFACE));
1323
1324 case CONTROL_TEXT_DISABLED_SHADOW:
1325 case SHADOW_OUT: return wxColour(GetSysColor(COLOR_BTNSHADOW));
71e03035 1326
24a23c35
VS
1327 case TITLEBAR: return wxColour(GetSysColor(COLOR_INACTIVECAPTION));
1328 case TITLEBAR_ACTIVE: return wxColour(GetSysColor(COLOR_ACTIVECAPTION));
6296744f
VS
1329 case TITLEBAR_TEXT: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
1330 case TITLEBAR_ACTIVE_TEXT: return wxColour(GetSysColor(COLOR_CAPTIONTEXT));
d1504049 1331
6296744f 1332 case DESKTOP: return wxColour(0x808000);
9c6d8b7c 1333 case FRAME: return wxColour(GetSysColor(COLOR_APPWORKSPACE));
16bdba2c
VZ
1334#else // !__WXMSW__
1335 // use the standard Windows colours elsewhere
86313763
VZ
1336 case WINDOW: return *wxWHITE;
1337
1e6feb95
VZ
1338 case CONTROL_PRESSED:
1339 case CONTROL_CURRENT:
1340 case CONTROL: return wxColour(0xc0c0c0);
1341
1342 case CONTROL_TEXT: return *wxBLACK;
1343
1344 case SCROLLBAR: return wxColour(0xe0e0e0);
1345 case SCROLLBAR_PRESSED: return *wxBLACK;
1346
1347 case HIGHLIGHT: return wxColour(0x800000);
1348 case HIGHLIGHT_TEXT: return wxColour(0xffffff);
1349
1350 case SHADOW_DARK: return *wxBLACK;
1351
24a23c35
VS
1352 case CONTROL_TEXT_DISABLED:return wxColour(0xe0e0e0);
1353 case SHADOW_HIGHLIGHT: return wxColour(0xffffff);
1e6feb95
VZ
1354
1355 case SHADOW_IN: return wxColour(0xc0c0c0);
1356
1357 case CONTROL_TEXT_DISABLED_SHADOW:
1358 case SHADOW_OUT: return wxColour(0x7f7f7f);
24a23c35
VS
1359
1360 case TITLEBAR: return wxColour(0xaeaaae);
1361 case TITLEBAR_ACTIVE: return wxColour(0x820300);
6296744f
VS
1362 case TITLEBAR_TEXT: return wxColour(0xc0c0c0);
1363 case TITLEBAR_ACTIVE_TEXT:return *wxWHITE;
1364
1365 case DESKTOP: return wxColour(0x808000);
9c6d8b7c 1366 case FRAME: return wxColour(0x808080);
16bdba2c 1367#endif // __WXMSW__
1e6feb95 1368
a407ff6a
VZ
1369 case GAUGE: return Get(HIGHLIGHT);
1370
1e6feb95
VZ
1371 case MAX:
1372 default:
9a83f860 1373 wxFAIL_MSG(wxT("invalid standard colour"));
1e6feb95
VZ
1374 return *wxBLACK;
1375 }
1376}
1377
1378// ============================================================================
1379// wxWin32Renderer
1380// ============================================================================
1381
1382// ----------------------------------------------------------------------------
1383// construction
1384// ----------------------------------------------------------------------------
1385
1386wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme)
147b8a4a 1387 : wxStdRenderer(scheme)
1e6feb95
VZ
1388{
1389 // init data
1e6feb95
VZ
1390 m_sizeScrollbarArrow = wxSize(16, 16);
1391
1e6feb95
VZ
1392 // init the arrow bitmaps
1393 static const size_t ARROW_WIDTH = 7;
1394 static const size_t ARROW_LENGTH = 4;
1395
1396 wxMask *mask;
1397 wxMemoryDC dcNormal,
1398 dcDisabled,
1399 dcInverse;
1400 for ( size_t n = 0; n < Arrow_Max; n++ )
1401 {
1402 bool isVertical = n > Arrow_Right;
1403 int w, h;
1404 if ( isVertical )
1405 {
1406 w = ARROW_WIDTH;
1407 h = ARROW_LENGTH;
1408 }
1409 else
1410 {
1411 h = ARROW_WIDTH;
1412 w = ARROW_LENGTH;
1413 }
1414
1415 // disabled arrow is larger because of the shadow
1416 m_bmpArrows[Arrow_Normal][n].Create(w, h);
1417 m_bmpArrows[Arrow_Disabled][n].Create(w + 1, h + 1);
1418
1419 dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]);
1420 dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]);
1421
1422 dcNormal.SetBackground(*wxWHITE_BRUSH);
1423 dcDisabled.SetBackground(*wxWHITE_BRUSH);
1424 dcNormal.Clear();
1425 dcDisabled.Clear();
1426
1427 dcNormal.SetPen(m_penBlack);
1428 dcDisabled.SetPen(m_penDarkGrey);
1429
1430 // calculate the position of the point of the arrow
1431 wxCoord x1, y1;
1432 if ( isVertical )
1433 {
1434 x1 = (ARROW_WIDTH - 1)/2;
1435 y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1;
1436 }
1437 else // horizontal
1438 {
1439 x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1;
1440 y1 = (ARROW_WIDTH - 1)/2;
1441 }
1442
1443 wxCoord x2 = x1,
1444 y2 = y1;
1445
1446 if ( isVertical )
1447 x2++;
1448 else
1449 y2++;
1450
1451 for ( size_t i = 0; i < ARROW_LENGTH; i++ )
1452 {
1453 dcNormal.DrawLine(x1, y1, x2, y2);
1454 dcDisabled.DrawLine(x1, y1, x2, y2);
1455
1456 if ( isVertical )
1457 {
1458 x1--;
1459 x2++;
1460
1461 if ( n == Arrow_Up )
1462 {
1463 y1++;
1464 y2++;
1465 }
1466 else // down arrow
1467 {
1468 y1--;
1469 y2--;
1470 }
1471 }
1472 else // left or right arrow
1473 {
1474 y1--;
1475 y2++;
1476
1477 if ( n == Arrow_Left )
1478 {
1479 x1++;
1480 x2++;
1481 }
1482 else
1483 {
1484 x1--;
1485 x2--;
1486 }
1487 }
1488 }
1489
1490 // draw the shadow for the disabled one
1491 dcDisabled.SetPen(m_penHighlight);
1492 switch ( n )
1493 {
1494 case Arrow_Left:
1495 y1 += 2;
1496 dcDisabled.DrawLine(x1, y1, x2, y2);
1497 break;
1498
1499 case Arrow_Right:
1500 x1 = ARROW_LENGTH - 1;
1501 y1 = (ARROW_WIDTH - 1)/2 + 1;
1502 x2 = 0;
1503 y2 = ARROW_WIDTH;
1504 dcDisabled.DrawLine(x1, y1, x2, y2);
1505 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1506 break;
1507
1508 case Arrow_Up:
1509 x1 += 2;
1510 dcDisabled.DrawLine(x1, y1, x2, y2);
1511 break;
1512
1513 case Arrow_Down:
1514 x1 = ARROW_WIDTH - 1;
1515 y1 = 1;
1516 x2 = (ARROW_WIDTH - 1)/2;
1517 y2 = ARROW_LENGTH;
1518 dcDisabled.DrawLine(x1, y1, x2, y2);
1519 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1520 break;
1521
1522 }
1523
d6922577 1524 // create the inverted bitmap but only for the right arrow as we only
1e6feb95
VZ
1525 // use it for the menus
1526 if ( n == Arrow_Right )
1527 {
d6922577
JS
1528 m_bmpArrows[Arrow_Inverted][n].Create(w, h);
1529 dcInverse.SelectObject(m_bmpArrows[Arrow_Inverted][n]);
1e6feb95
VZ
1530 dcInverse.Clear();
1531 dcInverse.Blit(0, 0, w, h,
1532 &dcNormal, 0, 0,
1533 wxXOR);
1534 dcInverse.SelectObject(wxNullBitmap);
1535
d6922577
JS
1536 mask = new wxMask(m_bmpArrows[Arrow_Inverted][n], *wxBLACK);
1537 m_bmpArrows[Arrow_Inverted][n].SetMask(mask);
1e6feb95 1538
d6922577
JS
1539 m_bmpArrows[Arrow_InvertedDisabled][n].Create(w, h);
1540 dcInverse.SelectObject(m_bmpArrows[Arrow_InvertedDisabled][n]);
1e6feb95
VZ
1541 dcInverse.Clear();
1542 dcInverse.Blit(0, 0, w, h,
1543 &dcDisabled, 0, 0,
1544 wxXOR);
1545 dcInverse.SelectObject(wxNullBitmap);
1546
d6922577
JS
1547 mask = new wxMask(m_bmpArrows[Arrow_InvertedDisabled][n], *wxBLACK);
1548 m_bmpArrows[Arrow_InvertedDisabled][n].SetMask(mask);
1e6feb95
VZ
1549 }
1550
1551 dcNormal.SelectObject(wxNullBitmap);
1552 dcDisabled.SelectObject(wxNullBitmap);
1553
1554 mask = new wxMask(m_bmpArrows[Arrow_Normal][n], *wxWHITE);
1555 m_bmpArrows[Arrow_Normal][n].SetMask(mask);
1556 mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
1557 m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
1558
1559 m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
1560 }
1561}
1562
1e6feb95
VZ
1563bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1564{
a290fa5a 1565 return true;
1e6feb95
VZ
1566}
1567
1e6feb95
VZ
1568// ----------------------------------------------------------------------------
1569// label
1570// ----------------------------------------------------------------------------
1571
1e6feb95
VZ
1572void wxWin32Renderer::DrawLabel(wxDC& dc,
1573 const wxString& label,
1574 const wxRect& rect,
1575 int flags,
1576 int alignment,
1577 int indexAccel,
1578 wxRect *rectBounds)
1e6feb95
VZ
1579{
1580 // the underscores are not drawn for focused controls in wxMSW
1581 if ( flags & wxCONTROL_FOCUSED )
1582 {
1583 indexAccel = -1;
1584 }
1585
1586 if ( flags & wxCONTROL_DISABLED )
1587 {
1588 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1589 // currently only can happen for a menu item and it seems that Windows
1590 // doesn't draw the shadow in this case, so we don't do it neither
1591 if ( flags & wxCONTROL_SELECTED )
1592 {
1593 // just make the label text greyed out
147b8a4a
VZ
1594 dc.SetTextForeground(m_penDarkGrey.GetColour());
1595
1596 flags &= ~wxCONTROL_DISABLED;
1e6feb95
VZ
1597 }
1598 }
1599
147b8a4a
VZ
1600 wxStdRenderer::DrawLabel(dc, label, rect, flags, alignment,
1601 indexAccel, rectBounds);
1602}
1e6feb95 1603
147b8a4a
VZ
1604void wxWin32Renderer::DrawFrameWithLabel(wxDC& dc,
1605 const wxString& label,
1606 const wxRect& rectFrame,
1607 const wxRect& rectText,
1608 int flags,
1609 int alignment,
1610 int indexAccel)
1611{
1612 wxString label2;
9a83f860 1613 label2 << wxT(' ') << label << wxT(' ');
147b8a4a 1614 if ( indexAccel != -1 )
1e6feb95 1615 {
147b8a4a
VZ
1616 // adjust it as we prepended a space
1617 indexAccel++;
1e6feb95
VZ
1618 }
1619
147b8a4a
VZ
1620 wxStdRenderer::DrawFrameWithLabel(dc, label2, rectFrame, rectText,
1621 flags, alignment, indexAccel);
1e6feb95
VZ
1622}
1623
1624void wxWin32Renderer::DrawButtonLabel(wxDC& dc,
1625 const wxString& label,
1626 const wxBitmap& image,
1627 const wxRect& rect,
1628 int flags,
1629 int alignment,
1630 int indexAccel,
1631 wxRect *rectBounds)
1632{
1633 // the underscores are not drawn for focused controls in wxMSW
1634 if ( flags & wxCONTROL_PRESSED )
1635 {
1636 indexAccel = -1;
1637 }
1638
147b8a4a
VZ
1639 wxStdRenderer::DrawButtonLabel(dc, label, image, rect, flags, alignment,
1640 indexAccel, rectBounds);
1641}
1e6feb95 1642
147b8a4a
VZ
1643void wxWin32Renderer::DrawButtonBorder(wxDC& dc,
1644 const wxRect& rectTotal,
1645 int flags,
1646 wxRect *rectIn)
1647{
1648 wxRect rect = rectTotal;
1e6feb95 1649
147b8a4a
VZ
1650 wxPen penOut(*wxBLACK);
1651 if ( flags & wxCONTROL_PRESSED )
1652 {
1653 // button pressed: draw a double border around it
1654 DrawRect(dc, &rect, penOut);
1655 DrawRect(dc, &rect, m_penDarkGrey);
1e6feb95 1656 }
147b8a4a 1657 else // button not pressed
1e6feb95 1658 {
147b8a4a 1659 if ( flags & (wxCONTROL_FOCUSED | wxCONTROL_ISDEFAULT) )
1e6feb95 1660 {
147b8a4a
VZ
1661 // button either default or focused (or both): add an extra border
1662 // around it
1663 DrawRect(dc, &rect, penOut);
1e6feb95
VZ
1664 }
1665
147b8a4a
VZ
1666 // now draw a normal button border
1667 DrawRaisedBorder(dc, &rect);
1e6feb95 1668 }
147b8a4a
VZ
1669
1670 if ( rectIn )
1671 *rectIn = rect;
1e6feb95
VZ
1672}
1673
1674// ----------------------------------------------------------------------------
1675// (check)listbox items
1676// ----------------------------------------------------------------------------
1677
6229b92f
VZ
1678void wxWin32Renderer::DrawCheckItemBitmap(wxDC& dc,
1679 const wxBitmap& bitmap,
1680 const wxRect& rect,
1681 int flags)
1e6feb95
VZ
1682{
1683 wxBitmap bmp;
1684 if ( bitmap.Ok() )
1685 {
1686 bmp = bitmap;
1687 }
1688 else // use default bitmap
1689 {
e3400e2e
VZ
1690 IndicatorStatus i = flags & wxCONTROL_CHECKED
1691 ? IndicatorStatus_Checked
1692 : IndicatorStatus_Unchecked;
1693
1694 if ( !m_bmpCheckBitmaps[i].Ok() )
1695 {
147b8a4a 1696 m_bmpCheckBitmaps[i] = wxBitmap(ms_xpmChecked[i]);
e3400e2e
VZ
1697 }
1698
1699 bmp = m_bmpCheckBitmaps[i];
1e6feb95
VZ
1700 }
1701
1702 dc.DrawBitmap(bmp, rect.x, rect.y + (rect.height - bmp.GetHeight()) / 2 - 1,
a290fa5a 1703 true /* use mask */);
1e6feb95
VZ
1704}
1705
1706// ----------------------------------------------------------------------------
1707// check/radio buttons
1708// ----------------------------------------------------------------------------
1709
1710wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags)
1711{
1712 IndicatorState indState;
147b8a4a
VZ
1713 IndicatorStatus indStatus;
1714 GetIndicatorsFromFlags(flags, indState, indStatus);
1e6feb95 1715
0428ac8c 1716 wxBitmap& bmp = m_bmpIndicators[indType][indState][indStatus];
e3400e2e 1717 if ( !bmp.Ok() )
54a96d02 1718 {
147b8a4a 1719 const char **xpm = ms_xpmIndicators[indType][indState][indStatus];
e3400e2e
VZ
1720 if ( xpm )
1721 {
1722 // create and cache it
1723 bmp = wxBitmap(xpm);
e3400e2e 1724 }
54a96d02 1725 }
e3400e2e
VZ
1726
1727 return bmp;
1e6feb95
VZ
1728}
1729
6229b92f
VZ
1730// ----------------------------------------------------------------------------
1731// toolbar stuff
1732// ----------------------------------------------------------------------------
1733
9a6384ca 1734#if wxUSE_TOOLBAR
3216dbf5
VZ
1735void wxWin32Renderer::DrawToolBarButton(wxDC& dc,
1736 const wxString& label,
1737 const wxBitmap& bitmap,
1738 const wxRect& rectOrig,
a8f4cabe 1739 int flags,
370efbe7
WS
1740 long style,
1741 int tbarStyle)
3216dbf5 1742{
a8f4cabe 1743 if (style == wxTOOL_STYLE_BUTTON)
3216dbf5
VZ
1744 {
1745 wxRect rect = rectOrig;
1746 rect.Deflate(BORDER_THICKNESS);
1747
1748 if ( flags & wxCONTROL_PRESSED )
1749 {
1750 DrawBorder(dc, wxBORDER_SUNKEN, rect, flags);
1751 }
1752 else if ( flags & wxCONTROL_CURRENT )
1753 {
1754 DrawBorder(dc, wxBORDER_RAISED, rect, flags);
1755 }
1756
370efbe7
WS
1757 if(tbarStyle & wxTB_TEXT)
1758 {
1759 if(tbarStyle & wxTB_HORIZONTAL)
1760 {
1761 dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
1762 }
1763 else
1764 {
1765 dc.DrawLabel(label, bitmap, rect, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
1766 }
1767 }
1768 else
1769 {
1770 int xpoint = (rect.GetLeft() + rect.GetRight() + 1 - bitmap.GetWidth()) / 2;
1771 int ypoint = (rect.GetTop() + rect.GetBottom() + 1 - bitmap.GetHeight()) / 2;
ffd73a2c 1772 dc.DrawBitmap(bitmap, xpoint, ypoint, bitmap.GetMask() != NULL);
370efbe7 1773 }
3216dbf5 1774 }
a8f4cabe 1775 else if (style == wxTOOL_STYLE_SEPARATOR)
3216dbf5 1776 {
2d3cddaf
VZ
1777 // leave a small gap aroudn the line, also account for the toolbar
1778 // border itself
1f7e5f7b
WS
1779 if(rectOrig.height > rectOrig.width)
1780 {
1781 // horizontal
1782 DrawVerticalLine(dc, rectOrig.x + rectOrig.width/2,
1783 rectOrig.y + 2*BORDER_THICKNESS,
1784 rectOrig.GetBottom() - BORDER_THICKNESS);
1785 }
1786 else
1787 {
1788 // vertical
1789 DrawHorizontalLine(dc, rectOrig.y + rectOrig.height/2,
1790 rectOrig.x + 2*BORDER_THICKNESS,
1791 rectOrig.GetRight() - BORDER_THICKNESS);
1792 }
3216dbf5 1793 }
a8f4cabe 1794 // don't draw wxTOOL_STYLE_CONTROL
3216dbf5 1795}
9a6384ca 1796#endif // wxUSE_TOOLBAR
3216dbf5 1797
1e6feb95
VZ
1798// ----------------------------------------------------------------------------
1799// notebook
1800// ----------------------------------------------------------------------------
1801
c4036939
VZ
1802#if wxUSE_NOTEBOOK
1803
1e6feb95
VZ
1804void wxWin32Renderer::DrawTab(wxDC& dc,
1805 const wxRect& rectOrig,
1806 wxDirection dir,
1807 const wxString& label,
1808 const wxBitmap& bitmap,
1809 int flags,
1810 int indexAccel)
1811{
00e086a7
WS
1812 #define SELECT_FOR_VERTICAL(X,Y) ( isVertical ? Y : X )
1813 #define REVERSE_FOR_VERTICAL(X,Y) \
1814 SELECT_FOR_VERTICAL(X,Y) \
1815 , \
1816 SELECT_FOR_VERTICAL(Y,X)
1817
1e6feb95
VZ
1818 wxRect rect = rectOrig;
1819
00e086a7
WS
1820 bool isVertical = ( dir == wxLEFT ) || ( dir == wxRIGHT );
1821
1e6feb95
VZ
1822 // the current tab is drawn indented (to the top for default case) and
1823 // bigger than the other ones
1824 const wxSize indent = GetTabIndent();
1825 if ( flags & wxCONTROL_SELECTED )
1826 {
7166a05d
WS
1827 rect.Inflate( SELECT_FOR_VERTICAL( indent.x , 0),
1828 SELECT_FOR_VERTICAL( 0, indent.y ));
1e6feb95
VZ
1829 switch ( dir )
1830 {
1831 default:
9a83f860 1832 wxFAIL_MSG(wxT("invaild notebook tab orientation"));
1e6feb95
VZ
1833 // fall through
1834
1835 case wxTOP:
1e6feb95 1836 rect.y -= indent.y;
00e086a7 1837 // fall through
1e6feb95 1838 case wxBOTTOM:
1e6feb95
VZ
1839 rect.height += indent.y;
1840 break;
1841
1842 case wxLEFT:
00e086a7
WS
1843 rect.x -= indent.x;
1844 // fall through
1e6feb95 1845 case wxRIGHT:
00e086a7 1846 rect.width += indent.x;
1e6feb95
VZ
1847 break;
1848 }
1849 }
1850
1851 // draw the text, image and the focus around them (if necessary)
00e086a7
WS
1852 wxRect rectLabel( REVERSE_FOR_VERTICAL(rect.x,rect.y),
1853 REVERSE_FOR_VERTICAL(rect.width,rect.height)
1854 );
1e6feb95 1855 rectLabel.Deflate(1, 1);
00e086a7
WS
1856 if ( isVertical )
1857 {
1858 // draw it horizontally into memory and rotate for screen
1859 wxMemoryDC dcMem;
1860 wxBitmap bitmapRotated,
1861 bitmapMem( rectLabel.x + rectLabel.width,
1862 rectLabel.y + rectLabel.height );
1863 dcMem.SelectObject(bitmapMem);
1864 dcMem.SetBackground(dc.GetBackground());
1865 dcMem.SetFont(dc.GetFont());
1866 dcMem.SetTextForeground(dc.GetTextForeground());
1867 dcMem.Clear();
9a6384ca
WS
1868 bitmapRotated =
1869#if wxUSE_IMAGE
1870 wxBitmap( wxImage( bitmap.ConvertToImage() ).Rotate90(dir==wxLEFT) )
1871#else
1872 bitmap
1873#endif // wxUSE_IMAGE
1874 ;
00e086a7
WS
1875 DrawButtonLabel(dcMem, label, bitmapRotated, rectLabel,
1876 flags, wxALIGN_CENTRE, indexAccel);
1877 dcMem.SelectObject(wxNullBitmap);
1878 bitmapMem = bitmapMem.GetSubBitmap(rectLabel);
9a6384ca 1879#if wxUSE_IMAGE
00e086a7 1880 bitmapMem = wxBitmap(wxImage(bitmapMem.ConvertToImage()).Rotate90(dir==wxRIGHT));
9a6384ca 1881#endif // wxUSE_IMAGE
00e086a7
WS
1882 dc.DrawBitmap(bitmapMem, rectLabel.y, rectLabel.x, false);
1883 }
1884 else
1885 {
1886 DrawButtonLabel(dc, label, bitmap, rectLabel,
1887 flags, wxALIGN_CENTRE, indexAccel);
1888 }
1e6feb95
VZ
1889
1890 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
1891 static const wxCoord CUTOFF = 2; // radius of the rounded corner
00e086a7
WS
1892 wxCoord x = SELECT_FOR_VERTICAL(rect.x,rect.y),
1893 y = SELECT_FOR_VERTICAL(rect.y,rect.x),
1894 x2 = SELECT_FOR_VERTICAL(rect.GetRight(),rect.GetBottom()),
1895 y2 = SELECT_FOR_VERTICAL(rect.GetBottom(),rect.GetRight());
1e6feb95
VZ
1896
1897 // FIXME: all this code will break if the tab indent or the border width,
1898 // it is tied to the fact that both of them are equal to 2
1899 switch ( dir )
1900 {
1901 default:
00e086a7
WS
1902 // default is top
1903 case wxLEFT:
1904 // left orientation looks like top but IsVertical makes x and y reversed
1e6feb95 1905 case wxTOP:
00e086a7 1906 // top is not vertical so use coordinates in written order
1e6feb95 1907 dc.SetPen(m_penHighlight);
00e086a7
WS
1908 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y2),
1909 REVERSE_FOR_VERTICAL(x, y + CUTOFF));
1910 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y + CUTOFF),
1911 REVERSE_FOR_VERTICAL(x + CUTOFF, y));
1912 dc.DrawLine(REVERSE_FOR_VERTICAL(x + CUTOFF, y),
1913 REVERSE_FOR_VERTICAL(x2 - CUTOFF + 1, y));
1e6feb95
VZ
1914
1915 dc.SetPen(m_penBlack);
00e086a7
WS
1916 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2),
1917 REVERSE_FOR_VERTICAL(x2, y + CUTOFF));
1918 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y + CUTOFF),
1919 REVERSE_FOR_VERTICAL(x2 - CUTOFF, y));
1e6feb95
VZ
1920
1921 dc.SetPen(m_penDarkGrey);
00e086a7
WS
1922 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y2),
1923 REVERSE_FOR_VERTICAL(x2 - 1, y + CUTOFF - 1));
1e6feb95
VZ
1924
1925 if ( flags & wxCONTROL_SELECTED )
1926 {
1927 dc.SetPen(m_penLightGrey);
1928
1929 // overwrite the part of the border below this tab
00e086a7
WS
1930 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 + 1),
1931 REVERSE_FOR_VERTICAL(x2 - 1, y2 + 1));
1e6feb95
VZ
1932
1933 // and the shadow of the tab to the left of us
00e086a7
WS
1934 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y + CUTOFF + 1),
1935 REVERSE_FOR_VERTICAL(x + 1, y2 + 1));
1e6feb95
VZ
1936 }
1937 break;
1938
00e086a7
WS
1939 case wxRIGHT:
1940 // right orientation looks like bottom but IsVertical makes x and y reversed
1e6feb95 1941 case wxBOTTOM:
00e086a7 1942 // bottom is not vertical so use coordinates in written order
1e6feb95
VZ
1943 dc.SetPen(m_penHighlight);
1944 // we need to continue one pixel further to overwrite the corner of
1945 // the border for the selected tab
00e086a7
WS
1946 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0)),
1947 REVERSE_FOR_VERTICAL(x, y2 - CUTOFF));
1948 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y2 - CUTOFF),
1949 REVERSE_FOR_VERTICAL(x + CUTOFF, y2));
1e6feb95
VZ
1950
1951 dc.SetPen(m_penBlack);
00e086a7
WS
1952 dc.DrawLine(REVERSE_FOR_VERTICAL(x + CUTOFF, y2),
1953 REVERSE_FOR_VERTICAL(x2 - CUTOFF + 1, y2));
1954 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y),
1955 REVERSE_FOR_VERTICAL(x2, y2 - CUTOFF));
1956 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2 - CUTOFF),
1957 REVERSE_FOR_VERTICAL(x2 - CUTOFF, y2));
1e6feb95
VZ
1958
1959 dc.SetPen(m_penDarkGrey);
00e086a7
WS
1960 dc.DrawLine(REVERSE_FOR_VERTICAL(x + CUTOFF, y2 - 1),
1961 REVERSE_FOR_VERTICAL(x2 - CUTOFF + 1, y2 - 1));
1962 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y),
1963 REVERSE_FOR_VERTICAL(x2 - 1, y2 - CUTOFF + 1));
1e6feb95
VZ
1964
1965 if ( flags & wxCONTROL_SELECTED )
1966 {
1967 dc.SetPen(m_penLightGrey);
1968
1969 // overwrite the part of the (double!) border above this tab
00e086a7
WS
1970 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 1),
1971 REVERSE_FOR_VERTICAL(x2 - 1, y - 1));
1972 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 2),
1973 REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1e6feb95
VZ
1974
1975 // and the shadow of the tab to the left of us
00e086a7
WS
1976 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 - CUTOFF),
1977 REVERSE_FOR_VERTICAL(x + 1, y - 1));
1e6feb95
VZ
1978 }
1979 break;
1e6feb95 1980 }
00e086a7
WS
1981
1982 #undef SELECT_FOR_VERTICAL
1983 #undef REVERSE_FOR_VERTICAL
1e6feb95
VZ
1984}
1985
c4036939
VZ
1986#endif // wxUSE_NOTEBOOK
1987
9a6384ca
WS
1988#if wxUSE_SLIDER
1989
1e6feb95
VZ
1990// ----------------------------------------------------------------------------
1991// slider
1992// ----------------------------------------------------------------------------
1993
61fef19b
VZ
1994wxSize
1995wxWin32Renderer::GetSliderThumbSize(const wxRect& WXUNUSED(rect),
1996 int lenThumb,
1997 wxOrientation orient) const
1e6feb95
VZ
1998{
1999 wxSize size;
6766e5d1
JS
2000 wxCoord width = wxMax (lenThumb, SLIDER_THUMB_LENGTH) / 2;
2001 wxCoord height = wxMax (lenThumb, SLIDER_THUMB_LENGTH);
1e6feb95 2002
00e086a7 2003 if (orient == wxHORIZONTAL)
1e6feb95 2004 {
6766e5d1
JS
2005 size.x = width;
2006 size.y = height;
1e6feb95 2007 }
6766e5d1
JS
2008 else
2009 { // == wxVERTICAL
2010 size.x = height;
2011 size.y = width;
1e6feb95
VZ
2012 }
2013
2014 return size;
2015}
2016
2017wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
6766e5d1
JS
2018 int lenThumb,
2019 wxOrientation orient,
2020 long style) const
1e6feb95 2021{
4462f911
VZ
2022 bool left, right;
2023 GetSliderLabelsSides(orient, style, &left, &right);
1e6feb95
VZ
2024
2025 wxRect rect = rectOrig;
2026
6766e5d1 2027 wxSize sizeThumb = GetSliderThumbSize (rect, lenThumb, orient);
1e6feb95 2028
4462f911
VZ
2029 if (orient == wxHORIZONTAL)
2030 {
6766e5d1 2031 rect.x += SLIDER_MARGIN;
00e086a7 2032 if (left & right)
6766e5d1
JS
2033 {
2034 rect.y += wxMax ((rect.height - 2*BORDER_THICKNESS) / 2, sizeThumb.y/2);
2035 }
00e086a7 2036 else if (left)
6766e5d1
JS
2037 {
2038 rect.y += wxMax ((rect.height - 2*BORDER_THICKNESS - sizeThumb.y/2), sizeThumb.y/2);
2039 }
2040 else
2041 {
2042 rect.y += sizeThumb.y/2;
2043 }
2044 rect.width -= 2*SLIDER_MARGIN;
2045 rect.height = 2*BORDER_THICKNESS;
1e6feb95 2046 }
4462f911
VZ
2047 else // == wxVERTICAL
2048 {
6766e5d1 2049 rect.y += SLIDER_MARGIN;
00e086a7 2050 if (left & right)
6766e5d1
JS
2051 {
2052 rect.x += wxMax ((rect.width - 2*BORDER_THICKNESS) / 2, sizeThumb.x/2);
2053 }
00e086a7 2054 else if (left)
6766e5d1
JS
2055 {
2056 rect.x += wxMax ((rect.width - 2*BORDER_THICKNESS - sizeThumb.x/2), sizeThumb.x/2);
2057 }
2058 else
2059 {
2060 rect.x += sizeThumb.x/2;
2061 }
1e6feb95 2062 rect.width = 2*BORDER_THICKNESS;
6766e5d1 2063 rect.height -= 2*SLIDER_MARGIN;
1e6feb95
VZ
2064 }
2065
2066 return rect;
2067}
2068
2069void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
2070 const wxRect& rectOrig,
6766e5d1 2071 int lenThumb,
1e6feb95
VZ
2072 wxOrientation orient,
2073 int flags,
6766e5d1 2074 long style,
1e6feb95
VZ
2075 wxRect *rectShaft)
2076{
6766e5d1
JS
2077 /* show shaft geometry
2078
2079 shaft
2080 +-------------+
2081 | |
2082 | XXX | <-- x1
2083 | XXX |
2084 | XXX |
2085 | XXX |
2086 | XXX | <-- x2
2087 | |
2088 +-------------+
2089
2090 ^ ^
2091 | |
2092 y1 y2
2093 */
2094
4462f911 2095 if (flags & wxCONTROL_FOCUSED)
6d789987 2096 DrawFocusRect(NULL, dc, rectOrig);
1e6feb95 2097
6766e5d1 2098 wxRect rect = GetSliderShaftRect(rectOrig, lenThumb, orient, style);
1e6feb95 2099
6766e5d1 2100 if (rectShaft) *rectShaft = rect;
1e6feb95
VZ
2101
2102 DrawSunkenBorder(dc, &rect);
2103}
2104
2105void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
2106 const wxRect& rect,
2107 wxOrientation orient,
6766e5d1
JS
2108 int flags,
2109 long style)
1e6feb95 2110{
6766e5d1
JS
2111 /* show thumb geometry
2112
2113 H <--- y1
2114 H H B
2115 H H B
2116 H H B <--- y3
2117 H D B
2118 H D B
2119 H D B
d6922577 2120 H D B where H is highlight colour
6766e5d1
JS
2121 H D B D dark grey
2122 H D B B black
2123 H D B
2124 H D B
2125 H D B <--- y4
2126 H D B
2127 H D B
2128 B <--- y2
2129
2130 ^ ^ ^
2131 | | |
2132 x1 x3 x2
1e6feb95
VZ
2133
2134 The interior of this shape is filled with the hatched brush if the thumb
2135 is pressed.
2136 */
2137
2138 DrawBackground(dc, wxNullColour, rect, flags);
2139
4462f911
VZ
2140 bool left, right;
2141 GetSliderLabelsSides(orient, style, &left, &right);
6766e5d1 2142
4462f911
VZ
2143 bool isVertical = orient == wxVERTICAL;
2144
2145 wxCoord sizeArrow = (isVertical ? rect.height : rect.width) / 2;
2146 wxCoord c = ((isVertical ? rect.height : rect.width) - 2*sizeArrow);
6766e5d1
JS
2147
2148 wxCoord x1, x2, x3, y1, y2, y3, y4;
4462f911
VZ
2149 x1 = (isVertical ? rect.y : rect.x);
2150 x2 = (isVertical ? rect.GetBottom() : rect.GetRight());
6766e5d1 2151 x3 = (x1-1+c) + sizeArrow;
4462f911
VZ
2152 y1 = (isVertical ? rect.x : rect.y);
2153 y2 = (isVertical ? rect.GetRight() : rect.GetBottom());
6766e5d1
JS
2154 y3 = (left ? (y1-1+c) + sizeArrow : y1);
2155 y4 = (right ? (y2+1-c) - sizeArrow : y2);
1e6feb95 2156
6766e5d1 2157 dc.SetPen(m_penBlack);
4462f911
VZ
2158 if (left)
2159 {
2160 DrawLine(dc, x3+1-c, y1, x2, y3, isVertical);
6766e5d1 2161 }
4462f911 2162 DrawLine(dc, x2, y3, x2, y4, isVertical);
00e086a7 2163 if (right)
1e6feb95 2164 {
4462f911 2165 DrawLine(dc, x3+1-c, y2, x2, y4, isVertical);
1e6feb95
VZ
2166 }
2167 else
2168 {
4462f911 2169 DrawLine(dc, x1, y2, x2, y2, isVertical);
1e6feb95
VZ
2170 }
2171
1e6feb95 2172 dc.SetPen(m_penDarkGrey);
4462f911
VZ
2173 DrawLine(dc, x2-1, y3+1, x2-1, y4-1, isVertical);
2174 if (right)
2175 {
2176 DrawLine(dc, x3+1-c, y2-1, x2-1, y4, isVertical);
6766e5d1
JS
2177 }
2178 else
2179 {
4462f911 2180 DrawLine(dc, x1+1, y2-1, x2-1, y2-1, isVertical);
6766e5d1 2181 }
1e6feb95 2182
6766e5d1 2183 dc.SetPen(m_penHighlight);
00e086a7 2184 if (left)
6766e5d1 2185 {
4462f911
VZ
2186 DrawLine(dc, x1, y3, x3, y1, isVertical);
2187 DrawLine(dc, x3+1-c, y1+1, x2-1, y3, isVertical);
6766e5d1
JS
2188 }
2189 else
2190 {
4462f911 2191 DrawLine(dc, x1, y1, x2, y1, isVertical);
6766e5d1 2192 }
4462f911 2193 DrawLine(dc, x1, y3, x1, y4, isVertical);
00e086a7 2194 if (right)
1e6feb95 2195 {
4462f911 2196 DrawLine(dc, x1, y4, x3+c, y2+c, isVertical);
6766e5d1
JS
2197 }
2198
4462f911
VZ
2199 if (flags & wxCONTROL_PRESSED)
2200 {
1e6feb95
VZ
2201 // TODO: MSW fills the entire area inside, not just the rect
2202 wxRect rectInt = rect;
4462f911 2203 if ( isVertical )
6766e5d1
JS
2204 {
2205 rectInt.SetLeft(y3);
2206 rectInt.SetRight(y4);
2207 }
1e6feb95 2208 else
6766e5d1
JS
2209 {
2210 rectInt.SetTop(y3);
2211 rectInt.SetBottom(y4);
2212 }
1e6feb95
VZ
2213 rectInt.Deflate(2);
2214
63f06c22 2215#if !defined(__WXMGL__)
1e6feb95
VZ
2216 static const char *stipple_xpm[] = {
2217 /* columns rows colors chars-per-pixel */
2218 "2 2 2 1",
2219 " c None",
2220 "w c white",
2221 /* pixels */
2222 "w ",
2223 " w",
2224 };
63f06c22
VS
2225#else
2226 // VS: MGL can only do 8x8 stipple brushes
2227 static const char *stipple_xpm[] = {
2228 /* columns rows colors chars-per-pixel */
2229 "8 8 2 1",
2230 " c None",
2231 "w c white",
2232 /* pixels */
2233 "w w w w ",
2234 " w w w w",
2235 "w w w w ",
2236 " w w w w",
2237 "w w w w ",
2238 " w w w w",
2239 "w w w w ",
2240 " w w w w",
2241 };
2242#endif
1e6feb95
VZ
2243 dc.SetBrush(wxBrush(stipple_xpm));
2244
2245 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
2246 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
2247 dc.SetPen(*wxTRANSPARENT_PEN);
2248 dc.DrawRectangle(rectInt);
2249 }
2250}
2251
2252void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
2253 const wxRect& rect,
6766e5d1 2254 int lenThumb,
1e6feb95
VZ
2255 wxOrientation orient,
2256 int start,
2257 int end,
2258 int step,
61fef19b 2259 int WXUNUSED(flags),
6766e5d1 2260 long style)
1e6feb95 2261{
6766e5d1
JS
2262 /* show ticks geometry
2263
2264 left right
2265 ticks shaft ticks
2266 ---- XX ---- <-- x1
2267 ---- XX ----
2268 ---- XX ----
2269 ---- XX ---- <-- x2
2270
2271 ^ ^ ^ ^
2272 | | | |
2273 y3 y1 y2 y4
2274 */
1e6feb95 2275
6766e5d1 2276 // empty slider?
4462f911
VZ
2277 if ( end == start )
2278 return;
2279
2280 bool left, right;
2281 GetSliderLabelsSides(orient, style, &left, &right);
2282
2283 bool isVertical = orient == wxVERTICAL;
6766e5d1
JS
2284
2285 // default thumb size
2286 wxSize sizeThumb = GetSliderThumbSize (rect, 0, orient);
4462f911 2287 wxCoord defaultLen = (isVertical ? sizeThumb.x : sizeThumb.y);
6766e5d1
JS
2288
2289 // normal thumb size
2290 sizeThumb = GetSliderThumbSize (rect, lenThumb, orient);
4462f911 2291 wxCoord widthThumb = (isVertical ? sizeThumb.y : sizeThumb.x);
6766e5d1
JS
2292
2293 wxRect rectShaft = GetSliderShaftRect (rect, lenThumb, orient, style);
2294
2295 wxCoord x1, x2, y1, y2, y3, y4 , len;
4462f911
VZ
2296 x1 = (isVertical ? rectShaft.y : rectShaft.x) + widthThumb/2;
2297 x2 = (isVertical ? rectShaft.GetBottom() : rectShaft.GetRight()) - widthThumb/2;
2298 y1 = (isVertical ? rectShaft.x : rectShaft.y) - defaultLen/2;
2299 y2 = (isVertical ? rectShaft.GetRight() : rectShaft.GetBottom()) + defaultLen/2;
2300 y3 = (isVertical ? rect.x : rect.y);
2301 y4 = (isVertical ? rect.GetRight() : rect.GetBottom());
6766e5d1 2302 len = x2 - x1;
1e6feb95
VZ
2303
2304 dc.SetPen(m_penBlack);
2305
2306 int range = end - start;
4462f911
VZ
2307 for ( int n = 0; n < range; n += step )
2308 {
1e6feb95
VZ
2309 wxCoord x = x1 + (len*n) / range;
2310
4462f911
VZ
2311 if (left & (y1 > y3))
2312 {
6766e5d1
JS
2313 DrawLine(dc, x, y1, x, y3, orient == wxVERTICAL);
2314 }
4462f911
VZ
2315 if (right & (y4 > y2))
2316 {
6766e5d1
JS
2317 DrawLine(dc, x, y2, x, y4, orient == wxVERTICAL);
2318 }
1e6feb95 2319 }
1e6feb95 2320 // always draw the line at the end position
4462f911
VZ
2321 if (left & (y1 > y3))
2322 {
6766e5d1
JS
2323 DrawLine(dc, x2, y1, x2, y3, orient == wxVERTICAL);
2324 }
4462f911
VZ
2325 if (right & (y4 > y2))
2326 {
6766e5d1
JS
2327 DrawLine(dc, x2, y2, x2, y4, orient == wxVERTICAL);
2328 }
1e6feb95
VZ
2329}
2330
9a6384ca
WS
2331#endif // wxUSE_SLIDER
2332
2333#if wxUSE_MENUS
2334
1e6feb95
VZ
2335// ----------------------------------------------------------------------------
2336// menu and menubar
2337// ----------------------------------------------------------------------------
2338
2339// wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2340class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo
2341{
2342public:
2343 virtual wxSize GetSize() const { return m_size; }
2344
2345 wxCoord GetLabelOffset() const { return m_ofsLabel; }
2346 wxCoord GetAccelOffset() const { return m_ofsAccel; }
2347
2348 wxCoord GetItemHeight() const { return m_heightItem; }
2349
2350private:
2351 // the total size of the menu
2352 wxSize m_size;
2353
2354 // the offset of the start of the menu item label
2355 wxCoord m_ofsLabel;
2356
2357 // the offset of the start of the accel label
2358 wxCoord m_ofsAccel;
2359
2360 // the height of a normal (not separator) item
2361 wxCoord m_heightItem;
2362
71e03035
VZ
2363 friend wxMenuGeometryInfo *
2364 wxWin32Renderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
1e6feb95
VZ
2365};
2366
2367// FIXME: all constants are hardcoded but shouldn't be
2368static const wxCoord MENU_LEFT_MARGIN = 9;
2369static const wxCoord MENU_RIGHT_MARGIN = 18;
2370static const wxCoord MENU_VERT_MARGIN = 3;
2371
2372// the margin around bitmap/check marks (on each side)
2373static const wxCoord MENU_BMP_MARGIN = 2;
2374
2375// the margin between the labels and accel strings
2376static const wxCoord MENU_ACCEL_MARGIN = 8;
2377
2378// the separator height in pixels: in fact, strangely enough, the real height
2379// is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2380// account here
2381static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
2382
2383// the size of the standard checkmark bitmap
2384static const wxCoord MENU_CHECK_SIZE = 9;
2385
2386void wxWin32Renderer::DrawMenuBarItem(wxDC& dc,
2387 const wxRect& rectOrig,
2388 const wxString& label,
2389 int flags,
2390 int indexAccel)
2391{
2392 wxRect rect = rectOrig;
2393 rect.height--;
2394
2395 wxDCTextColourChanger colChanger(dc);
2396
2397 if ( flags & wxCONTROL_SELECTED )
2398 {
2399 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2400
147b8a4a
VZ
2401 const wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2402 dc.SetBrush(colBg);
2403 dc.SetPen(colBg);
1e6feb95
VZ
2404 dc.DrawRectangle(rect);
2405 }
2406
2407 // don't draw the focus rect around menu bar items
2408 DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
2409 wxALIGN_CENTRE, indexAccel);
2410}
2411
2412void wxWin32Renderer::DrawMenuItem(wxDC& dc,
2413 wxCoord y,
2414 const wxMenuGeometryInfo& gi,
2415 const wxString& label,
2416 const wxString& accel,
2417 const wxBitmap& bitmap,
2418 int flags,
2419 int indexAccel)
2420{
2421 const wxWin32MenuGeometryInfo& geometryInfo =
2422 (const wxWin32MenuGeometryInfo&)gi;
2423
2424 wxRect rect;
2425 rect.x = 0;
2426 rect.y = y;
2427 rect.width = geometryInfo.GetSize().x;
2428 rect.height = geometryInfo.GetItemHeight();
2429
2430 // draw the selected item specially
2431 wxDCTextColourChanger colChanger(dc);
2432 if ( flags & wxCONTROL_SELECTED )
2433 {
2434 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2435
147b8a4a
VZ
2436 const wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2437 dc.SetBrush(colBg);
2438 dc.SetPen(colBg);
1e6feb95
VZ
2439 dc.DrawRectangle(rect);
2440 }
2441
2442 // draw the bitmap: use the bitmap provided or the standard checkmark for
2443 // the checkable items
2444 wxBitmap bmp = bitmap;
2445 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKED) )
2446 {
2447 bmp = GetIndicator(IndicatorType_Menu, flags);
2448 }
2449
2450 if ( bmp.Ok() )
2451 {
2452 rect.SetRight(geometryInfo.GetLabelOffset());
2453 wxControlRenderer::DrawBitmap(dc, bmp, rect);
2454 }
2455
2456 // draw the label
2457 rect.x = geometryInfo.GetLabelOffset();
2458 rect.SetRight(geometryInfo.GetAccelOffset());
2459
2460 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
2461
2462 // draw the accel string
2463 rect.x = geometryInfo.GetAccelOffset();
2464 rect.SetRight(geometryInfo.GetSize().x);
2465
2466 // NB: no accel index here
2467 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
2468
2469 // draw the submenu indicator
2470 if ( flags & wxCONTROL_ISSUBMENU )
2471 {
2472 rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
2473 rect.width = MENU_RIGHT_MARGIN;
2474
0428ac8c 2475 ArrowStyle arrowStyle;
1e6feb95 2476 if ( flags & wxCONTROL_DISABLED )
d6922577 2477 arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InvertedDisabled
1e6feb95
VZ
2478 : Arrow_Disabled;
2479 else if ( flags & wxCONTROL_SELECTED )
d6922577 2480 arrowStyle = Arrow_Inverted;
1e6feb95
VZ
2481 else
2482 arrowStyle = Arrow_Normal;
2483
2484 DrawArrow(dc, rect, Arrow_Right, arrowStyle);
2485 }
2486}
2487
2488void wxWin32Renderer::DrawMenuSeparator(wxDC& dc,
2489 wxCoord y,
2490 const wxMenuGeometryInfo& geomInfo)
2491{
2492 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
2493}
2494
2495wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& sizeText) const
2496{
2497 wxSize size = sizeText;
2498
2499 // FIXME: menubar height is configurable under Windows
2500 size.x += 12;
2501 size.y += 6;
2502
2503 return size;
2504}
2505
2506wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win,
2507 const wxMenu& menu) const
2508{
2509 // prepare the dc: for now we draw all the items with the system font
2510 wxClientDC dc(win);
a756f210 2511 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
1e6feb95
VZ
2512
2513 // the height of a normal item
2514 wxCoord heightText = dc.GetCharHeight();
2515
2516 // the total height
2517 wxCoord height = 0;
2518
2519 // the max length of label and accel strings: the menu width is the sum of
2520 // them, even if they're for different items (as the accels should be
2521 // aligned)
2522 //
2523 // the max length of the bitmap is never 0 as Windows always leaves enough
2524 // space for a check mark indicator
2525 wxCoord widthLabelMax = 0,
2526 widthAccelMax = 0,
2527 widthBmpMax = MENU_LEFT_MARGIN;
2528
ac32ba44 2529 for ( wxMenuItemList::compatibility_iterator node = menu.GetMenuItems().GetFirst();
1e6feb95
VZ
2530 node;
2531 node = node->GetNext() )
2532 {
2533 // height of this item
2534 wxCoord h;
2535
2536 wxMenuItem *item = node->GetData();
2537 if ( item->IsSeparator() )
2538 {
2539 h = MENU_SEPARATOR_HEIGHT;
2540 }
2541 else // not separator
2542 {
2543 h = heightText;
2544
2545 wxCoord widthLabel;
c267759c 2546 dc.GetTextExtent(item->GetItemLabelText(), &widthLabel, NULL);
1e6feb95
VZ
2547 if ( widthLabel > widthLabelMax )
2548 {
2549 widthLabelMax = widthLabel;
2550 }
2551
2552 wxCoord widthAccel;
2553 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
2554 if ( widthAccel > widthAccelMax )
2555 {
2556 widthAccelMax = widthAccel;
2557 }
2558
2559 const wxBitmap& bmp = item->GetBitmap();
2560 if ( bmp.Ok() )
2561 {
2562 wxCoord widthBmp = bmp.GetWidth();
2563 if ( widthBmp > widthBmpMax )
2564 widthBmpMax = widthBmp;
2565 }
2566 //else if ( item->IsCheckable() ): no need to check for this as
2567 // MENU_LEFT_MARGIN is big enough to show the check mark
2568 }
2569
2570 h += 2*MENU_VERT_MARGIN;
2571
2572 // remember the item position and height
2573 item->SetGeometry(height, h);
2574
2575 height += h;
2576 }
2577
2578 // bundle the metrics into a struct and return it
2579 wxWin32MenuGeometryInfo *gi = new wxWin32MenuGeometryInfo;
2580
2581 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
2582 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
2583 if ( widthAccelMax > 0 )
2584 {
2585 // if we actually have any accesl, add a margin
2586 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
2587 }
2588
2589 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
2590
2591 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
2592 gi->m_size.y = height;
2593
2594 return gi;
2595}
2596
9a6384ca
WS
2597#endif // wxUSE_MENUS
2598
2599#if wxUSE_STATUSBAR
2600
71e03035
VZ
2601// ----------------------------------------------------------------------------
2602// status bar
2603// ----------------------------------------------------------------------------
3379ed37 2604
71e03035
VZ
2605void wxWin32Renderer::DrawStatusField(wxDC& dc,
2606 const wxRect& rect,
2607 const wxString& label,
1cd9779f
VZ
2608 int flags,
2609 int style)
3379ed37 2610{
71e03035 2611 wxRect rectIn;
3379ed37 2612
1cd9779f 2613 if ( flags & wxCONTROL_SIZEGRIP )
71e03035
VZ
2614 {
2615 // draw the size grip: it is a normal rect except that in the lower
2616 // right corner we have several bands which may be used for dragging
2617 // the status bar corner
2618 //
2619 // each band consists of 4 stripes: m_penHighlight, double
2620 // m_penDarkGrey and transparent one
2621 wxCoord x2 = rect.GetRight(),
2622 y2 = rect.GetBottom();
3379ed37 2623
71e03035 2624 // draw the upper left part of the rect normally
c2919ab3
VZ
2625 if (style != wxSB_FLAT)
2626 {
2627 if (style == wxSB_RAISED)
2628 dc.SetPen(m_penHighlight);
2629 else
2630 dc.SetPen(m_penDarkGrey);
2631 dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2);
2632 dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop());
2633 }
71e03035
VZ
2634
2635 // draw the grey stripes of the grip
2636 size_t n;
2637 wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1;
2638 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
2639 {
2640 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
2641 dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1);
2642 }
2643
2644 // draw the white stripes
2645 dc.SetPen(m_penHighlight);
2646 ofs = WIDTH_STATUSBAR_GRIP_BAND + 1;
2647 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
2648 {
2649 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
2650 }
2651
2652 // draw the remaining rect boundaries
c2919ab3
VZ
2653 if (style != wxSB_FLAT)
2654 {
2655 if (style == wxSB_RAISED)
2656 dc.SetPen(m_penDarkGrey);
2657 else
2658 dc.SetPen(m_penHighlight);
2659 ofs -= WIDTH_STATUSBAR_GRIP_BAND;
2660 dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1);
2661 dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2);
2662 }
71e03035
VZ
2663
2664 rectIn = rect;
2665 rectIn.Deflate(1);
2666
2667 rectIn.width -= STATUSBAR_GRIP_SIZE;
71e03035 2668
1cd9779f
VZ
2669 // this will prevent the standard version from drawing any borders
2670 style = wxSB_FLAT;
2671 }
71e03035 2672
bfd5f909 2673 wxStdRenderer::DrawStatusField(dc, rect, label, flags, style);
71e03035 2674}
3379ed37 2675
9a6384ca
WS
2676#endif // wxUSE_STATUSBAR
2677
1e6feb95
VZ
2678// ----------------------------------------------------------------------------
2679// combobox
2680// ----------------------------------------------------------------------------
2681
2682void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal,
61fef19b 2683 wxBitmap * WXUNUSED(bmpFocus),
1e6feb95
VZ
2684 wxBitmap *bmpPressed,
2685 wxBitmap *bmpDisabled)
2686{
2687 static const wxCoord widthCombo = 16;
2688 static const wxCoord heightCombo = 17;
2689
2690 wxMemoryDC dcMem;
2691
2692 if ( bmpNormal )
2693 {
2694 bmpNormal->Create(widthCombo, heightCombo);
2695 dcMem.SelectObject(*bmpNormal);
2696 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2697 Arrow_Down, Arrow_Normal);
2698 }
2699
2700 if ( bmpPressed )
2701 {
2702 bmpPressed->Create(widthCombo, heightCombo);
2703 dcMem.SelectObject(*bmpPressed);
2704 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2705 Arrow_Down, Arrow_Pressed);
2706 }
2707
2708 if ( bmpDisabled )
2709 {
2710 bmpDisabled->Create(widthCombo, heightCombo);
2711 dcMem.SelectObject(*bmpDisabled);
2712 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2713 Arrow_Down, Arrow_Disabled);
2714 }
2715}
2716
2717// ----------------------------------------------------------------------------
147b8a4a 2718// scrollbar
1e6feb95
VZ
2719// ----------------------------------------------------------------------------
2720
147b8a4a 2721void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
1e6feb95 2722{
147b8a4a
VZ
2723 if ( isPressed )
2724 {
2725 DrawRect(dc, rect, m_penDarkGrey);
1e6feb95 2726
147b8a4a
VZ
2727 // the arrow is usually drawn inside border of width 2 and is offset by
2728 // another pixel in both directions when it's pressed - as the border
2729 // in this case is more narrow as well, we have to adjust rect like
2730 // this:
2731 rect->Inflate(-1);
2732 rect->x++;
2733 rect->y++;
2734 }
2735 else // !pressed
2736 {
2737 DrawAntiSunkenBorder(dc, rect);
2738 }
1e6feb95
VZ
2739}
2740
1e6feb95
VZ
2741void wxWin32Renderer::DrawArrow(wxDC& dc,
2742 wxDirection dir,
2743 const wxRect& rect,
2744 int flags)
2745{
0428ac8c 2746 ArrowStyle arrowStyle;
1e6feb95
VZ
2747 if ( flags & wxCONTROL_PRESSED )
2748 {
2749 // can't be pressed and disabled
2750 arrowStyle = Arrow_Pressed;
2751 }
2752 else
2753 {
2754 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
2755 }
2756
0428ac8c 2757 DrawArrowButton(dc, rect, GetArrowDirection(dir), arrowStyle);
1e6feb95
VZ
2758}
2759
2760void wxWin32Renderer::DrawArrow(wxDC& dc,
2761 const wxRect& rect,
0428ac8c
VZ
2762 ArrowDirection arrowDir,
2763 ArrowStyle arrowStyle)
1e6feb95
VZ
2764{
2765 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
2766
2767 // under Windows the arrows always have the same size so just centre it in
2768 // the provided rectangle
2769 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
2770 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
2771
2772 // Windows does it like this...
2773 if ( arrowDir == Arrow_Left )
2774 x--;
2775
2776 // draw it
a290fa5a 2777 dc.DrawBitmap(bmp, x, y, true /* use mask */);
1e6feb95
VZ
2778}
2779
2780void wxWin32Renderer::DrawArrowButton(wxDC& dc,
2781 const wxRect& rectAll,
0428ac8c
VZ
2782 ArrowDirection arrowDir,
2783 ArrowStyle arrowStyle)
1e6feb95
VZ
2784{
2785 wxRect rect = rectAll;
147b8a4a 2786 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
1e6feb95
VZ
2787 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
2788 DrawArrow(dc, rect, arrowDir, arrowStyle);
2789}
2790
2791void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
61fef19b 2792 wxOrientation WXUNUSED(orient),
1e6feb95 2793 const wxRect& rect,
61fef19b 2794 int WXUNUSED(flags))
1e6feb95
VZ
2795{
2796 // we don't use the flags, the thumb never changes appearance
2797 wxRect rectThumb = rect;
2798 DrawArrowBorder(dc, &rectThumb);
2799 DrawBackground(dc, wxNullColour, rectThumb);
2800}
2801
2802void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
61fef19b 2803 wxOrientation WXUNUSED(orient),
1e6feb95
VZ
2804 const wxRect& rectBar,
2805 int flags)
2806{
2807 wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
2808 ? wxColourScheme::SCROLLBAR_PRESSED
2809 : wxColourScheme::SCROLLBAR;
147b8a4a 2810 DrawBackground(dc, m_scheme->Get(col), rectBar);
1e6feb95
VZ
2811}
2812
63f06c22
VS
2813// ----------------------------------------------------------------------------
2814// standard icons
2815// ----------------------------------------------------------------------------
2816
13b22a67 2817/* Copyright (c) Julian Smart */
579de297 2818static const char *error_xpm[]={
13b22a67
JS
2819/* columns rows colors chars-per-pixel */
2820"32 32 70 1",
2821"- c #BF0101",
2822"b c #361F1F",
2823"& c #C08484",
2824"X c #BF3333",
2825"# c #C08181",
2826"% c #C01111",
2827"d c #C51515",
2828"s c #551818",
2829"O c #C07E7E",
2830": c #C00E0E",
2831"u c #E28A8A",
2832"2 c #C81F1F",
2833"8 c #FFFFFF",
2834"p c #E59494",
2835"< c #BB0101",
2836"y c #DA6A6A",
2837"A c #4C4C4C",
2838"9 c #F7DFDF",
2839"@ c #BF5353",
2840"w c #FAE9E9",
2841"F c #272727",
2842"5 c #D24A4A",
2843". c #C06363",
2844"n c #BF8282",
2845"7 c #F2C9C9",
2846"t c #C09292",
2847"M c #3E3E3E",
2848"x c #4D4D4D",
2849"4 c #CA2A2A",
2850"h c #E79F9F",
2851"* c #C05454",
2852"D c #711212",
2853"V c #737373",
2854"$ c #BF3232",
2855"N c #900B0B",
2856"6 c #BD0303",
2857"3 c #DF7F7F",
2858"K c #6F1212",
2859"C c #BD0000",
2860"m c #950909",
2861"P c #8A8A8A",
2862"j c #D75F5F",
2863" c None",
2864"e c #F4D4D4",
2865"S c #BF2020",
2866"L c #747474",
2867"G c #842C2C",
2868"c c #ECB4B4",
2869"l c #2E2121",
2870"g c #BF7E7E",
2871"k c #9B0808",
2872"= c #BF0505",
2873"a c #B10303",
2874"q c #7E2020",
2875"1 c #642222",
2876"J c #676767",
2877"B c #322020",
2878"; c #C00303",
2879"i c #242424",
2880"o c #C00000",
2881"> c #BF1F1F",
2882", c #842B2B",
2883"f c #701212",
2884"0 c #BE0000",
2885"r c #960909",
2886"H c #686868",
2887"v c #BC0000",
2888"Z c #671414",
2889"+ c #C02020",
2890"z c #CD3535",
2891/* pixels */
2892" ",
2893" ",
2894" .XoooOO ",
2895" .+ooooooooo@# ",
2896" $oooooooooooo%& ",
2897" *=-ooooooooooooo;: ",
2898" *oooooooooooooooooo> ",
2899" =ooooooooooooooooooo, ",
2900" $-ooooooooooooooooooo<1 ",
2901" .oooooo2334ooo533oooooo6 ",
2902" +ooooooo789oo2883oooooo0q ",
2903" oooooooo2w83o78eoooooooor ",
2904" toooooooooy88u884oooooooori ",
2905" Xooooooooooe888poooooooooas ",
2906" ooooooooooo4889doooooooooof ",
2907" ooooooooooo588w2oooooooooofi ",
2908" oooooooooodw8887oooooooooofi ",
2909" goooooooooh8w588jooooooookli ",
2910" tooooooooz885op8wdooooooorix ",
2911" oooooood98cood98cooooooori ",
2912" @oooooop8w2ooo5885ooooovbi ",
2913" n%ooooooooooooooooooooomiM ",
2914" &;oooooooooooooooooooNBiV ",
2915" :ooooooooooooooooooCZiA ",
2916" nSooooooooooooooooCDiF ",
2917" nG<oooooooooooooNZiiH ",
2918" 160ooooooooovmBiFH ",
2919" nqrraoookrrbiiA ",
2920" nJisKKKliiiML ",
2921" nPiiix ",
2922" ",
2923" "
2924};
63f06c22 2925
13b22a67 2926/* Copyright (c) Julian Smart */
579de297 2927static const char *info_xpm[]={
13b22a67
JS
2928/* columns rows colors chars-per-pixel */
2929"32 32 17 1",
2930"* c #A1A3FB",
2931"X c #FFFFFF",
2932"O c #191EF4",
2933"= c #777AF9",
2934": c #4D51F7",
2935" c None",
2936"- c #2328F5",
2937"+ c #4247F6",
2938"; c #C1C2FC",
2939". c #C0C0C0",
2940"& c #E0E1FE",
2941"% c #242424",
2942"> c #2D32F5",
2943"o c #CBCCFD",
2944"# c #0309F3",
2945"@ c #8C8FFA",
2946"$ c #EAEBFE",
2947/* pixels */
2948" ....... ",
2949" ...XXXXXXX... ",
2950" ..XXXXXXXXXXXXX.. ",
2951" .XXXXXXXXXXXXXXXXX. ",
2952" .XXXXXXXXoO+XXXXXXXX. ",
2953" .XXXXXXXXX@#OXXXXXXXXX. ",
2954" .XXXXXXXXXX$@oXXXXXXXXXX. ",
2955" .XXXXXXXXXXXXXXXXXXXXXXX.% ",
2956" .XXXXXXXXX&*=-XXXXXXXXXX.%% ",
2957".XXXXXXXXXX;:#>XXXXXXXXXXX.% ",
2958".XXXXXXXXXXX;#+XXXXXXXXXXX.% ",
2959".XXXXXXXXXXX;#+XXXXXXXXXXX.%% ",
2960" .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
2961" .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
2962" .XXXXXXXXXX;#+XXXXXXXXXX.%% ",
2963" .XXXXXXXX*-##+XXXXXXXX.%%% ",
2964" .XXXXXXXXXXXXXXXXXXX.%%%% ",
2965" .XXXXXXXXXXXXXXXXX.%%%% ",
2966" ..XXXXXXXXXXXXX..%%%% ",
2967" %...XXXXXXXX..%%%%% ",
2968" %%%..XXXXXX.%%%%% ",
2969" %%%.XXXXX.%%% ",
2970" %.XXXX.%% ",
2971" .XXX.%% ",
2972" .XX.%% ",
2973" .X.%% ",
2974" ..%% ",
2975" .%% ",
2976" %% ",
2977" % ",
2978" ",
2979" "
2980};
63f06c22 2981
13b22a67 2982/* Copyright (c) Julian Smart */
579de297 2983static const char *question_xpm[]={
13b22a67
JS
2984/* columns rows colors chars-per-pixel */
2985"32 32 16 1",
2986"O c #A3A3FF",
2987"X c #FFFFFF",
2988"% c #CACAFF",
2989"- c #4141FF",
2990"= c #6060FF",
2991"* c #2B2BFF",
2992"@ c #B5B5FF",
2993" c None",
2994"# c #1616FF",
2995"+ c #8181FF",
2996"$ c #0000FF",
2997". c #C0C0C0",
2998"; c #5555FF",
2999": c #242424",
3000"o c #E7E7FF",
3001"& c #7575FF",
3002/* pixels */
3003" ....... ",
3004" ...XXXXXXX... ",
3005" ..XXXXXXXXXXXXX.. ",
3006" .XXXXXXoO++@XXXXXX. ",
3007" .XXXXXXO#$$$$#%XXXXX. ",
3008" .XXXXXX@$$#&&#$#oXXXXX. ",
3009" .XXXXXXX*$$%XX%$$=XXXXXX. ",
3010" .XXXXXXX+-;XXXX$$-XXXXXX.: ",
3011" .XXXXXXXXXXXXX+$$&XXXXXX.:: ",
3012".XXXXXXXXXXXXo;$$*oXXXXXXX.: ",
3013".XXXXXXXXXXXo*$$*oXXXXXXXX.: ",
3014".XXXXXXXXXXX+$$*oXXXXXXXXX.:: ",
3015" .XXXXXXXXXX-$$oXXXXXXXXX.::: ",
3016" .XXXXXXXXXXX--XXXXXXXXXX.::: ",
3017" .XXXXXXXXXXXXXXXXXXXXXXX.:: ",
3018" .XXXXXXXXX-$$XXXXXXXXX.::: ",
3019" .XXXXXXXX-$$XXXXXXXX.:::: ",
3020" .XXXXXXXO++XXXXXXX.:::: ",
3021" ..XXXXXXXXXXXXX..:::: ",
3022" :...XXXXXXXX..::::: ",
3023" :::..XXXXXX.::::: ",
3024" :::.XXXXX.::: ",
3025" :.XXXX.:: ",
3026" .XXX.:: ",
3027" .XX.:: ",
3028" .X.:: ",
3029" ..:: ",
3030" .:: ",
3031" :: ",
3032" : ",
3033" ",
3034" "
3035};
63f06c22 3036
13b22a67 3037/* Copyright (c) Julian Smart */
579de297 3038static const char *warning_xpm[]={
13b22a67
JS
3039/* columns rows colors chars-per-pixel */
3040"32 32 9 1",
3041"@ c Black",
3042"o c #A6A800",
3043"+ c #8A8C00",
3044"$ c #B8BA00",
3045" c None",
3046"O c #6E7000",
3047"X c #DCDF00",
3048". c #C00000",
3049"# c #373800",
3050/* pixels */
3051" ",
3052" ",
3053" ",
3054" . ",
3055" ... ",
3056" ... ",
3057" ..... ",
3058" ...X.. ",
3059" ..XXX.. ",
3060" ...XXX... ",
3061" ..XXXXX.. ",
3062" ..XXXXXX... ",
3063" ...XXoO+XX.. ",
3064" ..XXXO@#XXX.. ",
3065" ..XXXXO@#XXX... ",
3066" ...XXXXO@#XXXX.. ",
3067" ..XXXXXO@#XXXX... ",
3068" ...XXXXXo@OXXXXX.. ",
3069" ...XXXXXXo@OXXXXXX.. ",
3070" ..XXXXXXX$@OXXXXXX... ",
3071" ...XXXXXXXX@XXXXXXXX.. ",
3072" ...XXXXXXXXXXXXXXXXXX... ",
3073" ..XXXXXXXXXXOXXXXXXXXX.. ",
3074" ...XXXXXXXXXO@#XXXXXXXXX.. ",
3075" ..XXXXXXXXXXX#XXXXXXXXXX... ",
3076" ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
3077" ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
3078" .............................. ",
3079" .............................. ",
3080" ",
3081" ",
3082" "
3083};
3084
63f06c22 3085
536b70ac
VS
3086wxBitmap wxWin32ArtProvider::CreateBitmap(const wxArtID& id,
3087 const wxArtClient& WXUNUSED(client),
3088 const wxSize& WXUNUSED(size))
3089{
3090 if ( id == wxART_INFORMATION )
3091 return wxBitmap(info_xpm);
3092 if ( id == wxART_ERROR )
3093 return wxBitmap(error_xpm);
3094 if ( id == wxART_WARNING )
3095 return wxBitmap(warning_xpm);
3096 if ( id == wxART_QUESTION )
3097 return wxBitmap(question_xpm);
3098 return wxNullBitmap;
63f06c22
VS
3099}
3100
24a23c35 3101
9a6384ca
WS
3102#if wxUSE_TEXTCTRL
3103
1e6feb95
VZ
3104// ----------------------------------------------------------------------------
3105// text control geometry
3106// ----------------------------------------------------------------------------
3107
61fef19b 3108wxRect
6229b92f 3109wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
61fef19b 3110 const wxRect& rect) const
1e6feb95 3111{
6229b92f 3112 wxRect rectTotal = wxStdRenderer::GetTextTotalArea(text, rect);
1e6feb95 3113
6229b92f 3114 // this is strange but it's what Windows does
1e6feb95
VZ
3115 rectTotal.height++;
3116
3117 return rectTotal;
3118}
3119
61fef19b 3120wxRect
6229b92f 3121wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
61fef19b
VZ
3122 const wxRect& rect,
3123 wxCoord *extraSpaceBeyond) const
1e6feb95
VZ
3124{
3125 wxRect rectText = rect;
3126
3127 // undo GetTextTotalArea()
3128 if ( rectText.height > 0 )
3129 rectText.height--;
3130
6229b92f 3131 return wxStdRenderer::GetTextClientArea(text, rect, extraSpaceBeyond);
1e6feb95
VZ
3132}
3133
9a6384ca
WS
3134#endif // wxUSE_TEXTCTRL
3135
1e6feb95
VZ
3136// ----------------------------------------------------------------------------
3137// size adjustments
3138// ----------------------------------------------------------------------------
3139
3140void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
3141{
3142#if wxUSE_SCROLLBAR
3143 if ( wxDynamicCast(window, wxScrollBar) )
3144 {
3145 // we only set the width of vert scrollbars and height of the
3146 // horizontal ones
3147 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
3148 size->y = m_sizeScrollbarArrow.y;
3149 else
3150 size->x = m_sizeScrollbarArrow.x;
3151
3152 // skip border width adjustments, they don't make sense for us
3153 return;
3154 }
9467bdb7 3155#endif // wxUSE_SCROLLBAR
1e6feb95 3156
06aa40d9
WS
3157#if wxUSE_BMPBUTTON
3158 if ( wxDynamicCast(window, wxBitmapButton) )
3159 {
3160 // do nothing
3161 } else
3162#endif // wxUSE_BMPBUTTON
43be3c33 3163#if wxUSE_BUTTON || wxUSE_TOGGLEBTN
9eddec69 3164 if ( 0
43be3c33 3165# if wxUSE_BUTTON
9eddec69 3166 || wxDynamicCast(window, wxButton)
43be3c33
JS
3167# endif // wxUSE_BUTTON
3168# if wxUSE_TOGGLEBTN
9eddec69 3169 || wxDynamicCast(window, wxToggleButton)
43be3c33
JS
3170# endif // wxUSE_TOGGLEBTN
3171 )
1e6feb95 3172 {
1b465102
VZ
3173 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3174 {
3175 // TODO: don't harcode all this
3176 size->x += 3*window->GetCharWidth();
3177
3178 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
3179 if ( size->y < heightBtn - 8 )
3180 size->y = heightBtn;
3181 else
3182 size->y += 9;
3183 }
1e6feb95 3184
6766e5d1
JS
3185 // for compatibility with other ports, the buttons default size is never
3186 // less than the standard one, but not when display not PDAs.
3187 if (wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA)
3188 {
a290fa5a 3189 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
6766e5d1 3190 {
a290fa5a 3191 wxSize szDef = wxButton::GetDefaultSize();
6766e5d1
JS
3192 if ( size->x < szDef.x )
3193 size->x = szDef.x;
3194 }
3195 }
3196
1e6feb95
VZ
3197 // no border width adjustments for buttons
3198 return;
3199 }
43be3c33 3200#endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
1e6feb95 3201
1cd9779f 3202 wxStdRenderer::AdjustSize(size, window);
1e6feb95
VZ
3203}
3204
249803fb
VZ
3205wxBitmap wxWin32Renderer::GetFrameButtonBitmap(FrameButtonType type)
3206{
3207 wxBitmap& bmp = m_bmpFrameButtons[type];
3208 if ( !bmp.Ok() )
3209 {
3210 bmp = wxBitmap(ms_xpmFrameButtons[type]);
3211 }
3212
3213 return bmp;
3214}
3215
1e6feb95
VZ
3216// ============================================================================
3217// wxInputHandler
3218// ============================================================================
3219
3220// ----------------------------------------------------------------------------
3221// wxWin32InputHandler
3222// ----------------------------------------------------------------------------
3223
61fef19b
VZ
3224bool wxWin32InputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
3225 const wxKeyEvent& WXUNUSED(event),
3226 bool WXUNUSED(pressed))
1e6feb95 3227{
a290fa5a 3228 return false;
1e6feb95
VZ
3229}
3230
67e49a98 3231bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
3232 const wxMouseEvent& event)
3233{
211cc8dc 3234 // clicking on the control gives it focus
71e03035 3235 if ( event.ButtonDown() )
211cc8dc 3236 {
ad02525d 3237 wxWindow * const win = control->GetInputWindow();
d1504049 3238
ad02525d 3239 if ( win->CanAcceptFocus() && wxWindow::FindFocus() != win )
71e03035
VZ
3240 {
3241 win->SetFocus();
211cc8dc 3242
a290fa5a 3243 return true;
71e03035 3244 }
211cc8dc
VS
3245 }
3246
a290fa5a 3247 return false;
1e6feb95
VZ
3248}
3249
9a6384ca
WS
3250#if wxUSE_SCROLLBAR
3251
1e6feb95
VZ
3252// ----------------------------------------------------------------------------
3253// wxWin32ScrollBarInputHandler
3254// ----------------------------------------------------------------------------
3255
3256wxWin32ScrollBarInputHandler::
9467bdb7 3257wxWin32ScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *handler)
1e6feb95
VZ
3258 : wxStdScrollBarInputHandler(renderer, handler)
3259{
a290fa5a 3260 m_scrollPaused = false;
1e6feb95
VZ
3261 m_interval = 0;
3262}
3263
3264bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
3265 const wxControlAction& action)
3266{
3267 // stop if went beyond the position of the original click (this can only
3268 // happen when we scroll by pages)
a290fa5a 3269 bool stop = false;
1e6feb95
VZ
3270 if ( action == wxACTION_SCROLL_PAGE_DOWN )
3271 {
56195504 3272 stop = scrollbar->HitTestBar(m_ptStartScrolling) != wxHT_SCROLLBAR_BAR_2;
1e6feb95
VZ
3273 }
3274 else if ( action == wxACTION_SCROLL_PAGE_UP )
3275 {
56195504 3276 stop = scrollbar->HitTestBar(m_ptStartScrolling) != wxHT_SCROLLBAR_BAR_1;
1e6feb95
VZ
3277 }
3278
3279 if ( stop )
3280 {
3281 StopScrolling(scrollbar);
3282
3283 scrollbar->Refresh();
3284
a290fa5a 3285 return false;
1e6feb95
VZ
3286 }
3287
3288 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
3289}
3290
67e49a98 3291bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
3292 const wxMouseEvent& event)
3293{
3294 // remember the current state
3295 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
3296
3297 // do process the message
3298 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
3299
3300 // analyse the changes
3301 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
3302 {
3303 // we just started dragging the thumb, remember its initial position to
3304 // be able to restore it if the drag is cancelled later
affe4044 3305 m_eventStartDrag = event;
1e6feb95
VZ
3306 }
3307
3308 return rc;
3309}
3310
67e49a98 3311bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
1e6feb95
VZ
3312 const wxMouseEvent& event)
3313{
3314 // we don't highlight scrollbar elements, so there is no need to process
3315 // mouse move events normally - only do it while mouse is captured (i.e.
3316 // when we're dragging the thumb or pressing on something)
3317 if ( !m_winCapture )
a290fa5a 3318 return false;
1e6feb95
VZ
3319
3320 if ( event.Entering() )
3321 {
3322 // we're not interested in this at all
a290fa5a 3323 return false;
1e6feb95
VZ
3324 }
3325
67e49a98 3326 wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
1e6feb95
VZ
3327 wxHitTest ht;
3328 if ( m_scrollPaused )
3329 {
3330 // check if the mouse returned to its original location
3331
3332 if ( event.Leaving() )
3333 {
3334 // it surely didn't
a290fa5a 3335 return false;
1e6feb95
VZ
3336 }
3337
56195504 3338 ht = scrollbar->HitTestBar(event.GetPosition());
1e6feb95
VZ
3339 if ( ht == m_htLast )
3340 {
3341 // yes it did, resume scrolling
a290fa5a 3342 m_scrollPaused = false;
1e6feb95
VZ
3343 if ( m_timerScroll )
3344 {
3345 // we were scrolling by line/page, restart timer
3346 m_timerScroll->Start(m_interval);
3347
a290fa5a 3348 Press(scrollbar, true);
1e6feb95
VZ
3349 }
3350 else // we were dragging the thumb
3351 {
3352 // restore its last location
3353 HandleThumbMove(scrollbar, m_eventLastDrag);
3354 }
3355
a290fa5a 3356 return true;
1e6feb95
VZ
3357 }
3358 }
3359 else // normal case, scrolling hasn't been paused
3360 {
3361 // if we're scrolling the scrollbar because the arrow or the shaft was
3362 // pressed, check that the mouse stays on the same scrollbar element
3363
a17a79ba
RR
3364#if 0
3365 // Always let thumb jump back if we leave the scrollbar
1e6feb95
VZ
3366 if ( event.Moving() )
3367 {
56195504 3368 ht = scrollbar->HitTestBar(event.GetPosition());
1e6feb95
VZ
3369 }
3370 else // event.Leaving()
3371 {
3372 ht = wxHT_NOWHERE;
3373 }
a17a79ba
RR
3374#else
3375 // Jump back only if we get far away from it
3376 wxPoint pos = event.GetPosition();
3377 if (scrollbar->HasFlag( wxVERTICAL ))
3378 {
4175e952 3379 if (pos.x > -40 && pos.x < scrollbar->GetSize().x+40)
a17a79ba
RR
3380 pos.x = 5;
3381 }
3382 else
3383 {
4175e952 3384 if (pos.y > -40 && pos.y < scrollbar->GetSize().y+40)
a17a79ba
RR
3385 pos.y = 5;
3386 }
56195504 3387 ht = scrollbar->HitTestBar(pos);
a17a79ba 3388#endif
1e6feb95
VZ
3389
3390 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3391 // is still ok - we only want to catch the case when the mouse leaves
3392 // the scrollbar here
3393 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
3394 {
3395 ht = wxHT_SCROLLBAR_THUMB;
3396 }
3397
3398 if ( ht != m_htLast )
3399 {
3400 // what were we doing? 2 possibilities: either an arrow/shaft was
3401 // pressed in which case we have a timer and so we just stop it or
3402 // we were dragging the thumb
3403 if ( m_timerScroll )
3404 {
3405 // pause scrolling
3406 m_interval = m_timerScroll->GetInterval();
3407 m_timerScroll->Stop();
a290fa5a 3408 m_scrollPaused = true;
1e6feb95
VZ
3409
3410 // unpress the arrow
a290fa5a 3411 Press(scrollbar, false);
1e6feb95
VZ
3412 }
3413 else // we were dragging the thumb
3414 {
3415 // remember the current thumb position to be able to restore it
3416 // if the mouse returns to it later
affe4044 3417 m_eventLastDrag = event;
1e6feb95
VZ
3418
3419 // and restore the original position (before dragging) of the
3420 // thumb for now
3421 HandleThumbMove(scrollbar, m_eventStartDrag);
3422 }
3423
a290fa5a 3424 return true;
1e6feb95
VZ
3425 }
3426 }
3427
9467bdb7 3428 return wxStdInputHandler::HandleMouseMove(control, event);
1e6feb95
VZ
3429}
3430
9a6384ca
WS
3431#endif // wxUSE_SCROLLBAR
3432
3433#if wxUSE_CHECKBOX
3434
1e6feb95
VZ
3435// ----------------------------------------------------------------------------
3436// wxWin32CheckboxInputHandler
3437// ----------------------------------------------------------------------------
3438
67e49a98 3439bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
3440 const wxKeyEvent& event,
3441 bool pressed)
3442{
3443 if ( pressed )
3444 {
3445 wxControlAction action;
3446 int keycode = event.GetKeyCode();
3447 switch ( keycode )
3448 {
3449 case WXK_SPACE:
3450 action = wxACTION_CHECKBOX_TOGGLE;
3451 break;
3452
3453 case WXK_SUBTRACT:
3454 case WXK_NUMPAD_SUBTRACT:
3455 action = wxACTION_CHECKBOX_CHECK;
3456 break;
3457
3458 case WXK_ADD:
3459 case WXK_NUMPAD_ADD:
3460 case WXK_NUMPAD_EQUAL:
3461 action = wxACTION_CHECKBOX_CLEAR;
3462 break;
3463 }
3464
a290fa5a 3465 if ( !action.IsEmpty() )
1e6feb95
VZ
3466 {
3467 control->PerformAction(action);
3468
a290fa5a 3469 return true;
1e6feb95
VZ
3470 }
3471 }
3472
a290fa5a 3473 return false;
1e6feb95
VZ
3474}
3475
9a6384ca
WS
3476#endif // wxUSE_CHECKBOX
3477
3478#if wxUSE_TEXTCTRL
3479
1e6feb95
VZ
3480// ----------------------------------------------------------------------------
3481// wxWin32TextCtrlInputHandler
3482// ----------------------------------------------------------------------------
3483
67e49a98 3484bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
3485 const wxKeyEvent& event,
3486 bool pressed)
3487{
3488 // handle only MSW-specific text bindings here, the others are handled in
3489 // the base class
3490 if ( pressed )
3491 {
3492 int keycode = event.GetKeyCode();
3493
3494 wxControlAction action;
3495 if ( keycode == WXK_DELETE && event.ShiftDown() )
3496 {
3497 action = wxACTION_TEXT_CUT;
3498 }
3499 else if ( keycode == WXK_INSERT )
3500 {
3501 if ( event.ControlDown() )
3502 action = wxACTION_TEXT_COPY;
3503 else if ( event.ShiftDown() )
3504 action = wxACTION_TEXT_PASTE;
3505 }
3506
3507 if ( action != wxACTION_NONE )
3508 {
3509 control->PerformAction(action);
3510
a290fa5a 3511 return true;
1e6feb95
VZ
3512 }
3513 }
3514
9467bdb7 3515 return wxStdInputHandler::HandleKey(control, event, pressed);
1e6feb95
VZ
3516}
3517
9a6384ca
WS
3518#endif // wxUSE_TEXTCTRL
3519
3520#if wxUSE_STATUSBAR
3521
71e03035
VZ
3522// ----------------------------------------------------------------------------
3523// wxWin32StatusBarInputHandler
3524// ----------------------------------------------------------------------------
3525
3526wxWin32StatusBarInputHandler::
3527wxWin32StatusBarInputHandler(wxInputHandler *handler)
3528 : wxStdInputHandler(handler)
3529{
a290fa5a 3530 m_isOnGrip = false;
71e03035
VZ
3531}
3532
3533bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar,
3534 const wxPoint& pt) const
3535{
3536 if ( statbar->HasFlag(wxST_SIZEGRIP) &&
d1504049 3537 statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
71e03035 3538 {
d1504049
VZ
3539 wxTopLevelWindow *
3540 parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow);
71e03035 3541
a290fa5a 3542 wxCHECK_MSG( parentTLW, false,
9a83f860 3543 wxT("the status bar should be a child of a TLW") );
d1504049
VZ
3544
3545 // a maximized window can't be resized anyhow
3546 if ( !parentTLW->IsMaximized() )
3547 {
3548 // VZ: I think that the standard Windows behaviour is to only
3549 // show the resizing cursor when the mouse is on top of the
3550 // grip itself but apparently different Windows versions behave
3551 // differently (?) and it seems a better UI to allow resizing
3552 // the status bar even when the mouse is above the grip
3553 wxSize sizeSbar = statbar->GetSize();
3554
3555 int diff = sizeSbar.x - pt.x;
3556 return diff >= 0 && diff < (wxCoord)STATUSBAR_GRIP_SIZE;
3557 }
71e03035
VZ
3558 }
3559
a290fa5a 3560 return false;
71e03035
VZ
3561}
3562
3563bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
3564 const wxMouseEvent& event)
3565{
3566 if ( event.Button(1) )
3567 {
3568 if ( event.ButtonDown(1) )
3569 {
3570 wxWindow *statbar = consumer->GetInputWindow();
3571
3572 if ( IsOnGrip(statbar, event.GetPosition()) )
3573 {
3574 wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
3575 wxTopLevelWindow);
3576 if ( tlw )
3577 {
3578 tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
3579 wxHT_TOPLEVEL_BORDER_SE);
3580
3581 statbar->SetCursor(m_cursorOld);
3582
a290fa5a 3583 return true;
71e03035
VZ
3584 }
3585 }
3586 }
3587 }
3588
3589 return wxStdInputHandler::HandleMouse(consumer, event);
3590}
3591
3592bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
3593 const wxMouseEvent& event)
3594{
3595 wxWindow *statbar = consumer->GetInputWindow();
3596
3597 bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
3598 if ( isOnGrip != m_isOnGrip )
3599 {
3600 m_isOnGrip = isOnGrip;
3601 if ( isOnGrip )
3602 {
3603 m_cursorOld = statbar->GetCursor();
3604 statbar->SetCursor(wxCURSOR_SIZENWSE);
3605 }
3606 else
3607 {
3608 statbar->SetCursor(m_cursorOld);
3609 }
3610 }
3611
3612 return wxStdInputHandler::HandleMouseMove(consumer, event);
3613}
3614
9a6384ca
WS
3615#endif // wxUSE_STATUSBAR
3616
768f0c5a
VS
3617// ----------------------------------------------------------------------------
3618// wxWin32FrameInputHandler
3619// ----------------------------------------------------------------------------
3620
8f71aafa
VS
3621class wxWin32SystemMenuEvtHandler : public wxEvtHandler
3622{
3623public:
2279b45a 3624 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
00e086a7 3625
2279b45a
VS
3626 void Attach(wxInputConsumer *consumer);
3627 void Detach();
00e086a7 3628
8f71aafa
VS
3629private:
3630 DECLARE_EVENT_TABLE()
3631 void OnSystemMenu(wxCommandEvent &event);
3632 void OnCloseFrame(wxCommandEvent &event);
3633 void OnClose(wxCloseEvent &event);
00e086a7 3634
8f71aafa
VS
3635 wxWin32FrameInputHandler *m_inputHnd;
3636 wxTopLevelWindow *m_wnd;
0b4f47a3 3637#if wxUSE_ACCEL
8f71aafa 3638 wxAcceleratorTable m_oldAccelTable;
0b4f47a3 3639#endif
8f71aafa
VS
3640};
3641
9467bdb7
VZ
3642wxWin32SystemMenuEvtHandler::
3643wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler)
8f71aafa
VS
3644{
3645 m_inputHnd = handler;
2279b45a
VS
3646 m_wnd = NULL;
3647}
3648
3649void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
3650{
9a83f860 3651 wxASSERT_MSG( m_wnd == NULL, wxT("can't attach the handler twice!") );
2279b45a 3652
8f71aafa
VS
3653 m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
3654 m_wnd->PushEventHandler(this);
00e086a7 3655
0b4f47a3 3656#if wxUSE_ACCEL
00e086a7 3657 // VS: This code relies on using generic implementation of
8f71aafa
VS
3658 // wxAcceleratorTable in wxUniv!
3659 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
3660 m_oldAccelTable = table;
3661 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
3662 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
3663 m_wnd->SetAcceleratorTable(table);
0b4f47a3 3664#endif
8f71aafa
VS
3665}
3666
2279b45a 3667void wxWin32SystemMenuEvtHandler::Detach()
8f71aafa
VS
3668{
3669 if ( m_wnd )
3670 {
0b4f47a3 3671#if wxUSE_ACCEL
8f71aafa 3672 m_wnd->SetAcceleratorTable(m_oldAccelTable);
0b4f47a3 3673#endif
00e086a7 3674 m_wnd->RemoveEventHandler(this);
2279b45a 3675 m_wnd = NULL;
8f71aafa
VS
3676 }
3677}
3678
3679BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
3680 EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
3681 EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
3682 EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
3683END_EVENT_TABLE()
3684
3685void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
3686{
0b4f47a3 3687#if wxUSE_ACCEL
8f71aafa
VS
3688 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
3689 m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
0b4f47a3
DS
3690#endif
3691
9a6384ca 3692#if wxUSE_MENUS
249803fb 3693 m_inputHnd->PopupSystemMenu(m_wnd);
9a6384ca 3694#endif // wxUSE_MENUS
0b4f47a3
DS
3695
3696#if wxUSE_ACCEL
8f71aafa 3697 m_wnd->SetAcceleratorTable(table);
0b4f47a3 3698#endif
8f71aafa
VS
3699}
3700
3701void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
3702{
3703 m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
3704 wxTOPLEVEL_BUTTON_CLOSE);
3705}
3706
3707void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
3708{
3709 m_wnd = NULL;
3710 event.Skip();
3711}
3712
3713
2279b45a 3714wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
9467bdb7 3715 : wxStdInputHandler(handler)
8f71aafa 3716{
2279b45a
VS
3717 m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
3718}
3719
3720wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
3721{
3722 if ( m_menuHandler )
8f71aafa 3723 {
2279b45a
VS
3724 m_menuHandler->Detach();
3725 delete m_menuHandler;
3726 }
3727}
3728
3729bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
3730 const wxMouseEvent& event)
3731{
3732 if ( event.LeftDClick() || event.LeftDown() || event.RightDown() )
3733 {
3734 wxTopLevelWindow *tlw =
3735 wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
3736
3737 long hit = tlw->HitTest(event.GetPosition());
3738
3739 if ( event.LeftDClick() && hit == wxHT_TOPLEVEL_TITLEBAR )
8f71aafa 3740 {
2279b45a
VS
3741 tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
3742 tlw->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
3743 : wxTOPLEVEL_BUTTON_MAXIMIZE);
a290fa5a 3744 return true;
8f71aafa 3745 }
2279b45a 3746 else if ( tlw->GetWindowStyle() & wxSYSTEM_MENU )
8f71aafa 3747 {
2279b45a 3748 if ( (event.LeftDown() && hit == wxHT_TOPLEVEL_ICON) ||
00e086a7
WS
3749 (event.RightDown() &&
3750 (hit == wxHT_TOPLEVEL_TITLEBAR ||
2279b45a 3751 hit == wxHT_TOPLEVEL_ICON)) )
8f71aafa 3752 {
9a6384ca 3753#if wxUSE_MENUS
249803fb 3754 PopupSystemMenu(tlw);
9a6384ca 3755#endif // wxUSE_MENUS
a290fa5a 3756 return true;
8f71aafa 3757 }
2279b45a
VS
3758 }
3759 }
3760
9467bdb7 3761 return wxStdInputHandler::HandleMouse(consumer, event);
2279b45a 3762}
8f71aafa 3763
9a6384ca
WS
3764#if wxUSE_MENUS
3765
249803fb 3766void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window) const
2279b45a 3767{
249803fb 3768 wxMenu menu;
2279b45a
VS
3769
3770 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
249803fb
VZ
3771 menu.Append(wxID_RESTORE_FRAME , _("&Restore"));
3772 menu.Append(wxID_MOVE_FRAME , _("&Move"));
2279b45a 3773 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
249803fb 3774 menu.Append(wxID_RESIZE_FRAME , _("&Size"));
2279b45a 3775 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME) )
249803fb 3776 menu.Append(wxID_ICONIZE_FRAME , _("Mi&nimize"));
2279b45a 3777 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
249803fb
VZ
3778 menu.Append(wxID_MAXIMIZE_FRAME , _("Ma&ximize"));
3779 menu.AppendSeparator();
3780 menu.Append(wxID_CLOSE_FRAME, _("Close\tAlt-F4"));
00e086a7 3781
2279b45a
VS
3782 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
3783 {
3784 if ( window->IsMaximized() )
3785 {
249803fb
VZ
3786 menu.Enable(wxID_MAXIMIZE_FRAME, false);
3787 menu.Enable(wxID_MOVE_FRAME, false);
2279b45a 3788 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
249803fb 3789 menu.Enable(wxID_RESIZE_FRAME, false);
2279b45a
VS
3790 }
3791 else
249803fb 3792 menu.Enable(wxID_RESTORE_FRAME, false);
2279b45a
VS
3793 }
3794
249803fb 3795 window->PopupMenu(&menu, wxPoint(0, 0));
2279b45a
VS
3796}
3797
9a6384ca
WS
3798#endif // wxUSE_MENUS
3799
00e086a7 3800bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
2279b45a
VS
3801 bool activated)
3802{
3803 if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
3804 {
3805 // always detach if active frame changed:
3806 m_menuHandler->Detach();
3807
3808 if ( activated )
3809 {
3810 m_menuHandler->Attach(consumer);
8f71aafa
VS
3811 }
3812 }
3813
9467bdb7 3814 return wxStdInputHandler::HandleActivation(consumer, activated);
8f71aafa 3815}
4353a8df 3816
e7637222 3817#endif // wxUSE_THEME_WIN32