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