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