Fixed width of scrollbars in wxUniv.
[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 /*
3146 Don't adjust the size for a scrollbar as its DoGetBestClientSize
3147 already has the correct size set. Any size changes here would get
3148 added to the best size, making the scrollbar larger.
3149 Also skip border width adjustments, they don't make sense for us.
3150 */
3151 return;
3152 }
3153 #endif // wxUSE_SCROLLBAR
3154
3155 #if wxUSE_BMPBUTTON
3156 if ( wxDynamicCast(window, wxBitmapButton) )
3157 {
3158 // do nothing
3159 } else
3160 #endif // wxUSE_BMPBUTTON
3161 #if wxUSE_BUTTON || wxUSE_TOGGLEBTN
3162 if ( 0
3163 # if wxUSE_BUTTON
3164 || wxDynamicCast(window, wxButton)
3165 # endif // wxUSE_BUTTON
3166 # if wxUSE_TOGGLEBTN
3167 || wxDynamicCast(window, wxToggleButton)
3168 # endif // wxUSE_TOGGLEBTN
3169 )
3170 {
3171 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3172 {
3173 // TODO: don't harcode all this
3174 size->x += 3*window->GetCharWidth();
3175
3176 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
3177 if ( size->y < heightBtn - 8 )
3178 size->y = heightBtn;
3179 else
3180 size->y += 9;
3181 }
3182
3183 // for compatibility with other ports, the buttons default size is never
3184 // less than the standard one, but not when display not PDAs.
3185 if (wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA)
3186 {
3187 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3188 {
3189 wxSize szDef = wxButton::GetDefaultSize();
3190 if ( size->x < szDef.x )
3191 size->x = szDef.x;
3192 }
3193 }
3194
3195 // no border width adjustments for buttons
3196 return;
3197 }
3198 #endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
3199
3200 wxStdRenderer::AdjustSize(size, window);
3201 }
3202
3203 wxBitmap wxWin32Renderer::GetFrameButtonBitmap(FrameButtonType type)
3204 {
3205 wxBitmap& bmp = m_bmpFrameButtons[type];
3206 if ( !bmp.IsOk() )
3207 {
3208 bmp = wxBitmap(ms_xpmFrameButtons[type]);
3209 }
3210
3211 return bmp;
3212 }
3213
3214 // ============================================================================
3215 // wxInputHandler
3216 // ============================================================================
3217
3218 // ----------------------------------------------------------------------------
3219 // wxWin32InputHandler
3220 // ----------------------------------------------------------------------------
3221
3222 bool wxWin32InputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
3223 const wxKeyEvent& WXUNUSED(event),
3224 bool WXUNUSED(pressed))
3225 {
3226 return false;
3227 }
3228
3229 bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control,
3230 const wxMouseEvent& event)
3231 {
3232 // clicking on the control gives it focus
3233 if ( event.ButtonDown() )
3234 {
3235 wxWindow * const win = control->GetInputWindow();
3236
3237 if ( win->CanAcceptFocus() && wxWindow::FindFocus() != win )
3238 {
3239 win->SetFocus();
3240
3241 return true;
3242 }
3243 }
3244
3245 return false;
3246 }
3247
3248 #if wxUSE_SCROLLBAR
3249
3250 // ----------------------------------------------------------------------------
3251 // wxWin32ScrollBarInputHandler
3252 // ----------------------------------------------------------------------------
3253
3254 wxWin32ScrollBarInputHandler::
3255 wxWin32ScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *handler)
3256 : wxStdScrollBarInputHandler(renderer, handler)
3257 {
3258 m_scrollPaused = false;
3259 m_interval = 0;
3260 }
3261
3262 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
3263 const wxControlAction& action)
3264 {
3265 // stop if went beyond the position of the original click (this can only
3266 // happen when we scroll by pages)
3267 bool stop = false;
3268 if ( action == wxACTION_SCROLL_PAGE_DOWN )
3269 {
3270 stop = scrollbar->HitTestBar(m_ptStartScrolling) != wxHT_SCROLLBAR_BAR_2;
3271 }
3272 else if ( action == wxACTION_SCROLL_PAGE_UP )
3273 {
3274 stop = scrollbar->HitTestBar(m_ptStartScrolling) != wxHT_SCROLLBAR_BAR_1;
3275 }
3276
3277 if ( stop )
3278 {
3279 StopScrolling(scrollbar);
3280
3281 scrollbar->Refresh();
3282
3283 return false;
3284 }
3285
3286 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
3287 }
3288
3289 bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
3290 const wxMouseEvent& event)
3291 {
3292 // remember the current state
3293 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
3294
3295 // do process the message
3296 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
3297
3298 // analyse the changes
3299 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
3300 {
3301 // we just started dragging the thumb, remember its initial position to
3302 // be able to restore it if the drag is cancelled later
3303 m_eventStartDrag = event;
3304 }
3305
3306 return rc;
3307 }
3308
3309 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
3310 const wxMouseEvent& event)
3311 {
3312 // we don't highlight scrollbar elements, so there is no need to process
3313 // mouse move events normally - only do it while mouse is captured (i.e.
3314 // when we're dragging the thumb or pressing on something)
3315 if ( !m_winCapture )
3316 return false;
3317
3318 if ( event.Entering() )
3319 {
3320 // we're not interested in this at all
3321 return false;
3322 }
3323
3324 wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
3325 wxHitTest ht;
3326 if ( m_scrollPaused )
3327 {
3328 // check if the mouse returned to its original location
3329
3330 if ( event.Leaving() )
3331 {
3332 // it surely didn't
3333 return false;
3334 }
3335
3336 ht = scrollbar->HitTestBar(event.GetPosition());
3337 if ( ht == m_htLast )
3338 {
3339 // yes it did, resume scrolling
3340 m_scrollPaused = false;
3341 if ( m_timerScroll )
3342 {
3343 // we were scrolling by line/page, restart timer
3344 m_timerScroll->Start(m_interval);
3345
3346 Press(scrollbar, true);
3347 }
3348 else // we were dragging the thumb
3349 {
3350 // restore its last location
3351 HandleThumbMove(scrollbar, m_eventLastDrag);
3352 }
3353
3354 return true;
3355 }
3356 }
3357 else // normal case, scrolling hasn't been paused
3358 {
3359 // if we're scrolling the scrollbar because the arrow or the shaft was
3360 // pressed, check that the mouse stays on the same scrollbar element
3361
3362 #if 0
3363 // Always let thumb jump back if we leave the scrollbar
3364 if ( event.Moving() )
3365 {
3366 ht = scrollbar->HitTestBar(event.GetPosition());
3367 }
3368 else // event.Leaving()
3369 {
3370 ht = wxHT_NOWHERE;
3371 }
3372 #else
3373 // Jump back only if we get far away from it
3374 wxPoint pos = event.GetPosition();
3375 if (scrollbar->HasFlag( wxVERTICAL ))
3376 {
3377 if (pos.x > -40 && pos.x < scrollbar->GetSize().x+40)
3378 pos.x = 5;
3379 }
3380 else
3381 {
3382 if (pos.y > -40 && pos.y < scrollbar->GetSize().y+40)
3383 pos.y = 5;
3384 }
3385 ht = scrollbar->HitTestBar(pos);
3386 #endif
3387
3388 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3389 // is still ok - we only want to catch the case when the mouse leaves
3390 // the scrollbar here
3391 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
3392 {
3393 ht = wxHT_SCROLLBAR_THUMB;
3394 }
3395
3396 if ( ht != m_htLast )
3397 {
3398 // what were we doing? 2 possibilities: either an arrow/shaft was
3399 // pressed in which case we have a timer and so we just stop it or
3400 // we were dragging the thumb
3401 if ( m_timerScroll )
3402 {
3403 // pause scrolling
3404 m_interval = m_timerScroll->GetInterval();
3405 m_timerScroll->Stop();
3406 m_scrollPaused = true;
3407
3408 // unpress the arrow
3409 Press(scrollbar, false);
3410 }
3411 else // we were dragging the thumb
3412 {
3413 // remember the current thumb position to be able to restore it
3414 // if the mouse returns to it later
3415 m_eventLastDrag = event;
3416
3417 // and restore the original position (before dragging) of the
3418 // thumb for now
3419 HandleThumbMove(scrollbar, m_eventStartDrag);
3420 }
3421
3422 return true;
3423 }
3424 }
3425
3426 return wxStdInputHandler::HandleMouseMove(control, event);
3427 }
3428
3429 #endif // wxUSE_SCROLLBAR
3430
3431 #if wxUSE_CHECKBOX
3432
3433 // ----------------------------------------------------------------------------
3434 // wxWin32CheckboxInputHandler
3435 // ----------------------------------------------------------------------------
3436
3437 bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control,
3438 const wxKeyEvent& event,
3439 bool pressed)
3440 {
3441 if ( pressed )
3442 {
3443 wxControlAction action;
3444 int keycode = event.GetKeyCode();
3445 switch ( keycode )
3446 {
3447 case WXK_SPACE:
3448 action = wxACTION_CHECKBOX_TOGGLE;
3449 break;
3450
3451 case WXK_SUBTRACT:
3452 case WXK_NUMPAD_SUBTRACT:
3453 action = wxACTION_CHECKBOX_CHECK;
3454 break;
3455
3456 case WXK_ADD:
3457 case WXK_NUMPAD_ADD:
3458 case WXK_NUMPAD_EQUAL:
3459 action = wxACTION_CHECKBOX_CLEAR;
3460 break;
3461 }
3462
3463 if ( !action.IsEmpty() )
3464 {
3465 control->PerformAction(action);
3466
3467 return true;
3468 }
3469 }
3470
3471 return false;
3472 }
3473
3474 #endif // wxUSE_CHECKBOX
3475
3476 #if wxUSE_TEXTCTRL
3477
3478 // ----------------------------------------------------------------------------
3479 // wxWin32TextCtrlInputHandler
3480 // ----------------------------------------------------------------------------
3481
3482 bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control,
3483 const wxKeyEvent& event,
3484 bool pressed)
3485 {
3486 // handle only MSW-specific text bindings here, the others are handled in
3487 // the base class
3488 if ( pressed )
3489 {
3490 int keycode = event.GetKeyCode();
3491
3492 wxControlAction action;
3493 if ( keycode == WXK_DELETE && event.ShiftDown() )
3494 {
3495 action = wxACTION_TEXT_CUT;
3496 }
3497 else if ( keycode == WXK_INSERT )
3498 {
3499 if ( event.ControlDown() )
3500 action = wxACTION_TEXT_COPY;
3501 else if ( event.ShiftDown() )
3502 action = wxACTION_TEXT_PASTE;
3503 }
3504
3505 if ( action != wxACTION_NONE )
3506 {
3507 control->PerformAction(action);
3508
3509 return true;
3510 }
3511 }
3512
3513 return wxStdInputHandler::HandleKey(control, event, pressed);
3514 }
3515
3516 #endif // wxUSE_TEXTCTRL
3517
3518 #if wxUSE_STATUSBAR
3519
3520 // ----------------------------------------------------------------------------
3521 // wxWin32StatusBarInputHandler
3522 // ----------------------------------------------------------------------------
3523
3524 wxWin32StatusBarInputHandler::
3525 wxWin32StatusBarInputHandler(wxInputHandler *handler)
3526 : wxStdInputHandler(handler)
3527 {
3528 m_isOnGrip = false;
3529 }
3530
3531 bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar,
3532 const wxPoint& pt) const
3533 {
3534 if ( statbar->HasFlag(wxST_SIZEGRIP) &&
3535 statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
3536 {
3537 wxTopLevelWindow *
3538 parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow);
3539
3540 wxCHECK_MSG( parentTLW, false,
3541 wxT("the status bar should be a child of a TLW") );
3542
3543 // a maximized window can't be resized anyhow
3544 if ( !parentTLW->IsMaximized() )
3545 {
3546 // VZ: I think that the standard Windows behaviour is to only
3547 // show the resizing cursor when the mouse is on top of the
3548 // grip itself but apparently different Windows versions behave
3549 // differently (?) and it seems a better UI to allow resizing
3550 // the status bar even when the mouse is above the grip
3551 wxSize sizeSbar = statbar->GetSize();
3552
3553 int diff = sizeSbar.x - pt.x;
3554 return diff >= 0 && diff < (wxCoord)STATUSBAR_GRIP_SIZE;
3555 }
3556 }
3557
3558 return false;
3559 }
3560
3561 bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
3562 const wxMouseEvent& event)
3563 {
3564 if ( event.Button(1) )
3565 {
3566 if ( event.ButtonDown(1) )
3567 {
3568 wxWindow *statbar = consumer->GetInputWindow();
3569
3570 if ( IsOnGrip(statbar, event.GetPosition()) )
3571 {
3572 wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
3573 wxTopLevelWindow);
3574 if ( tlw )
3575 {
3576 tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
3577 wxHT_TOPLEVEL_BORDER_SE);
3578
3579 statbar->SetCursor(m_cursorOld);
3580
3581 return true;
3582 }
3583 }
3584 }
3585 }
3586
3587 return wxStdInputHandler::HandleMouse(consumer, event);
3588 }
3589
3590 bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
3591 const wxMouseEvent& event)
3592 {
3593 wxWindow *statbar = consumer->GetInputWindow();
3594
3595 bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
3596 if ( isOnGrip != m_isOnGrip )
3597 {
3598 m_isOnGrip = isOnGrip;
3599 if ( isOnGrip )
3600 {
3601 m_cursorOld = statbar->GetCursor();
3602 statbar->SetCursor(wxCURSOR_SIZENWSE);
3603 }
3604 else
3605 {
3606 statbar->SetCursor(m_cursorOld);
3607 }
3608 }
3609
3610 return wxStdInputHandler::HandleMouseMove(consumer, event);
3611 }
3612
3613 #endif // wxUSE_STATUSBAR
3614
3615 // ----------------------------------------------------------------------------
3616 // wxWin32FrameInputHandler
3617 // ----------------------------------------------------------------------------
3618
3619 class wxWin32SystemMenuEvtHandler : public wxEvtHandler
3620 {
3621 public:
3622 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
3623
3624 void Attach(wxInputConsumer *consumer);
3625 void Detach();
3626
3627 private:
3628 DECLARE_EVENT_TABLE()
3629 void OnSystemMenu(wxCommandEvent &event);
3630 void OnCloseFrame(wxCommandEvent &event);
3631 void OnClose(wxCloseEvent &event);
3632
3633 wxWin32FrameInputHandler *m_inputHnd;
3634 wxTopLevelWindow *m_wnd;
3635 #if wxUSE_ACCEL
3636 wxAcceleratorTable m_oldAccelTable;
3637 #endif
3638 };
3639
3640 wxWin32SystemMenuEvtHandler::
3641 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler)
3642 {
3643 m_inputHnd = handler;
3644 m_wnd = NULL;
3645 }
3646
3647 void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
3648 {
3649 wxASSERT_MSG( m_wnd == NULL, wxT("can't attach the handler twice!") );
3650
3651 m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
3652 m_wnd->PushEventHandler(this);
3653
3654 #if wxUSE_ACCEL
3655 // VS: This code relies on using generic implementation of
3656 // wxAcceleratorTable in wxUniv!
3657 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
3658 m_oldAccelTable = table;
3659 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
3660 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
3661 m_wnd->SetAcceleratorTable(table);
3662 #endif
3663 }
3664
3665 void wxWin32SystemMenuEvtHandler::Detach()
3666 {
3667 if ( m_wnd )
3668 {
3669 #if wxUSE_ACCEL
3670 m_wnd->SetAcceleratorTable(m_oldAccelTable);
3671 #endif
3672 m_wnd->RemoveEventHandler(this);
3673 m_wnd = NULL;
3674 }
3675 }
3676
3677 BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
3678 EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
3679 EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
3680 EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
3681 END_EVENT_TABLE()
3682
3683 void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
3684 {
3685 #if wxUSE_ACCEL
3686 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
3687 m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
3688 #endif
3689
3690 #if wxUSE_MENUS
3691 m_inputHnd->PopupSystemMenu(m_wnd);
3692 #endif // wxUSE_MENUS
3693
3694 #if wxUSE_ACCEL
3695 m_wnd->SetAcceleratorTable(table);
3696 #endif
3697 }
3698
3699 void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
3700 {
3701 m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
3702 wxTOPLEVEL_BUTTON_CLOSE);
3703 }
3704
3705 void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
3706 {
3707 m_wnd = NULL;
3708 event.Skip();
3709 }
3710
3711
3712 wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
3713 : wxStdInputHandler(handler)
3714 {
3715 m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
3716 }
3717
3718 wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
3719 {
3720 if ( m_menuHandler )
3721 {
3722 m_menuHandler->Detach();
3723 delete m_menuHandler;
3724 }
3725 }
3726
3727 bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
3728 const wxMouseEvent& event)
3729 {
3730 if ( event.LeftDClick() || event.LeftDown() || event.RightDown() )
3731 {
3732 wxTopLevelWindow *tlw =
3733 wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
3734
3735 long hit = tlw->HitTest(event.GetPosition());
3736
3737 if ( event.LeftDClick() && hit == wxHT_TOPLEVEL_TITLEBAR )
3738 {
3739 tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
3740 tlw->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
3741 : wxTOPLEVEL_BUTTON_MAXIMIZE);
3742 return true;
3743 }
3744 else if ( tlw->GetWindowStyle() & wxSYSTEM_MENU )
3745 {
3746 if ( (event.LeftDown() && hit == wxHT_TOPLEVEL_ICON) ||
3747 (event.RightDown() &&
3748 (hit == wxHT_TOPLEVEL_TITLEBAR ||
3749 hit == wxHT_TOPLEVEL_ICON)) )
3750 {
3751 #if wxUSE_MENUS
3752 PopupSystemMenu(tlw);
3753 #endif // wxUSE_MENUS
3754 return true;
3755 }
3756 }
3757 }
3758
3759 return wxStdInputHandler::HandleMouse(consumer, event);
3760 }
3761
3762 #if wxUSE_MENUS
3763
3764 void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window) const
3765 {
3766 wxMenu menu;
3767
3768 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
3769 menu.Append(wxID_RESTORE_FRAME , _("&Restore"));
3770 menu.Append(wxID_MOVE_FRAME , _("&Move"));
3771 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
3772 menu.Append(wxID_RESIZE_FRAME , _("&Size"));
3773 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME) )
3774 menu.Append(wxID_ICONIZE_FRAME , _("Mi&nimize"));
3775 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
3776 menu.Append(wxID_MAXIMIZE_FRAME , _("Ma&ximize"));
3777 menu.AppendSeparator();
3778 menu.Append(wxID_CLOSE_FRAME, _("Close\tAlt-F4"));
3779
3780 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
3781 {
3782 if ( window->IsMaximized() )
3783 {
3784 menu.Enable(wxID_MAXIMIZE_FRAME, false);
3785 menu.Enable(wxID_MOVE_FRAME, false);
3786 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
3787 menu.Enable(wxID_RESIZE_FRAME, false);
3788 }
3789 else
3790 menu.Enable(wxID_RESTORE_FRAME, false);
3791 }
3792
3793 window->PopupMenu(&menu, wxPoint(0, 0));
3794 }
3795
3796 #endif // wxUSE_MENUS
3797
3798 bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
3799 bool activated)
3800 {
3801 if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
3802 {
3803 // always detach if active frame changed:
3804 m_menuHandler->Detach();
3805
3806 if ( activated )
3807 {
3808 m_menuHandler->Attach(consumer);
3809 }
3810 }
3811
3812 return wxStdInputHandler::HandleActivation(consumer, activated);
3813 }
3814
3815 #endif // wxUSE_THEME_WIN32