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