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