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