Merge in from trunk r67662 to r64801
[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 #if !defined(__WXMGL__)
2216 static const char *stipple_xpm[] = {
2217 /* columns rows colors chars-per-pixel */
2218 "2 2 2 1",
2219 " c None",
2220 "w c white",
2221 /* pixels */
2222 "w ",
2223 " w",
2224 };
2225 #else
2226 // VS: MGL can only do 8x8 stipple brushes
2227 static const char *stipple_xpm[] = {
2228 /* columns rows colors chars-per-pixel */
2229 "8 8 2 1",
2230 " c None",
2231 "w c white",
2232 /* pixels */
2233 "w w w w ",
2234 " w w w w",
2235 "w w w w ",
2236 " w w w w",
2237 "w w w w ",
2238 " w w w w",
2239 "w w w w ",
2240 " w w w w",
2241 };
2242 #endif
2243 dc.SetBrush(wxBrush(stipple_xpm));
2244
2245 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
2246 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
2247 dc.SetPen(*wxTRANSPARENT_PEN);
2248 dc.DrawRectangle(rectInt);
2249 }
2250 }
2251
2252 void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
2253 const wxRect& rect,
2254 int lenThumb,
2255 wxOrientation orient,
2256 int start,
2257 int end,
2258 int step,
2259 int WXUNUSED(flags),
2260 long style)
2261 {
2262 /* show ticks geometry
2263
2264 left right
2265 ticks shaft ticks
2266 ---- XX ---- <-- x1
2267 ---- XX ----
2268 ---- XX ----
2269 ---- XX ---- <-- x2
2270
2271 ^ ^ ^ ^
2272 | | | |
2273 y3 y1 y2 y4
2274 */
2275
2276 // empty slider?
2277 if ( end == start )
2278 return;
2279
2280 bool left, right;
2281 GetSliderLabelsSides(orient, style, &left, &right);
2282
2283 bool isVertical = orient == wxVERTICAL;
2284
2285 // default thumb size
2286 wxSize sizeThumb = GetSliderThumbSize (rect, 0, orient);
2287 wxCoord defaultLen = (isVertical ? sizeThumb.x : sizeThumb.y);
2288
2289 // normal thumb size
2290 sizeThumb = GetSliderThumbSize (rect, lenThumb, orient);
2291 wxCoord widthThumb = (isVertical ? sizeThumb.y : sizeThumb.x);
2292
2293 wxRect rectShaft = GetSliderShaftRect (rect, lenThumb, orient, style);
2294
2295 wxCoord x1, x2, y1, y2, y3, y4 , len;
2296 x1 = (isVertical ? rectShaft.y : rectShaft.x) + widthThumb/2;
2297 x2 = (isVertical ? rectShaft.GetBottom() : rectShaft.GetRight()) - widthThumb/2;
2298 y1 = (isVertical ? rectShaft.x : rectShaft.y) - defaultLen/2;
2299 y2 = (isVertical ? rectShaft.GetRight() : rectShaft.GetBottom()) + defaultLen/2;
2300 y3 = (isVertical ? rect.x : rect.y);
2301 y4 = (isVertical ? rect.GetRight() : rect.GetBottom());
2302 len = x2 - x1;
2303
2304 dc.SetPen(m_penBlack);
2305
2306 int range = end - start;
2307 for ( int n = 0; n < range; n += step )
2308 {
2309 wxCoord x = x1 + (len*n) / range;
2310
2311 if (left & (y1 > y3))
2312 {
2313 DrawLine(dc, x, y1, x, y3, orient == wxVERTICAL);
2314 }
2315 if (right & (y4 > y2))
2316 {
2317 DrawLine(dc, x, y2, x, y4, orient == wxVERTICAL);
2318 }
2319 }
2320 // always draw the line at the end position
2321 if (left & (y1 > y3))
2322 {
2323 DrawLine(dc, x2, y1, x2, y3, orient == wxVERTICAL);
2324 }
2325 if (right & (y4 > y2))
2326 {
2327 DrawLine(dc, x2, y2, x2, y4, orient == wxVERTICAL);
2328 }
2329 }
2330
2331 #endif // wxUSE_SLIDER
2332
2333 #if wxUSE_MENUS
2334
2335 // ----------------------------------------------------------------------------
2336 // menu and menubar
2337 // ----------------------------------------------------------------------------
2338
2339 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2340 class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo
2341 {
2342 public:
2343 virtual wxSize GetSize() const { return m_size; }
2344
2345 wxCoord GetLabelOffset() const { return m_ofsLabel; }
2346 wxCoord GetAccelOffset() const { return m_ofsAccel; }
2347
2348 wxCoord GetItemHeight() const { return m_heightItem; }
2349
2350 private:
2351 // the total size of the menu
2352 wxSize m_size;
2353
2354 // the offset of the start of the menu item label
2355 wxCoord m_ofsLabel;
2356
2357 // the offset of the start of the accel label
2358 wxCoord m_ofsAccel;
2359
2360 // the height of a normal (not separator) item
2361 wxCoord m_heightItem;
2362
2363 friend wxMenuGeometryInfo *
2364 wxWin32Renderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
2365 };
2366
2367 // FIXME: all constants are hardcoded but shouldn't be
2368 static const wxCoord MENU_LEFT_MARGIN = 9;
2369 static const wxCoord MENU_RIGHT_MARGIN = 18;
2370 static const wxCoord MENU_VERT_MARGIN = 3;
2371
2372 // the margin around bitmap/check marks (on each side)
2373 static const wxCoord MENU_BMP_MARGIN = 2;
2374
2375 // the margin between the labels and accel strings
2376 static const wxCoord MENU_ACCEL_MARGIN = 8;
2377
2378 // the separator height in pixels: in fact, strangely enough, the real height
2379 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2380 // account here
2381 static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
2382
2383 // the size of the standard checkmark bitmap
2384 static const wxCoord MENU_CHECK_SIZE = 9;
2385
2386 void wxWin32Renderer::DrawMenuBarItem(wxDC& dc,
2387 const wxRect& rectOrig,
2388 const wxString& label,
2389 int flags,
2390 int indexAccel)
2391 {
2392 wxRect rect = rectOrig;
2393 rect.height--;
2394
2395 wxDCTextColourChanger colChanger(dc);
2396
2397 if ( flags & wxCONTROL_SELECTED )
2398 {
2399 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2400
2401 const wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2402 dc.SetBrush(colBg);
2403 dc.SetPen(colBg);
2404 dc.DrawRectangle(rect);
2405 }
2406
2407 // don't draw the focus rect around menu bar items
2408 DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
2409 wxALIGN_CENTRE, indexAccel);
2410 }
2411
2412 void wxWin32Renderer::DrawMenuItem(wxDC& dc,
2413 wxCoord y,
2414 const wxMenuGeometryInfo& gi,
2415 const wxString& label,
2416 const wxString& accel,
2417 const wxBitmap& bitmap,
2418 int flags,
2419 int indexAccel)
2420 {
2421 const wxWin32MenuGeometryInfo& geometryInfo =
2422 (const wxWin32MenuGeometryInfo&)gi;
2423
2424 wxRect rect;
2425 rect.x = 0;
2426 rect.y = y;
2427 rect.width = geometryInfo.GetSize().x;
2428 rect.height = geometryInfo.GetItemHeight();
2429
2430 // draw the selected item specially
2431 wxDCTextColourChanger colChanger(dc);
2432 if ( flags & wxCONTROL_SELECTED )
2433 {
2434 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2435
2436 const wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2437 dc.SetBrush(colBg);
2438 dc.SetPen(colBg);
2439 dc.DrawRectangle(rect);
2440 }
2441
2442 // draw the bitmap: use the bitmap provided or the standard checkmark for
2443 // the checkable items
2444 wxBitmap bmp = bitmap;
2445 if ( !bmp.IsOk() && (flags & wxCONTROL_CHECKED) )
2446 {
2447 bmp = GetIndicator(IndicatorType_Menu, flags);
2448 }
2449
2450 if ( bmp.IsOk() )
2451 {
2452 rect.SetRight(geometryInfo.GetLabelOffset());
2453 wxControlRenderer::DrawBitmap(dc, bmp, rect);
2454 }
2455
2456 // draw the label
2457 rect.x = geometryInfo.GetLabelOffset();
2458 rect.SetRight(geometryInfo.GetAccelOffset());
2459
2460 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
2461
2462 // draw the accel string
2463 rect.x = geometryInfo.GetAccelOffset();
2464 rect.SetRight(geometryInfo.GetSize().x);
2465
2466 // NB: no accel index here
2467 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
2468
2469 // draw the submenu indicator
2470 if ( flags & wxCONTROL_ISSUBMENU )
2471 {
2472 rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
2473 rect.width = MENU_RIGHT_MARGIN;
2474
2475 ArrowStyle arrowStyle;
2476 if ( flags & wxCONTROL_DISABLED )
2477 arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InvertedDisabled
2478 : Arrow_Disabled;
2479 else if ( flags & wxCONTROL_SELECTED )
2480 arrowStyle = Arrow_Inverted;
2481 else
2482 arrowStyle = Arrow_Normal;
2483
2484 DrawArrow(dc, rect, Arrow_Right, arrowStyle);
2485 }
2486 }
2487
2488 void wxWin32Renderer::DrawMenuSeparator(wxDC& dc,
2489 wxCoord y,
2490 const wxMenuGeometryInfo& geomInfo)
2491 {
2492 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
2493 }
2494
2495 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& sizeText) const
2496 {
2497 wxSize size = sizeText;
2498
2499 // FIXME: menubar height is configurable under Windows
2500 size.x += 12;
2501 size.y += 6;
2502
2503 return size;
2504 }
2505
2506 wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win,
2507 const wxMenu& menu) const
2508 {
2509 // prepare the dc: for now we draw all the items with the system font
2510 wxClientDC dc(win);
2511 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
2512
2513 // the height of a normal item
2514 wxCoord heightText = dc.GetCharHeight();
2515
2516 // the total height
2517 wxCoord height = 0;
2518
2519 // the max length of label and accel strings: the menu width is the sum of
2520 // them, even if they're for different items (as the accels should be
2521 // aligned)
2522 //
2523 // the max length of the bitmap is never 0 as Windows always leaves enough
2524 // space for a check mark indicator
2525 wxCoord widthLabelMax = 0,
2526 widthAccelMax = 0,
2527 widthBmpMax = MENU_LEFT_MARGIN;
2528
2529 for ( wxMenuItemList::compatibility_iterator node = menu.GetMenuItems().GetFirst();
2530 node;
2531 node = node->GetNext() )
2532 {
2533 // height of this item
2534 wxCoord h;
2535
2536 wxMenuItem *item = node->GetData();
2537 if ( item->IsSeparator() )
2538 {
2539 h = MENU_SEPARATOR_HEIGHT;
2540 }
2541 else // not separator
2542 {
2543 h = heightText;
2544
2545 wxCoord widthLabel;
2546 dc.GetTextExtent(item->GetItemLabelText(), &widthLabel, NULL);
2547 if ( widthLabel > widthLabelMax )
2548 {
2549 widthLabelMax = widthLabel;
2550 }
2551
2552 wxCoord widthAccel;
2553 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
2554 if ( widthAccel > widthAccelMax )
2555 {
2556 widthAccelMax = widthAccel;
2557 }
2558
2559 const wxBitmap& bmp = item->GetBitmap();
2560 if ( bmp.IsOk() )
2561 {
2562 wxCoord widthBmp = bmp.GetWidth();
2563 if ( widthBmp > widthBmpMax )
2564 widthBmpMax = widthBmp;
2565 }
2566 //else if ( item->IsCheckable() ): no need to check for this as
2567 // MENU_LEFT_MARGIN is big enough to show the check mark
2568 }
2569
2570 h += 2*MENU_VERT_MARGIN;
2571
2572 // remember the item position and height
2573 item->SetGeometry(height, h);
2574
2575 height += h;
2576 }
2577
2578 // bundle the metrics into a struct and return it
2579 wxWin32MenuGeometryInfo *gi = new wxWin32MenuGeometryInfo;
2580
2581 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
2582 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
2583 if ( widthAccelMax > 0 )
2584 {
2585 // if we actually have any accesl, add a margin
2586 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
2587 }
2588
2589 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
2590
2591 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
2592 gi->m_size.y = height;
2593
2594 return gi;
2595 }
2596
2597 #endif // wxUSE_MENUS
2598
2599 #if wxUSE_STATUSBAR
2600
2601 // ----------------------------------------------------------------------------
2602 // status bar
2603 // ----------------------------------------------------------------------------
2604
2605 void wxWin32Renderer::DrawStatusField(wxDC& dc,
2606 const wxRect& rect,
2607 const wxString& label,
2608 int flags,
2609 int style)
2610 {
2611 wxRect rectIn;
2612
2613 if ( flags & wxCONTROL_SIZEGRIP )
2614 {
2615 // draw the size grip: it is a normal rect except that in the lower
2616 // right corner we have several bands which may be used for dragging
2617 // the status bar corner
2618 //
2619 // each band consists of 4 stripes: m_penHighlight, double
2620 // m_penDarkGrey and transparent one
2621 wxCoord x2 = rect.GetRight(),
2622 y2 = rect.GetBottom();
2623
2624 // draw the upper left part of the rect normally
2625 if (style != wxSB_FLAT)
2626 {
2627 if (style == wxSB_RAISED)
2628 dc.SetPen(m_penHighlight);
2629 else
2630 dc.SetPen(m_penDarkGrey);
2631 dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2);
2632 dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop());
2633 }
2634
2635 // draw the grey stripes of the grip
2636 size_t n;
2637 wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1;
2638 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
2639 {
2640 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
2641 dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1);
2642 }
2643
2644 // draw the white stripes
2645 dc.SetPen(m_penHighlight);
2646 ofs = WIDTH_STATUSBAR_GRIP_BAND + 1;
2647 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
2648 {
2649 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
2650 }
2651
2652 // draw the remaining rect boundaries
2653 if (style != wxSB_FLAT)
2654 {
2655 if (style == wxSB_RAISED)
2656 dc.SetPen(m_penDarkGrey);
2657 else
2658 dc.SetPen(m_penHighlight);
2659 ofs -= WIDTH_STATUSBAR_GRIP_BAND;
2660 dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1);
2661 dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2);
2662 }
2663
2664 rectIn = rect;
2665 rectIn.Deflate(1);
2666
2667 rectIn.width -= STATUSBAR_GRIP_SIZE;
2668
2669 // this will prevent the standard version from drawing any borders
2670 style = wxSB_FLAT;
2671 }
2672
2673 wxStdRenderer::DrawStatusField(dc, rect, label, flags, style);
2674 }
2675
2676 #endif // wxUSE_STATUSBAR
2677
2678 // ----------------------------------------------------------------------------
2679 // combobox
2680 // ----------------------------------------------------------------------------
2681
2682 void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal,
2683 wxBitmap * WXUNUSED(bmpFocus),
2684 wxBitmap *bmpPressed,
2685 wxBitmap *bmpDisabled)
2686 {
2687 static const wxCoord widthCombo = 16;
2688 static const wxCoord heightCombo = 17;
2689
2690 wxMemoryDC dcMem;
2691
2692 if ( bmpNormal )
2693 {
2694 bmpNormal->Create(widthCombo, heightCombo);
2695 dcMem.SelectObject(*bmpNormal);
2696 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2697 Arrow_Down, Arrow_Normal);
2698 }
2699
2700 if ( bmpPressed )
2701 {
2702 bmpPressed->Create(widthCombo, heightCombo);
2703 dcMem.SelectObject(*bmpPressed);
2704 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2705 Arrow_Down, Arrow_Pressed);
2706 }
2707
2708 if ( bmpDisabled )
2709 {
2710 bmpDisabled->Create(widthCombo, heightCombo);
2711 dcMem.SelectObject(*bmpDisabled);
2712 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2713 Arrow_Down, Arrow_Disabled);
2714 }
2715 }
2716
2717 // ----------------------------------------------------------------------------
2718 // scrollbar
2719 // ----------------------------------------------------------------------------
2720
2721 void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
2722 {
2723 if ( isPressed )
2724 {
2725 DrawRect(dc, rect, m_penDarkGrey);
2726
2727 // the arrow is usually drawn inside border of width 2 and is offset by
2728 // another pixel in both directions when it's pressed - as the border
2729 // in this case is more narrow as well, we have to adjust rect like
2730 // this:
2731 rect->Inflate(-1);
2732 rect->x++;
2733 rect->y++;
2734 }
2735 else // !pressed
2736 {
2737 DrawAntiSunkenBorder(dc, rect);
2738 }
2739 }
2740
2741 void wxWin32Renderer::DrawArrow(wxDC& dc,
2742 wxDirection dir,
2743 const wxRect& rect,
2744 int flags)
2745 {
2746 ArrowStyle arrowStyle;
2747 if ( flags & wxCONTROL_PRESSED )
2748 {
2749 // can't be pressed and disabled
2750 arrowStyle = Arrow_Pressed;
2751 }
2752 else
2753 {
2754 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
2755 }
2756
2757 DrawArrowButton(dc, rect, GetArrowDirection(dir), arrowStyle);
2758 }
2759
2760 void wxWin32Renderer::DrawArrow(wxDC& dc,
2761 const wxRect& rect,
2762 ArrowDirection arrowDir,
2763 ArrowStyle arrowStyle)
2764 {
2765 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
2766
2767 // under Windows the arrows always have the same size so just centre it in
2768 // the provided rectangle
2769 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
2770 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
2771
2772 // Windows does it like this...
2773 if ( arrowDir == Arrow_Left )
2774 x--;
2775
2776 // draw it
2777 dc.DrawBitmap(bmp, x, y, true /* use mask */);
2778 }
2779
2780 void wxWin32Renderer::DrawArrowButton(wxDC& dc,
2781 const wxRect& rectAll,
2782 ArrowDirection arrowDir,
2783 ArrowStyle arrowStyle)
2784 {
2785 wxRect rect = rectAll;
2786 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
2787 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
2788 DrawArrow(dc, rect, arrowDir, arrowStyle);
2789 }
2790
2791 void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
2792 wxOrientation WXUNUSED(orient),
2793 const wxRect& rect,
2794 int WXUNUSED(flags))
2795 {
2796 // we don't use the flags, the thumb never changes appearance
2797 wxRect rectThumb = rect;
2798 DrawArrowBorder(dc, &rectThumb);
2799 DrawBackground(dc, wxNullColour, rectThumb);
2800 }
2801
2802 void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
2803 wxOrientation WXUNUSED(orient),
2804 const wxRect& rectBar,
2805 int flags)
2806 {
2807 wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
2808 ? wxColourScheme::SCROLLBAR_PRESSED
2809 : wxColourScheme::SCROLLBAR;
2810 DrawBackground(dc, m_scheme->Get(col), rectBar);
2811 }
2812
2813 // ----------------------------------------------------------------------------
2814 // standard icons
2815 // ----------------------------------------------------------------------------
2816
2817 /* Copyright (c) Julian Smart */
2818 static const char *error_xpm[]={
2819 /* columns rows colors chars-per-pixel */
2820 "32 32 70 1",
2821 "- c #BF0101",
2822 "b c #361F1F",
2823 "& c #C08484",
2824 "X c #BF3333",
2825 "# c #C08181",
2826 "% c #C01111",
2827 "d c #C51515",
2828 "s c #551818",
2829 "O c #C07E7E",
2830 ": c #C00E0E",
2831 "u c #E28A8A",
2832 "2 c #C81F1F",
2833 "8 c #FFFFFF",
2834 "p c #E59494",
2835 "< c #BB0101",
2836 "y c #DA6A6A",
2837 "A c #4C4C4C",
2838 "9 c #F7DFDF",
2839 "@ c #BF5353",
2840 "w c #FAE9E9",
2841 "F c #272727",
2842 "5 c #D24A4A",
2843 ". c #C06363",
2844 "n c #BF8282",
2845 "7 c #F2C9C9",
2846 "t c #C09292",
2847 "M c #3E3E3E",
2848 "x c #4D4D4D",
2849 "4 c #CA2A2A",
2850 "h c #E79F9F",
2851 "* c #C05454",
2852 "D c #711212",
2853 "V c #737373",
2854 "$ c #BF3232",
2855 "N c #900B0B",
2856 "6 c #BD0303",
2857 "3 c #DF7F7F",
2858 "K c #6F1212",
2859 "C c #BD0000",
2860 "m c #950909",
2861 "P c #8A8A8A",
2862 "j c #D75F5F",
2863 " c None",
2864 "e c #F4D4D4",
2865 "S c #BF2020",
2866 "L c #747474",
2867 "G c #842C2C",
2868 "c c #ECB4B4",
2869 "l c #2E2121",
2870 "g c #BF7E7E",
2871 "k c #9B0808",
2872 "= c #BF0505",
2873 "a c #B10303",
2874 "q c #7E2020",
2875 "1 c #642222",
2876 "J c #676767",
2877 "B c #322020",
2878 "; c #C00303",
2879 "i c #242424",
2880 "o c #C00000",
2881 "> c #BF1F1F",
2882 ", c #842B2B",
2883 "f c #701212",
2884 "0 c #BE0000",
2885 "r c #960909",
2886 "H c #686868",
2887 "v c #BC0000",
2888 "Z c #671414",
2889 "+ c #C02020",
2890 "z c #CD3535",
2891 /* pixels */
2892 " ",
2893 " ",
2894 " .XoooOO ",
2895 " .+ooooooooo@# ",
2896 " $oooooooooooo%& ",
2897 " *=-ooooooooooooo;: ",
2898 " *oooooooooooooooooo> ",
2899 " =ooooooooooooooooooo, ",
2900 " $-ooooooooooooooooooo<1 ",
2901 " .oooooo2334ooo533oooooo6 ",
2902 " +ooooooo789oo2883oooooo0q ",
2903 " oooooooo2w83o78eoooooooor ",
2904 " toooooooooy88u884oooooooori ",
2905 " Xooooooooooe888poooooooooas ",
2906 " ooooooooooo4889doooooooooof ",
2907 " ooooooooooo588w2oooooooooofi ",
2908 " oooooooooodw8887oooooooooofi ",
2909 " goooooooooh8w588jooooooookli ",
2910 " tooooooooz885op8wdooooooorix ",
2911 " oooooood98cood98cooooooori ",
2912 " @oooooop8w2ooo5885ooooovbi ",
2913 " n%ooooooooooooooooooooomiM ",
2914 " &;oooooooooooooooooooNBiV ",
2915 " :ooooooooooooooooooCZiA ",
2916 " nSooooooooooooooooCDiF ",
2917 " nG<oooooooooooooNZiiH ",
2918 " 160ooooooooovmBiFH ",
2919 " nqrraoookrrbiiA ",
2920 " nJisKKKliiiML ",
2921 " nPiiix ",
2922 " ",
2923 " "
2924 };
2925
2926 /* Copyright (c) Julian Smart */
2927 static const char *info_xpm[]={
2928 /* columns rows colors chars-per-pixel */
2929 "32 32 17 1",
2930 "* c #A1A3FB",
2931 "X c #FFFFFF",
2932 "O c #191EF4",
2933 "= c #777AF9",
2934 ": c #4D51F7",
2935 " c None",
2936 "- c #2328F5",
2937 "+ c #4247F6",
2938 "; c #C1C2FC",
2939 ". c #C0C0C0",
2940 "& c #E0E1FE",
2941 "% c #242424",
2942 "> c #2D32F5",
2943 "o c #CBCCFD",
2944 "# c #0309F3",
2945 "@ c #8C8FFA",
2946 "$ c #EAEBFE",
2947 /* pixels */
2948 " ....... ",
2949 " ...XXXXXXX... ",
2950 " ..XXXXXXXXXXXXX.. ",
2951 " .XXXXXXXXXXXXXXXXX. ",
2952 " .XXXXXXXXoO+XXXXXXXX. ",
2953 " .XXXXXXXXX@#OXXXXXXXXX. ",
2954 " .XXXXXXXXXX$@oXXXXXXXXXX. ",
2955 " .XXXXXXXXXXXXXXXXXXXXXXX.% ",
2956 " .XXXXXXXXX&*=-XXXXXXXXXX.%% ",
2957 ".XXXXXXXXXX;:#>XXXXXXXXXXX.% ",
2958 ".XXXXXXXXXXX;#+XXXXXXXXXXX.% ",
2959 ".XXXXXXXXXXX;#+XXXXXXXXXXX.%% ",
2960 " .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
2961 " .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
2962 " .XXXXXXXXXX;#+XXXXXXXXXX.%% ",
2963 " .XXXXXXXX*-##+XXXXXXXX.%%% ",
2964 " .XXXXXXXXXXXXXXXXXXX.%%%% ",
2965 " .XXXXXXXXXXXXXXXXX.%%%% ",
2966 " ..XXXXXXXXXXXXX..%%%% ",
2967 " %...XXXXXXXX..%%%%% ",
2968 " %%%..XXXXXX.%%%%% ",
2969 " %%%.XXXXX.%%% ",
2970 " %.XXXX.%% ",
2971 " .XXX.%% ",
2972 " .XX.%% ",
2973 " .X.%% ",
2974 " ..%% ",
2975 " .%% ",
2976 " %% ",
2977 " % ",
2978 " ",
2979 " "
2980 };
2981
2982 /* Copyright (c) Julian Smart */
2983 static const char *question_xpm[]={
2984 /* columns rows colors chars-per-pixel */
2985 "32 32 16 1",
2986 "O c #A3A3FF",
2987 "X c #FFFFFF",
2988 "% c #CACAFF",
2989 "- c #4141FF",
2990 "= c #6060FF",
2991 "* c #2B2BFF",
2992 "@ c #B5B5FF",
2993 " c None",
2994 "# c #1616FF",
2995 "+ c #8181FF",
2996 "$ c #0000FF",
2997 ". c #C0C0C0",
2998 "; c #5555FF",
2999 ": c #242424",
3000 "o c #E7E7FF",
3001 "& c #7575FF",
3002 /* pixels */
3003 " ....... ",
3004 " ...XXXXXXX... ",
3005 " ..XXXXXXXXXXXXX.. ",
3006 " .XXXXXXoO++@XXXXXX. ",
3007 " .XXXXXXO#$$$$#%XXXXX. ",
3008 " .XXXXXX@$$#&&#$#oXXXXX. ",
3009 " .XXXXXXX*$$%XX%$$=XXXXXX. ",
3010 " .XXXXXXX+-;XXXX$$-XXXXXX.: ",
3011 " .XXXXXXXXXXXXX+$$&XXXXXX.:: ",
3012 ".XXXXXXXXXXXXo;$$*oXXXXXXX.: ",
3013 ".XXXXXXXXXXXo*$$*oXXXXXXXX.: ",
3014 ".XXXXXXXXXXX+$$*oXXXXXXXXX.:: ",
3015 " .XXXXXXXXXX-$$oXXXXXXXXX.::: ",
3016 " .XXXXXXXXXXX--XXXXXXXXXX.::: ",
3017 " .XXXXXXXXXXXXXXXXXXXXXXX.:: ",
3018 " .XXXXXXXXX-$$XXXXXXXXX.::: ",
3019 " .XXXXXXXX-$$XXXXXXXX.:::: ",
3020 " .XXXXXXXO++XXXXXXX.:::: ",
3021 " ..XXXXXXXXXXXXX..:::: ",
3022 " :...XXXXXXXX..::::: ",
3023 " :::..XXXXXX.::::: ",
3024 " :::.XXXXX.::: ",
3025 " :.XXXX.:: ",
3026 " .XXX.:: ",
3027 " .XX.:: ",
3028 " .X.:: ",
3029 " ..:: ",
3030 " .:: ",
3031 " :: ",
3032 " : ",
3033 " ",
3034 " "
3035 };
3036
3037 /* Copyright (c) Julian Smart */
3038 static const char *warning_xpm[]={
3039 /* columns rows colors chars-per-pixel */
3040 "32 32 9 1",
3041 "@ c Black",
3042 "o c #A6A800",
3043 "+ c #8A8C00",
3044 "$ c #B8BA00",
3045 " c None",
3046 "O c #6E7000",
3047 "X c #DCDF00",
3048 ". c #C00000",
3049 "# c #373800",
3050 /* pixels */
3051 " ",
3052 " ",
3053 " ",
3054 " . ",
3055 " ... ",
3056 " ... ",
3057 " ..... ",
3058 " ...X.. ",
3059 " ..XXX.. ",
3060 " ...XXX... ",
3061 " ..XXXXX.. ",
3062 " ..XXXXXX... ",
3063 " ...XXoO+XX.. ",
3064 " ..XXXO@#XXX.. ",
3065 " ..XXXXO@#XXX... ",
3066 " ...XXXXO@#XXXX.. ",
3067 " ..XXXXXO@#XXXX... ",
3068 " ...XXXXXo@OXXXXX.. ",
3069 " ...XXXXXXo@OXXXXXX.. ",
3070 " ..XXXXXXX$@OXXXXXX... ",
3071 " ...XXXXXXXX@XXXXXXXX.. ",
3072 " ...XXXXXXXXXXXXXXXXXX... ",
3073 " ..XXXXXXXXXXOXXXXXXXXX.. ",
3074 " ...XXXXXXXXXO@#XXXXXXXXX.. ",
3075 " ..XXXXXXXXXXX#XXXXXXXXXX... ",
3076 " ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
3077 " ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
3078 " .............................. ",
3079 " .............................. ",
3080 " ",
3081 " ",
3082 " "
3083 };
3084
3085
3086 wxBitmap wxWin32ArtProvider::CreateBitmap(const wxArtID& id,
3087 const wxArtClient& WXUNUSED(client),
3088 const wxSize& WXUNUSED(size))
3089 {
3090 if ( id == wxART_INFORMATION )
3091 return wxBitmap(info_xpm);
3092 if ( id == wxART_ERROR )
3093 return wxBitmap(error_xpm);
3094 if ( id == wxART_WARNING )
3095 return wxBitmap(warning_xpm);
3096 if ( id == wxART_QUESTION )
3097 return wxBitmap(question_xpm);
3098 return wxNullBitmap;
3099 }
3100
3101
3102 #if wxUSE_TEXTCTRL
3103
3104 // ----------------------------------------------------------------------------
3105 // text control geometry
3106 // ----------------------------------------------------------------------------
3107
3108 wxRect
3109 wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
3110 const wxRect& rect) const
3111 {
3112 wxRect rectTotal = wxStdRenderer::GetTextTotalArea(text, rect);
3113
3114 // this is strange but it's what Windows does
3115 rectTotal.height++;
3116
3117 return rectTotal;
3118 }
3119
3120 wxRect
3121 wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
3122 const wxRect& rect,
3123 wxCoord *extraSpaceBeyond) const
3124 {
3125 wxRect rectText = rect;
3126
3127 // undo GetTextTotalArea()
3128 if ( rectText.height > 0 )
3129 rectText.height--;
3130
3131 return wxStdRenderer::GetTextClientArea(text, rect, extraSpaceBeyond);
3132 }
3133
3134 #endif // wxUSE_TEXTCTRL
3135
3136 // ----------------------------------------------------------------------------
3137 // size adjustments
3138 // ----------------------------------------------------------------------------
3139
3140 void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
3141 {
3142 #if wxUSE_SCROLLBAR
3143 if ( wxDynamicCast(window, wxScrollBar) )
3144 {
3145 // we only set the width of vert scrollbars and height of the
3146 // horizontal ones
3147 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
3148 size->y = m_sizeScrollbarArrow.y;
3149 else
3150 size->x = m_sizeScrollbarArrow.x;
3151
3152 // skip border width adjustments, they don't make sense for us
3153 return;
3154 }
3155 #endif // wxUSE_SCROLLBAR
3156
3157 #if wxUSE_BMPBUTTON
3158 if ( wxDynamicCast(window, wxBitmapButton) )
3159 {
3160 // do nothing
3161 } else
3162 #endif // wxUSE_BMPBUTTON
3163 #if wxUSE_BUTTON || wxUSE_TOGGLEBTN
3164 if ( 0
3165 # if wxUSE_BUTTON
3166 || wxDynamicCast(window, wxButton)
3167 # endif // wxUSE_BUTTON
3168 # if wxUSE_TOGGLEBTN
3169 || wxDynamicCast(window, wxToggleButton)
3170 # endif // wxUSE_TOGGLEBTN
3171 )
3172 {
3173 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3174 {
3175 // TODO: don't harcode all this
3176 size->x += 3*window->GetCharWidth();
3177
3178 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
3179 if ( size->y < heightBtn - 8 )
3180 size->y = heightBtn;
3181 else
3182 size->y += 9;
3183 }
3184
3185 // for compatibility with other ports, the buttons default size is never
3186 // less than the standard one, but not when display not PDAs.
3187 if (wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA)
3188 {
3189 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3190 {
3191 wxSize szDef = wxButton::GetDefaultSize();
3192 if ( size->x < szDef.x )
3193 size->x = szDef.x;
3194 }
3195 }
3196
3197 // no border width adjustments for buttons
3198 return;
3199 }
3200 #endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
3201
3202 wxStdRenderer::AdjustSize(size, window);
3203 }
3204
3205 wxBitmap wxWin32Renderer::GetFrameButtonBitmap(FrameButtonType type)
3206 {
3207 wxBitmap& bmp = m_bmpFrameButtons[type];
3208 if ( !bmp.IsOk() )
3209 {
3210 bmp = wxBitmap(ms_xpmFrameButtons[type]);
3211 }
3212
3213 return bmp;
3214 }
3215
3216 // ============================================================================
3217 // wxInputHandler
3218 // ============================================================================
3219
3220 // ----------------------------------------------------------------------------
3221 // wxWin32InputHandler
3222 // ----------------------------------------------------------------------------
3223
3224 bool wxWin32InputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
3225 const wxKeyEvent& WXUNUSED(event),
3226 bool WXUNUSED(pressed))
3227 {
3228 return false;
3229 }
3230
3231 bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control,
3232 const wxMouseEvent& event)
3233 {
3234 // clicking on the control gives it focus
3235 if ( event.ButtonDown() )
3236 {
3237 wxWindow * const win = control->GetInputWindow();
3238
3239 if ( win->CanAcceptFocus() && wxWindow::FindFocus() != win )
3240 {
3241 win->SetFocus();
3242
3243 return true;
3244 }
3245 }
3246
3247 return false;
3248 }
3249
3250 #if wxUSE_SCROLLBAR
3251
3252 // ----------------------------------------------------------------------------
3253 // wxWin32ScrollBarInputHandler
3254 // ----------------------------------------------------------------------------
3255
3256 wxWin32ScrollBarInputHandler::
3257 wxWin32ScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *handler)
3258 : wxStdScrollBarInputHandler(renderer, handler)
3259 {
3260 m_scrollPaused = false;
3261 m_interval = 0;
3262 }
3263
3264 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
3265 const wxControlAction& action)
3266 {
3267 // stop if went beyond the position of the original click (this can only
3268 // happen when we scroll by pages)
3269 bool stop = false;
3270 if ( action == wxACTION_SCROLL_PAGE_DOWN )
3271 {
3272 stop = scrollbar->HitTestBar(m_ptStartScrolling) != wxHT_SCROLLBAR_BAR_2;
3273 }
3274 else if ( action == wxACTION_SCROLL_PAGE_UP )
3275 {
3276 stop = scrollbar->HitTestBar(m_ptStartScrolling) != wxHT_SCROLLBAR_BAR_1;
3277 }
3278
3279 if ( stop )
3280 {
3281 StopScrolling(scrollbar);
3282
3283 scrollbar->Refresh();
3284
3285 return false;
3286 }
3287
3288 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
3289 }
3290
3291 bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
3292 const wxMouseEvent& event)
3293 {
3294 // remember the current state
3295 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
3296
3297 // do process the message
3298 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
3299
3300 // analyse the changes
3301 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
3302 {
3303 // we just started dragging the thumb, remember its initial position to
3304 // be able to restore it if the drag is cancelled later
3305 m_eventStartDrag = event;
3306 }
3307
3308 return rc;
3309 }
3310
3311 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
3312 const wxMouseEvent& event)
3313 {
3314 // we don't highlight scrollbar elements, so there is no need to process
3315 // mouse move events normally - only do it while mouse is captured (i.e.
3316 // when we're dragging the thumb or pressing on something)
3317 if ( !m_winCapture )
3318 return false;
3319
3320 if ( event.Entering() )
3321 {
3322 // we're not interested in this at all
3323 return false;
3324 }
3325
3326 wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
3327 wxHitTest ht;
3328 if ( m_scrollPaused )
3329 {
3330 // check if the mouse returned to its original location
3331
3332 if ( event.Leaving() )
3333 {
3334 // it surely didn't
3335 return false;
3336 }
3337
3338 ht = scrollbar->HitTestBar(event.GetPosition());
3339 if ( ht == m_htLast )
3340 {
3341 // yes it did, resume scrolling
3342 m_scrollPaused = false;
3343 if ( m_timerScroll )
3344 {
3345 // we were scrolling by line/page, restart timer
3346 m_timerScroll->Start(m_interval);
3347
3348 Press(scrollbar, true);
3349 }
3350 else // we were dragging the thumb
3351 {
3352 // restore its last location
3353 HandleThumbMove(scrollbar, m_eventLastDrag);
3354 }
3355
3356 return true;
3357 }
3358 }
3359 else // normal case, scrolling hasn't been paused
3360 {
3361 // if we're scrolling the scrollbar because the arrow or the shaft was
3362 // pressed, check that the mouse stays on the same scrollbar element
3363
3364 #if 0
3365 // Always let thumb jump back if we leave the scrollbar
3366 if ( event.Moving() )
3367 {
3368 ht = scrollbar->HitTestBar(event.GetPosition());
3369 }
3370 else // event.Leaving()
3371 {
3372 ht = wxHT_NOWHERE;
3373 }
3374 #else
3375 // Jump back only if we get far away from it
3376 wxPoint pos = event.GetPosition();
3377 if (scrollbar->HasFlag( wxVERTICAL ))
3378 {
3379 if (pos.x > -40 && pos.x < scrollbar->GetSize().x+40)
3380 pos.x = 5;
3381 }
3382 else
3383 {
3384 if (pos.y > -40 && pos.y < scrollbar->GetSize().y+40)
3385 pos.y = 5;
3386 }
3387 ht = scrollbar->HitTestBar(pos);
3388 #endif
3389
3390 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3391 // is still ok - we only want to catch the case when the mouse leaves
3392 // the scrollbar here
3393 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
3394 {
3395 ht = wxHT_SCROLLBAR_THUMB;
3396 }
3397
3398 if ( ht != m_htLast )
3399 {
3400 // what were we doing? 2 possibilities: either an arrow/shaft was
3401 // pressed in which case we have a timer and so we just stop it or
3402 // we were dragging the thumb
3403 if ( m_timerScroll )
3404 {
3405 // pause scrolling
3406 m_interval = m_timerScroll->GetInterval();
3407 m_timerScroll->Stop();
3408 m_scrollPaused = true;
3409
3410 // unpress the arrow
3411 Press(scrollbar, false);
3412 }
3413 else // we were dragging the thumb
3414 {
3415 // remember the current thumb position to be able to restore it
3416 // if the mouse returns to it later
3417 m_eventLastDrag = event;
3418
3419 // and restore the original position (before dragging) of the
3420 // thumb for now
3421 HandleThumbMove(scrollbar, m_eventStartDrag);
3422 }
3423
3424 return true;
3425 }
3426 }
3427
3428 return wxStdInputHandler::HandleMouseMove(control, event);
3429 }
3430
3431 #endif // wxUSE_SCROLLBAR
3432
3433 #if wxUSE_CHECKBOX
3434
3435 // ----------------------------------------------------------------------------
3436 // wxWin32CheckboxInputHandler
3437 // ----------------------------------------------------------------------------
3438
3439 bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control,
3440 const wxKeyEvent& event,
3441 bool pressed)
3442 {
3443 if ( pressed )
3444 {
3445 wxControlAction action;
3446 int keycode = event.GetKeyCode();
3447 switch ( keycode )
3448 {
3449 case WXK_SPACE:
3450 action = wxACTION_CHECKBOX_TOGGLE;
3451 break;
3452
3453 case WXK_SUBTRACT:
3454 case WXK_NUMPAD_SUBTRACT:
3455 action = wxACTION_CHECKBOX_CHECK;
3456 break;
3457
3458 case WXK_ADD:
3459 case WXK_NUMPAD_ADD:
3460 case WXK_NUMPAD_EQUAL:
3461 action = wxACTION_CHECKBOX_CLEAR;
3462 break;
3463 }
3464
3465 if ( !action.IsEmpty() )
3466 {
3467 control->PerformAction(action);
3468
3469 return true;
3470 }
3471 }
3472
3473 return false;
3474 }
3475
3476 #endif // wxUSE_CHECKBOX
3477
3478 #if wxUSE_TEXTCTRL
3479
3480 // ----------------------------------------------------------------------------
3481 // wxWin32TextCtrlInputHandler
3482 // ----------------------------------------------------------------------------
3483
3484 bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control,
3485 const wxKeyEvent& event,
3486 bool pressed)
3487 {
3488 // handle only MSW-specific text bindings here, the others are handled in
3489 // the base class
3490 if ( pressed )
3491 {
3492 int keycode = event.GetKeyCode();
3493
3494 wxControlAction action;
3495 if ( keycode == WXK_DELETE && event.ShiftDown() )
3496 {
3497 action = wxACTION_TEXT_CUT;
3498 }
3499 else if ( keycode == WXK_INSERT )
3500 {
3501 if ( event.ControlDown() )
3502 action = wxACTION_TEXT_COPY;
3503 else if ( event.ShiftDown() )
3504 action = wxACTION_TEXT_PASTE;
3505 }
3506
3507 if ( action != wxACTION_NONE )
3508 {
3509 control->PerformAction(action);
3510
3511 return true;
3512 }
3513 }
3514
3515 return wxStdInputHandler::HandleKey(control, event, pressed);
3516 }
3517
3518 #endif // wxUSE_TEXTCTRL
3519
3520 #if wxUSE_STATUSBAR
3521
3522 // ----------------------------------------------------------------------------
3523 // wxWin32StatusBarInputHandler
3524 // ----------------------------------------------------------------------------
3525
3526 wxWin32StatusBarInputHandler::
3527 wxWin32StatusBarInputHandler(wxInputHandler *handler)
3528 : wxStdInputHandler(handler)
3529 {
3530 m_isOnGrip = false;
3531 }
3532
3533 bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar,
3534 const wxPoint& pt) const
3535 {
3536 if ( statbar->HasFlag(wxST_SIZEGRIP) &&
3537 statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
3538 {
3539 wxTopLevelWindow *
3540 parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow);
3541
3542 wxCHECK_MSG( parentTLW, false,
3543 wxT("the status bar should be a child of a TLW") );
3544
3545 // a maximized window can't be resized anyhow
3546 if ( !parentTLW->IsMaximized() )
3547 {
3548 // VZ: I think that the standard Windows behaviour is to only
3549 // show the resizing cursor when the mouse is on top of the
3550 // grip itself but apparently different Windows versions behave
3551 // differently (?) and it seems a better UI to allow resizing
3552 // the status bar even when the mouse is above the grip
3553 wxSize sizeSbar = statbar->GetSize();
3554
3555 int diff = sizeSbar.x - pt.x;
3556 return diff >= 0 && diff < (wxCoord)STATUSBAR_GRIP_SIZE;
3557 }
3558 }
3559
3560 return false;
3561 }
3562
3563 bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
3564 const wxMouseEvent& event)
3565 {
3566 if ( event.Button(1) )
3567 {
3568 if ( event.ButtonDown(1) )
3569 {
3570 wxWindow *statbar = consumer->GetInputWindow();
3571
3572 if ( IsOnGrip(statbar, event.GetPosition()) )
3573 {
3574 wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
3575 wxTopLevelWindow);
3576 if ( tlw )
3577 {
3578 tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
3579 wxHT_TOPLEVEL_BORDER_SE);
3580
3581 statbar->SetCursor(m_cursorOld);
3582
3583 return true;
3584 }
3585 }
3586 }
3587 }
3588
3589 return wxStdInputHandler::HandleMouse(consumer, event);
3590 }
3591
3592 bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
3593 const wxMouseEvent& event)
3594 {
3595 wxWindow *statbar = consumer->GetInputWindow();
3596
3597 bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
3598 if ( isOnGrip != m_isOnGrip )
3599 {
3600 m_isOnGrip = isOnGrip;
3601 if ( isOnGrip )
3602 {
3603 m_cursorOld = statbar->GetCursor();
3604 statbar->SetCursor(wxCURSOR_SIZENWSE);
3605 }
3606 else
3607 {
3608 statbar->SetCursor(m_cursorOld);
3609 }
3610 }
3611
3612 return wxStdInputHandler::HandleMouseMove(consumer, event);
3613 }
3614
3615 #endif // wxUSE_STATUSBAR
3616
3617 // ----------------------------------------------------------------------------
3618 // wxWin32FrameInputHandler
3619 // ----------------------------------------------------------------------------
3620
3621 class wxWin32SystemMenuEvtHandler : public wxEvtHandler
3622 {
3623 public:
3624 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
3625
3626 void Attach(wxInputConsumer *consumer);
3627 void Detach();
3628
3629 private:
3630 DECLARE_EVENT_TABLE()
3631 void OnSystemMenu(wxCommandEvent &event);
3632 void OnCloseFrame(wxCommandEvent &event);
3633 void OnClose(wxCloseEvent &event);
3634
3635 wxWin32FrameInputHandler *m_inputHnd;
3636 wxTopLevelWindow *m_wnd;
3637 #if wxUSE_ACCEL
3638 wxAcceleratorTable m_oldAccelTable;
3639 #endif
3640 };
3641
3642 wxWin32SystemMenuEvtHandler::
3643 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler)
3644 {
3645 m_inputHnd = handler;
3646 m_wnd = NULL;
3647 }
3648
3649 void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
3650 {
3651 wxASSERT_MSG( m_wnd == NULL, wxT("can't attach the handler twice!") );
3652
3653 m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
3654 m_wnd->PushEventHandler(this);
3655
3656 #if wxUSE_ACCEL
3657 // VS: This code relies on using generic implementation of
3658 // wxAcceleratorTable in wxUniv!
3659 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
3660 m_oldAccelTable = table;
3661 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
3662 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
3663 m_wnd->SetAcceleratorTable(table);
3664 #endif
3665 }
3666
3667 void wxWin32SystemMenuEvtHandler::Detach()
3668 {
3669 if ( m_wnd )
3670 {
3671 #if wxUSE_ACCEL
3672 m_wnd->SetAcceleratorTable(m_oldAccelTable);
3673 #endif
3674 m_wnd->RemoveEventHandler(this);
3675 m_wnd = NULL;
3676 }
3677 }
3678
3679 BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
3680 EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
3681 EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
3682 EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
3683 END_EVENT_TABLE()
3684
3685 void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
3686 {
3687 #if wxUSE_ACCEL
3688 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
3689 m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
3690 #endif
3691
3692 #if wxUSE_MENUS
3693 m_inputHnd->PopupSystemMenu(m_wnd);
3694 #endif // wxUSE_MENUS
3695
3696 #if wxUSE_ACCEL
3697 m_wnd->SetAcceleratorTable(table);
3698 #endif
3699 }
3700
3701 void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
3702 {
3703 m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
3704 wxTOPLEVEL_BUTTON_CLOSE);
3705 }
3706
3707 void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
3708 {
3709 m_wnd = NULL;
3710 event.Skip();
3711 }
3712
3713
3714 wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
3715 : wxStdInputHandler(handler)
3716 {
3717 m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
3718 }
3719
3720 wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
3721 {
3722 if ( m_menuHandler )
3723 {
3724 m_menuHandler->Detach();
3725 delete m_menuHandler;
3726 }
3727 }
3728
3729 bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
3730 const wxMouseEvent& event)
3731 {
3732 if ( event.LeftDClick() || event.LeftDown() || event.RightDown() )
3733 {
3734 wxTopLevelWindow *tlw =
3735 wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
3736
3737 long hit = tlw->HitTest(event.GetPosition());
3738
3739 if ( event.LeftDClick() && hit == wxHT_TOPLEVEL_TITLEBAR )
3740 {
3741 tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
3742 tlw->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
3743 : wxTOPLEVEL_BUTTON_MAXIMIZE);
3744 return true;
3745 }
3746 else if ( tlw->GetWindowStyle() & wxSYSTEM_MENU )
3747 {
3748 if ( (event.LeftDown() && hit == wxHT_TOPLEVEL_ICON) ||
3749 (event.RightDown() &&
3750 (hit == wxHT_TOPLEVEL_TITLEBAR ||
3751 hit == wxHT_TOPLEVEL_ICON)) )
3752 {
3753 #if wxUSE_MENUS
3754 PopupSystemMenu(tlw);
3755 #endif // wxUSE_MENUS
3756 return true;
3757 }
3758 }
3759 }
3760
3761 return wxStdInputHandler::HandleMouse(consumer, event);
3762 }
3763
3764 #if wxUSE_MENUS
3765
3766 void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window) const
3767 {
3768 wxMenu menu;
3769
3770 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
3771 menu.Append(wxID_RESTORE_FRAME , _("&Restore"));
3772 menu.Append(wxID_MOVE_FRAME , _("&Move"));
3773 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
3774 menu.Append(wxID_RESIZE_FRAME , _("&Size"));
3775 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME) )
3776 menu.Append(wxID_ICONIZE_FRAME , _("Mi&nimize"));
3777 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
3778 menu.Append(wxID_MAXIMIZE_FRAME , _("Ma&ximize"));
3779 menu.AppendSeparator();
3780 menu.Append(wxID_CLOSE_FRAME, _("Close\tAlt-F4"));
3781
3782 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
3783 {
3784 if ( window->IsMaximized() )
3785 {
3786 menu.Enable(wxID_MAXIMIZE_FRAME, false);
3787 menu.Enable(wxID_MOVE_FRAME, false);
3788 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
3789 menu.Enable(wxID_RESIZE_FRAME, false);
3790 }
3791 else
3792 menu.Enable(wxID_RESTORE_FRAME, false);
3793 }
3794
3795 window->PopupMenu(&menu, wxPoint(0, 0));
3796 }
3797
3798 #endif // wxUSE_MENUS
3799
3800 bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
3801 bool activated)
3802 {
3803 if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
3804 {
3805 // always detach if active frame changed:
3806 m_menuHandler->Detach();
3807
3808 if ( activated )
3809 {
3810 m_menuHandler->Attach(consumer);
3811 }
3812 }
3813
3814 return wxStdInputHandler::HandleActivation(consumer, activated);
3815 }
3816
3817 #endif // wxUSE_THEME_WIN32