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