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