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