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