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