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