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