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