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