]> git.saurik.com Git - wxWidgets.git/blob - src/univ/themes/win32.cpp
Added comment explaining that it's not necessary to use LEX and YACC on
[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_CAPTIONTEXT));
1300 #else // !__WXMSW__
1301 // use the standard Windows colours elsewhere
1302 case WINDOW: return *wxWHITE;
1303
1304 case CONTROL_PRESSED:
1305 case CONTROL_CURRENT:
1306 case CONTROL: return wxColour(0xc0c0c0);
1307
1308 case CONTROL_TEXT: return *wxBLACK;
1309
1310 case SCROLLBAR: return wxColour(0xe0e0e0);
1311 case SCROLLBAR_PRESSED: return *wxBLACK;
1312
1313 case HIGHLIGHT: return wxColour(0x800000);
1314 case HIGHLIGHT_TEXT: return wxColour(0xffffff);
1315
1316 case SHADOW_DARK: return *wxBLACK;
1317
1318 case CONTROL_TEXT_DISABLED:return wxColour(0xe0e0e0);
1319 case SHADOW_HIGHLIGHT: return wxColour(0xffffff);
1320
1321 case SHADOW_IN: return wxColour(0xc0c0c0);
1322
1323 case CONTROL_TEXT_DISABLED_SHADOW:
1324 case SHADOW_OUT: return wxColour(0x7f7f7f);
1325
1326 case TITLEBAR: return wxColour(0xaeaaae);
1327 case TITLEBAR_ACTIVE: return wxColour(0x820300);
1328 case TITLEBAR_TEXT: return *wxWHITE;
1329 #endif // __WXMSW__
1330
1331 case MAX:
1332 default:
1333 wxFAIL_MSG(_T("invalid standard colour"));
1334 return *wxBLACK;
1335 }
1336 }
1337
1338 // ============================================================================
1339 // wxWin32Renderer
1340 // ============================================================================
1341
1342 // ----------------------------------------------------------------------------
1343 // construction
1344 // ----------------------------------------------------------------------------
1345
1346 wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme)
1347 {
1348 // init data
1349 m_scheme = scheme;
1350 m_sizeScrollbarArrow = wxSize(16, 16);
1351
1352 // init colours and pens
1353 m_penBlack = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_DARK), 0, wxSOLID);
1354
1355 m_colDarkGrey = wxSCHEME_COLOUR(scheme, SHADOW_OUT);
1356 m_penDarkGrey = wxPen(m_colDarkGrey, 0, wxSOLID);
1357
1358 m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN), 0, wxSOLID);
1359
1360 m_colHighlight = wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT);
1361 m_penHighlight = wxPen(m_colHighlight, 0, wxSOLID);
1362
1363 m_titlebarFont = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
1364 m_titlebarFont.SetWeight(wxFONTWEIGHT_BOLD);
1365
1366 // init the arrow bitmaps
1367 static const size_t ARROW_WIDTH = 7;
1368 static const size_t ARROW_LENGTH = 4;
1369
1370 wxMask *mask;
1371 wxMemoryDC dcNormal,
1372 dcDisabled,
1373 dcInverse;
1374 for ( size_t n = 0; n < Arrow_Max; n++ )
1375 {
1376 bool isVertical = n > Arrow_Right;
1377 int w, h;
1378 if ( isVertical )
1379 {
1380 w = ARROW_WIDTH;
1381 h = ARROW_LENGTH;
1382 }
1383 else
1384 {
1385 h = ARROW_WIDTH;
1386 w = ARROW_LENGTH;
1387 }
1388
1389 // disabled arrow is larger because of the shadow
1390 m_bmpArrows[Arrow_Normal][n].Create(w, h);
1391 m_bmpArrows[Arrow_Disabled][n].Create(w + 1, h + 1);
1392
1393 dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]);
1394 dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]);
1395
1396 dcNormal.SetBackground(*wxWHITE_BRUSH);
1397 dcDisabled.SetBackground(*wxWHITE_BRUSH);
1398 dcNormal.Clear();
1399 dcDisabled.Clear();
1400
1401 dcNormal.SetPen(m_penBlack);
1402 dcDisabled.SetPen(m_penDarkGrey);
1403
1404 // calculate the position of the point of the arrow
1405 wxCoord x1, y1;
1406 if ( isVertical )
1407 {
1408 x1 = (ARROW_WIDTH - 1)/2;
1409 y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1;
1410 }
1411 else // horizontal
1412 {
1413 x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1;
1414 y1 = (ARROW_WIDTH - 1)/2;
1415 }
1416
1417 wxCoord x2 = x1,
1418 y2 = y1;
1419
1420 if ( isVertical )
1421 x2++;
1422 else
1423 y2++;
1424
1425 for ( size_t i = 0; i < ARROW_LENGTH; i++ )
1426 {
1427 dcNormal.DrawLine(x1, y1, x2, y2);
1428 dcDisabled.DrawLine(x1, y1, x2, y2);
1429
1430 if ( isVertical )
1431 {
1432 x1--;
1433 x2++;
1434
1435 if ( n == Arrow_Up )
1436 {
1437 y1++;
1438 y2++;
1439 }
1440 else // down arrow
1441 {
1442 y1--;
1443 y2--;
1444 }
1445 }
1446 else // left or right arrow
1447 {
1448 y1--;
1449 y2++;
1450
1451 if ( n == Arrow_Left )
1452 {
1453 x1++;
1454 x2++;
1455 }
1456 else
1457 {
1458 x1--;
1459 x2--;
1460 }
1461 }
1462 }
1463
1464 // draw the shadow for the disabled one
1465 dcDisabled.SetPen(m_penHighlight);
1466 switch ( n )
1467 {
1468 case Arrow_Left:
1469 y1 += 2;
1470 dcDisabled.DrawLine(x1, y1, x2, y2);
1471 break;
1472
1473 case Arrow_Right:
1474 x1 = ARROW_LENGTH - 1;
1475 y1 = (ARROW_WIDTH - 1)/2 + 1;
1476 x2 = 0;
1477 y2 = ARROW_WIDTH;
1478 dcDisabled.DrawLine(x1, y1, x2, y2);
1479 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1480 break;
1481
1482 case Arrow_Up:
1483 x1 += 2;
1484 dcDisabled.DrawLine(x1, y1, x2, y2);
1485 break;
1486
1487 case Arrow_Down:
1488 x1 = ARROW_WIDTH - 1;
1489 y1 = 1;
1490 x2 = (ARROW_WIDTH - 1)/2;
1491 y2 = ARROW_LENGTH;
1492 dcDisabled.DrawLine(x1, y1, x2, y2);
1493 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1494 break;
1495
1496 }
1497
1498 // create the inversed bitmap but only for the right arrow as we only
1499 // use it for the menus
1500 if ( n == Arrow_Right )
1501 {
1502 m_bmpArrows[Arrow_Inversed][n].Create(w, h);
1503 dcInverse.SelectObject(m_bmpArrows[Arrow_Inversed][n]);
1504 dcInverse.Clear();
1505 dcInverse.Blit(0, 0, w, h,
1506 &dcNormal, 0, 0,
1507 wxXOR);
1508 dcInverse.SelectObject(wxNullBitmap);
1509
1510 mask = new wxMask(m_bmpArrows[Arrow_Inversed][n], *wxBLACK);
1511 m_bmpArrows[Arrow_Inversed][n].SetMask(mask);
1512
1513 m_bmpArrows[Arrow_InversedDisabled][n].Create(w, h);
1514 dcInverse.SelectObject(m_bmpArrows[Arrow_InversedDisabled][n]);
1515 dcInverse.Clear();
1516 dcInverse.Blit(0, 0, w, h,
1517 &dcDisabled, 0, 0,
1518 wxXOR);
1519 dcInverse.SelectObject(wxNullBitmap);
1520
1521 mask = new wxMask(m_bmpArrows[Arrow_InversedDisabled][n], *wxBLACK);
1522 m_bmpArrows[Arrow_InversedDisabled][n].SetMask(mask);
1523 }
1524
1525 dcNormal.SelectObject(wxNullBitmap);
1526 dcDisabled.SelectObject(wxNullBitmap);
1527
1528 mask = new wxMask(m_bmpArrows[Arrow_Normal][n], *wxWHITE);
1529 m_bmpArrows[Arrow_Normal][n].SetMask(mask);
1530 mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
1531 m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
1532
1533 m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
1534 }
1535
1536 // init the frame buttons bitmaps
1537 m_bmpFrameButtons[FrameButton_Close] = wxBitmap(frame_button_close_xpm);
1538 m_bmpFrameButtons[FrameButton_Minimize] = wxBitmap(frame_button_minimize_xpm);
1539 m_bmpFrameButtons[FrameButton_Maximize] = wxBitmap(frame_button_maximize_xpm);
1540 m_bmpFrameButtons[FrameButton_Restore] = wxBitmap(frame_button_restore_xpm);
1541 m_bmpFrameButtons[FrameButton_Help] = wxBitmap(frame_button_help_xpm);
1542 }
1543
1544 // ----------------------------------------------------------------------------
1545 // border stuff
1546 // ----------------------------------------------------------------------------
1547
1548 /*
1549 The raised border in Win32 looks like this:
1550
1551 IIIIIIIIIIIIIIIIIIIIIIB
1552 I GB
1553 I GB I = white (HILIGHT)
1554 I GB H = light grey (LIGHT)
1555 I GB G = dark grey (SHADOI)
1556 I GB B = black (DKSHADOI)
1557 I GB I = hIghlight (COLOR_3DHILIGHT)
1558 I GB
1559 IGGGGGGGGGGGGGGGGGGGGGB
1560 BBBBBBBBBBBBBBBBBBBBBBB
1561
1562 The sunken border looks like this:
1563
1564 GGGGGGGGGGGGGGGGGGGGGGI
1565 GBBBBBBBBBBBBBBBBBBBBHI
1566 GB HI
1567 GB HI
1568 GB HI
1569 GB HI
1570 GB HI
1571 GB HI
1572 GHHHHHHHHHHHHHHHHHHHHHI
1573 IIIIIIIIIIIIIIIIIIIIIII
1574
1575 The static border (used for the controls which don't get focus) is like
1576 this:
1577
1578 GGGGGGGGGGGGGGGGGGGGGGW
1579 G W
1580 G W
1581 G W
1582 G W
1583 G W
1584 G W
1585 G W
1586 WWWWWWWWWWWWWWWWWWWWWWW
1587
1588 The most complicated is the double border:
1589
1590 HHHHHHHHHHHHHHHHHHHHHHB
1591 HWWWWWWWWWWWWWWWWWWWWGB
1592 HWHHHHHHHHHHHHHHHHHHHGB
1593 HWH HGB
1594 HWH HGB
1595 HWH HGB
1596 HWH HGB
1597 HWHHHHHHHHHHHHHHHHHHHGB
1598 HGGGGGGGGGGGGGGGGGGGGGB
1599 BBBBBBBBBBBBBBBBBBBBBBB
1600
1601 And the simple border is, well, simple:
1602
1603 BBBBBBBBBBBBBBBBBBBBBBB
1604 B B
1605 B B
1606 B B
1607 B B
1608 B B
1609 B B
1610 B B
1611 B B
1612 BBBBBBBBBBBBBBBBBBBBBBB
1613 */
1614
1615 void wxWin32Renderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1616 {
1617 // draw
1618 dc.SetPen(pen);
1619 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1620 dc.DrawRectangle(*rect);
1621
1622 // adjust the rect
1623 rect->Inflate(-1);
1624 }
1625
1626 void wxWin32Renderer::DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1627 {
1628 // draw the bottom and right sides
1629 dc.SetPen(pen);
1630 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1631 rect->GetRight() + 1, rect->GetBottom());
1632 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1633 rect->GetRight(), rect->GetBottom());
1634
1635 // adjust the rect
1636 rect->width--;
1637 rect->height--;
1638 }
1639
1640 void wxWin32Renderer::DrawShadedRect(wxDC& dc, wxRect *rect,
1641 const wxPen& pen1, const wxPen& pen2)
1642 {
1643 // draw the rectangle
1644 dc.SetPen(pen1);
1645 dc.DrawLine(rect->GetLeft(), rect->GetTop(),
1646 rect->GetLeft(), rect->GetBottom());
1647 dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
1648 rect->GetRight(), rect->GetTop());
1649 dc.SetPen(pen2);
1650 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1651 rect->GetRight(), rect->GetBottom());
1652 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1653 rect->GetRight() + 1, rect->GetBottom());
1654
1655 // adjust the rect
1656 rect->Inflate(-1);
1657 }
1658
1659 void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxRect *rect)
1660 {
1661 DrawShadedRect(dc, rect, m_penHighlight, m_penBlack);
1662 DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
1663 }
1664
1665 void wxWin32Renderer::DrawSunkenBorder(wxDC& dc, wxRect *rect)
1666 {
1667 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
1668 DrawShadedRect(dc, rect, m_penBlack, m_penLightGrey);
1669 }
1670
1671 void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
1672 {
1673 if ( isPressed )
1674 {
1675 DrawRect(dc, rect, m_penDarkGrey);
1676
1677 // the arrow is usually drawn inside border of width 2 and is offset by
1678 // another pixel in both directions when it's pressed - as the border
1679 // in this case is more narrow as well, we have to adjust rect like
1680 // this:
1681 rect->Inflate(-1);
1682 rect->x++;
1683 rect->y++;
1684 }
1685 else
1686 {
1687 DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
1688 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
1689 }
1690 }
1691
1692 void wxWin32Renderer::DrawBorder(wxDC& dc,
1693 wxBorder border,
1694 const wxRect& rectTotal,
1695 int WXUNUSED(flags),
1696 wxRect *rectIn)
1697 {
1698 int i;
1699
1700 wxRect rect = rectTotal;
1701
1702 switch ( border )
1703 {
1704 case wxBORDER_SUNKEN:
1705 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1706 {
1707 DrawSunkenBorder(dc, &rect);
1708 }
1709 break;
1710
1711 case wxBORDER_STATIC:
1712 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1713 break;
1714
1715 case wxBORDER_RAISED:
1716 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1717 {
1718 DrawRaisedBorder(dc, &rect);
1719 }
1720 break;
1721
1722 case wxBORDER_DOUBLE:
1723 DrawArrowBorder(dc, &rect);
1724 DrawRect(dc, &rect, m_penLightGrey);
1725 break;
1726
1727 case wxBORDER_SIMPLE:
1728 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1729 {
1730 DrawRect(dc, &rect, m_penBlack);
1731 }
1732 break;
1733
1734 default:
1735 wxFAIL_MSG(_T("unknown border type"));
1736 // fall through
1737
1738 case wxBORDER_DEFAULT:
1739 case wxBORDER_NONE:
1740 break;
1741 }
1742
1743 if ( rectIn )
1744 *rectIn = rect;
1745 }
1746
1747 wxRect wxWin32Renderer::GetBorderDimensions(wxBorder border) const
1748 {
1749 wxCoord width;
1750 switch ( border )
1751 {
1752 case wxBORDER_RAISED:
1753 case wxBORDER_SUNKEN:
1754 width = BORDER_THICKNESS;
1755 break;
1756
1757 case wxBORDER_SIMPLE:
1758 case wxBORDER_STATIC:
1759 width = 1;
1760 break;
1761
1762 case wxBORDER_DOUBLE:
1763 width = 3;
1764 break;
1765
1766 default:
1767 wxFAIL_MSG(_T("unknown border type"));
1768 // fall through
1769
1770 case wxBORDER_DEFAULT:
1771 case wxBORDER_NONE:
1772 width = 0;
1773 break;
1774 }
1775
1776 wxRect rect;
1777 rect.x =
1778 rect.y =
1779 rect.width =
1780 rect.height = width;
1781
1782 return rect;
1783 }
1784
1785 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1786 {
1787 return TRUE;
1788 }
1789
1790 // ----------------------------------------------------------------------------
1791 // borders
1792 // ----------------------------------------------------------------------------
1793
1794 void wxWin32Renderer::DrawTextBorder(wxDC& dc,
1795 wxBorder border,
1796 const wxRect& rect,
1797 int flags,
1798 wxRect *rectIn)
1799 {
1800 // text controls are not special under windows
1801 DrawBorder(dc, border, rect, flags, rectIn);
1802 }
1803
1804 void wxWin32Renderer::DrawButtonBorder(wxDC& dc,
1805 const wxRect& rectTotal,
1806 int flags,
1807 wxRect *rectIn)
1808 {
1809 wxRect rect = rectTotal;
1810
1811 if ( flags & wxCONTROL_PRESSED )
1812 {
1813 // button pressed: draw a double border around it
1814 DrawRect(dc, &rect, m_penBlack);
1815 DrawRect(dc, &rect, m_penDarkGrey);
1816 }
1817 else
1818 {
1819 // button not pressed
1820
1821 if ( flags & (wxCONTROL_FOCUSED | wxCONTROL_ISDEFAULT) )
1822 {
1823 // button either default or focused (or both): add an extra border around it
1824 DrawRect(dc, &rect, m_penBlack);
1825 }
1826
1827 // now draw a normal button
1828 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
1829 DrawHalfRect(dc, &rect, m_penDarkGrey);
1830 }
1831
1832 if ( rectIn )
1833 {
1834 *rectIn = rect;
1835 }
1836 }
1837
1838 // ----------------------------------------------------------------------------
1839 // lines and frame
1840 // ----------------------------------------------------------------------------
1841
1842 void wxWin32Renderer::DrawHorizontalLine(wxDC& dc,
1843 wxCoord y, wxCoord x1, wxCoord x2)
1844 {
1845 dc.SetPen(m_penDarkGrey);
1846 dc.DrawLine(x1, y, x2 + 1, y);
1847 dc.SetPen(m_penHighlight);
1848 y++;
1849 dc.DrawLine(x1, y, x2 + 1, y);
1850 }
1851
1852 void wxWin32Renderer::DrawVerticalLine(wxDC& dc,
1853 wxCoord x, wxCoord y1, wxCoord y2)
1854 {
1855 dc.SetPen(m_penDarkGrey);
1856 dc.DrawLine(x, y1, x, y2 + 1);
1857 dc.SetPen(m_penHighlight);
1858 x++;
1859 dc.DrawLine(x, y1, x, y2 + 1);
1860 }
1861
1862 void wxWin32Renderer::DrawFrame(wxDC& dc,
1863 const wxString& label,
1864 const wxRect& rect,
1865 int flags,
1866 int alignment,
1867 int indexAccel)
1868 {
1869 wxCoord height = 0; // of the label
1870 wxRect rectFrame = rect;
1871 if ( !label.empty() )
1872 {
1873 // the text should touch the top border of the rect, so the frame
1874 // itself should be lower
1875 dc.GetTextExtent(label, NULL, &height);
1876 rectFrame.y += height / 2;
1877 rectFrame.height -= height / 2;
1878
1879 // we have to draw each part of the frame individually as we can't
1880 // erase the background beyond the label as it might contain some
1881 // pixmap already, so drawing everything and then overwriting part of
1882 // the frame with label doesn't work
1883
1884 // TODO: the +5 and space insertion should be customizable
1885
1886 wxRect rectText;
1887 rectText.x = rectFrame.x + 5;
1888 rectText.y = rect.y;
1889 rectText.width = rectFrame.width - 7; // +2 border width
1890 rectText.height = height;
1891
1892 wxString label2;
1893 label2 << _T(' ') << label << _T(' ');
1894 if ( indexAccel != -1 )
1895 {
1896 // adjust it as we prepended a space
1897 indexAccel++;
1898 }
1899
1900 wxRect rectLabel;
1901 DrawLabel(dc, label2, rectText, flags, alignment, indexAccel, &rectLabel);
1902
1903 StandardDrawFrame(dc, rectFrame, rectLabel);
1904 }
1905 else
1906 {
1907 // just draw the complete frame
1908 DrawShadedRect(dc, &rectFrame, m_penDarkGrey, m_penHighlight);
1909 DrawShadedRect(dc, &rectFrame, m_penHighlight, m_penDarkGrey);
1910 }
1911 }
1912
1913 // ----------------------------------------------------------------------------
1914 // label
1915 // ----------------------------------------------------------------------------
1916
1917 void wxWin32Renderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
1918 {
1919 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1920 // pixels each while we really need dots here... PS_ALTERNATE might
1921 // work, but it is for NT 5 only
1922 #if 0
1923 DrawRect(dc, &rect, wxPen(*wxBLACK, 0, wxDOT));
1924 #else
1925 // draw the pixels manually: note that to behave in the same manner as
1926 // DrawRect(), we must exclude the bottom and right borders from the
1927 // rectangle
1928 wxCoord x1 = rect.GetLeft(),
1929 y1 = rect.GetTop(),
1930 x2 = rect.GetRight(),
1931 y2 = rect.GetBottom();
1932
1933 dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID));
1934
1935 // this seems to be closer than what Windows does than wxINVERT although
1936 // I'm still not sure if it's correct
1937 dc.SetLogicalFunction(wxAND_REVERSE);
1938
1939 wxCoord z;
1940 for ( z = x1 + 1; z < x2; z += 2 )
1941 dc.DrawPoint(z, rect.GetTop());
1942
1943 wxCoord shift = z == x2 ? 0 : 1;
1944 for ( z = y1 + shift; z < y2; z += 2 )
1945 dc.DrawPoint(x2, z);
1946
1947 shift = z == y2 ? 0 : 1;
1948 for ( z = x2 - shift; z > x1; z -= 2 )
1949 dc.DrawPoint(z, y2);
1950
1951 shift = z == x1 ? 0 : 1;
1952 for ( z = y2 - shift; z > y1; z -= 2 )
1953 dc.DrawPoint(x1, z);
1954
1955 dc.SetLogicalFunction(wxCOPY);
1956 #endif // 0/1
1957 }
1958
1959 void wxWin32Renderer::DrawLabelShadow(wxDC& dc,
1960 const wxString& label,
1961 const wxRect& rect,
1962 int alignment,
1963 int indexAccel)
1964 {
1965 // draw shadow of the text
1966 dc.SetTextForeground(m_colHighlight);
1967 wxRect rectShadow = rect;
1968 rectShadow.x++;
1969 rectShadow.y++;
1970 dc.DrawLabel(label, rectShadow, alignment, indexAccel);
1971
1972 // make the text grey
1973 dc.SetTextForeground(m_colDarkGrey);
1974 }
1975
1976 void wxWin32Renderer::DrawLabel(wxDC& dc,
1977 const wxString& label,
1978 const wxRect& rect,
1979 int flags,
1980 int alignment,
1981 int indexAccel,
1982 wxRect *rectBounds)
1983 {
1984 DoDrawLabel(dc, label, rect, flags, alignment, indexAccel, rectBounds);
1985 }
1986
1987 void wxWin32Renderer::DoDrawLabel(wxDC& dc,
1988 const wxString& label,
1989 const wxRect& rect,
1990 int flags,
1991 int alignment,
1992 int indexAccel,
1993 wxRect *rectBounds,
1994 const wxPoint& focusOffset)
1995 {
1996 // the underscores are not drawn for focused controls in wxMSW
1997 if ( flags & wxCONTROL_FOCUSED )
1998 {
1999 indexAccel = -1;
2000 }
2001
2002 if ( flags & wxCONTROL_DISABLED )
2003 {
2004 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2005 // currently only can happen for a menu item and it seems that Windows
2006 // doesn't draw the shadow in this case, so we don't do it neither
2007 if ( flags & wxCONTROL_SELECTED )
2008 {
2009 // just make the label text greyed out
2010 dc.SetTextForeground(m_colDarkGrey);
2011 }
2012 else // draw normal disabled label
2013 {
2014 DrawLabelShadow(dc, label, rect, alignment, indexAccel);
2015 }
2016 }
2017
2018 wxRect rectLabel;
2019 dc.DrawLabel(label, wxNullBitmap, rect, alignment, indexAccel, &rectLabel);
2020
2021 if ( flags & wxCONTROL_DISABLED )
2022 {
2023 // restore the fg colour
2024 dc.SetTextForeground(*wxBLACK);
2025 }
2026
2027 if ( flags & wxCONTROL_FOCUSED )
2028 {
2029 if ( focusOffset.x || focusOffset.y )
2030 {
2031 rectLabel.Inflate(focusOffset.x, focusOffset.y);
2032 }
2033
2034 DrawFocusRect(dc, rectLabel);
2035 }
2036
2037 if ( rectBounds )
2038 *rectBounds = rectLabel;
2039 }
2040
2041 void wxWin32Renderer::DrawButtonLabel(wxDC& dc,
2042 const wxString& label,
2043 const wxBitmap& image,
2044 const wxRect& rect,
2045 int flags,
2046 int alignment,
2047 int indexAccel,
2048 wxRect *rectBounds)
2049 {
2050 // the underscores are not drawn for focused controls in wxMSW
2051 if ( flags & wxCONTROL_PRESSED )
2052 {
2053 indexAccel = -1;
2054 }
2055
2056 wxRect rectLabel = rect;
2057 if ( !label.empty() )
2058 {
2059 // shift the label if a button is pressed
2060 if ( flags & wxCONTROL_PRESSED )
2061 {
2062 rectLabel.x++;
2063 rectLabel.y++;
2064 }
2065
2066 if ( flags & wxCONTROL_DISABLED )
2067 {
2068 DrawLabelShadow(dc, label, rectLabel, alignment, indexAccel);
2069 }
2070
2071 // leave enough space for the focus rectangle
2072 if ( flags & wxCONTROL_FOCUSED )
2073 {
2074 rectLabel.Inflate(-2);
2075 }
2076 }
2077
2078 dc.DrawLabel(label, image, rectLabel, alignment, indexAccel, rectBounds);
2079
2080 if ( !label.empty() && (flags & wxCONTROL_FOCUSED) )
2081 {
2082 if ( flags & wxCONTROL_PRESSED )
2083 {
2084 // the focus rectangle is never pressed, so undo the shift done
2085 // above
2086 rectLabel.x--;
2087 rectLabel.y--;
2088 rectLabel.width--;
2089 rectLabel.height--;
2090 }
2091
2092 DrawFocusRect(dc, rectLabel);
2093 }
2094 }
2095
2096 // ----------------------------------------------------------------------------
2097 // (check)listbox items
2098 // ----------------------------------------------------------------------------
2099
2100 void wxWin32Renderer::DrawItem(wxDC& dc,
2101 const wxString& label,
2102 const wxRect& rect,
2103 int flags)
2104 {
2105 wxDCTextColourChanger colChanger(dc);
2106
2107 if ( flags & wxCONTROL_SELECTED )
2108 {
2109 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2110
2111 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2112 dc.SetBrush(wxBrush(colBg, wxSOLID));
2113 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2114 dc.DrawRectangle(rect);
2115 }
2116
2117 wxRect rectText = rect;
2118 rectText.x += 2;
2119 rectText.width -= 2;
2120 dc.DrawLabel(label, wxNullBitmap, rectText);
2121
2122 if ( flags & wxCONTROL_FOCUSED )
2123 {
2124 DrawFocusRect(dc, rect);
2125 }
2126 }
2127
2128 void wxWin32Renderer::DrawCheckItem(wxDC& dc,
2129 const wxString& label,
2130 const wxBitmap& bitmap,
2131 const wxRect& rect,
2132 int flags)
2133 {
2134 wxBitmap bmp;
2135 if ( bitmap.Ok() )
2136 {
2137 bmp = bitmap;
2138 }
2139 else // use default bitmap
2140 {
2141 bmp = wxBitmap(flags & wxCONTROL_CHECKED ? checked_item_xpm
2142 : unchecked_item_xpm);
2143 }
2144
2145 dc.DrawBitmap(bmp, rect.x, rect.y + (rect.height - bmp.GetHeight()) / 2 - 1,
2146 TRUE /* use mask */);
2147
2148 wxRect rectLabel = rect;
2149 int bmpWidth = bmp.GetWidth();
2150 rectLabel.x += bmpWidth;
2151 rectLabel.width -= bmpWidth;
2152
2153 DrawItem(dc, label, rectLabel, flags);
2154 }
2155
2156 // ----------------------------------------------------------------------------
2157 // check/radio buttons
2158 // ----------------------------------------------------------------------------
2159
2160 wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags)
2161 {
2162 IndicatorState indState;
2163 if ( flags & wxCONTROL_SELECTED )
2164 indState = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
2165 : IndicatorState_Selected;
2166 else if ( flags & wxCONTROL_DISABLED )
2167 indState = IndicatorState_Disabled;
2168 else if ( flags & wxCONTROL_PRESSED )
2169 indState = IndicatorState_Pressed;
2170 else
2171 indState = IndicatorState_Normal;
2172
2173 IndicatorStatus indStatus = flags & wxCONTROL_CHECKED
2174 ? IndicatorStatus_Checked
2175 : IndicatorStatus_Unchecked;
2176
2177 const char **xpm = bmpIndicators[indType][indState][indStatus];
2178 return xpm ? wxBitmap(xpm) : wxNullBitmap;
2179 }
2180
2181 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc,
2182 const wxString& label,
2183 const wxBitmap& bitmap,
2184 const wxRect& rect,
2185 int flags,
2186 wxAlignment align,
2187 int indexAccel,
2188 wxCoord focusOffsetY)
2189 {
2190 // calculate the position of the bitmap and of the label
2191 wxCoord heightBmp = bitmap.GetHeight();
2192 wxCoord xBmp,
2193 yBmp = rect.y + (rect.height - heightBmp) / 2;
2194
2195 wxRect rectLabel;
2196 dc.GetMultiLineTextExtent(label, NULL, &rectLabel.height);
2197 rectLabel.y = rect.y + (rect.height - rectLabel.height) / 2;
2198
2199 // align label vertically with the bitmap - looks nicer like this
2200 rectLabel.y -= (rectLabel.height - heightBmp) % 2;
2201
2202 // calc horz position
2203 if ( align == wxALIGN_RIGHT )
2204 {
2205 xBmp = rect.GetRight() - bitmap.GetWidth();
2206 rectLabel.x = rect.x + 3;
2207 rectLabel.SetRight(xBmp);
2208 }
2209 else // normal (checkbox to the left of the text) case
2210 {
2211 xBmp = rect.x;
2212 rectLabel.x = xBmp + bitmap.GetWidth() + 5;
2213 rectLabel.SetRight(rect.GetRight());
2214 }
2215
2216 dc.DrawBitmap(bitmap, xBmp, yBmp, TRUE /* use mask */);
2217
2218 DoDrawLabel(
2219 dc, label, rectLabel,
2220 flags,
2221 wxALIGN_LEFT | wxALIGN_TOP,
2222 indexAccel,
2223 NULL, // we don't need bounding rect
2224 // use custom vert focus rect offset
2225 wxPoint(FOCUS_RECT_OFFSET_X, focusOffsetY)
2226 );
2227 }
2228
2229 void wxWin32Renderer::DrawRadioButton(wxDC& dc,
2230 const wxString& label,
2231 const wxBitmap& bitmap,
2232 const wxRect& rect,
2233 int flags,
2234 wxAlignment align,
2235 int indexAccel)
2236 {
2237 DrawCheckOrRadioButton(dc, label,
2238 bitmap.Ok() ? bitmap : GetRadioBitmap(flags),
2239 rect, flags, align, indexAccel,
2240 FOCUS_RECT_OFFSET_Y); // default focus rect offset
2241 }
2242
2243 void wxWin32Renderer::DrawCheckButton(wxDC& dc,
2244 const wxString& label,
2245 const wxBitmap& bitmap,
2246 const wxRect& rect,
2247 int flags,
2248 wxAlignment align,
2249 int indexAccel)
2250 {
2251 DrawCheckOrRadioButton(dc, label,
2252 bitmap.Ok() ? bitmap : GetCheckBitmap(flags),
2253 rect, flags, align, indexAccel,
2254 0); // no focus rect offset for checkboxes
2255 }
2256
2257 // ----------------------------------------------------------------------------
2258 // text control
2259 // ----------------------------------------------------------------------------
2260
2261 void wxWin32Renderer::DrawTextLine(wxDC& dc,
2262 const wxString& text,
2263 const wxRect& rect,
2264 int selStart,
2265 int selEnd,
2266 int flags)
2267 {
2268 // nothing special to do here
2269 StandardDrawTextLine(dc, text, rect, selStart, selEnd, flags);
2270 }
2271
2272 void wxWin32Renderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
2273 {
2274 // we don't draw them
2275 }
2276
2277 // ----------------------------------------------------------------------------
2278 // notebook
2279 // ----------------------------------------------------------------------------
2280
2281 void wxWin32Renderer::DrawTab(wxDC& dc,
2282 const wxRect& rectOrig,
2283 wxDirection dir,
2284 const wxString& label,
2285 const wxBitmap& bitmap,
2286 int flags,
2287 int indexAccel)
2288 {
2289 wxRect rect = rectOrig;
2290
2291 // the current tab is drawn indented (to the top for default case) and
2292 // bigger than the other ones
2293 const wxSize indent = GetTabIndent();
2294 if ( flags & wxCONTROL_SELECTED )
2295 {
2296 switch ( dir )
2297 {
2298 default:
2299 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2300 // fall through
2301
2302 case wxTOP:
2303 rect.Inflate(indent.x, 0);
2304 rect.y -= indent.y;
2305 rect.height += indent.y;
2306 break;
2307
2308 case wxBOTTOM:
2309 rect.Inflate(indent.x, 0);
2310 rect.height += indent.y;
2311 break;
2312
2313 case wxLEFT:
2314 case wxRIGHT:
2315 wxFAIL_MSG(_T("TODO"));
2316 break;
2317 }
2318 }
2319
2320 // draw the text, image and the focus around them (if necessary)
2321 wxRect rectLabel = rect;
2322 rectLabel.Deflate(1, 1);
2323 DrawButtonLabel(dc, label, bitmap, rectLabel,
2324 flags, wxALIGN_CENTRE, indexAccel);
2325
2326 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2327 static const wxCoord CUTOFF = 2; // radius of the rounded corner
2328 wxCoord x = rect.x,
2329 y = rect.y,
2330 x2 = rect.GetRight(),
2331 y2 = rect.GetBottom();
2332
2333 // FIXME: all this code will break if the tab indent or the border width,
2334 // it is tied to the fact that both of them are equal to 2
2335 switch ( dir )
2336 {
2337 default:
2338 case wxTOP:
2339 dc.SetPen(m_penHighlight);
2340 dc.DrawLine(x, y2, x, y + CUTOFF);
2341 dc.DrawLine(x, y + CUTOFF, x + CUTOFF, y);
2342 dc.DrawLine(x + CUTOFF, y, x2 - CUTOFF + 1, y);
2343
2344 dc.SetPen(m_penBlack);
2345 dc.DrawLine(x2, y2, x2, y + CUTOFF);
2346 dc.DrawLine(x2, y + CUTOFF, x2 - CUTOFF, y);
2347
2348 dc.SetPen(m_penDarkGrey);
2349 dc.DrawLine(x2 - 1, y2, x2 - 1, y + CUTOFF - 1);
2350
2351 if ( flags & wxCONTROL_SELECTED )
2352 {
2353 dc.SetPen(m_penLightGrey);
2354
2355 // overwrite the part of the border below this tab
2356 dc.DrawLine(x + 1, y2 + 1, x2 - 1, y2 + 1);
2357
2358 // and the shadow of the tab to the left of us
2359 dc.DrawLine(x + 1, y + CUTOFF + 1, x + 1, y2 + 1);
2360 }
2361 break;
2362
2363 case wxBOTTOM:
2364 dc.SetPen(m_penHighlight);
2365 // we need to continue one pixel further to overwrite the corner of
2366 // the border for the selected tab
2367 dc.DrawLine(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0),
2368 x, y2 - CUTOFF);
2369 dc.DrawLine(x, y2 - CUTOFF, x + CUTOFF, y2);
2370
2371 dc.SetPen(m_penBlack);
2372 dc.DrawLine(x + CUTOFF, y2, x2 - CUTOFF + 1, y2);
2373 dc.DrawLine(x2, y, x2, y2 - CUTOFF);
2374 dc.DrawLine(x2, y2 - CUTOFF, x2 - CUTOFF, y2);
2375
2376 dc.SetPen(m_penDarkGrey);
2377 dc.DrawLine(x + CUTOFF, y2 - 1, x2 - CUTOFF + 1, y2 - 1);
2378 dc.DrawLine(x2 - 1, y, x2 - 1, y2 - CUTOFF + 1);
2379
2380 if ( flags & wxCONTROL_SELECTED )
2381 {
2382 dc.SetPen(m_penLightGrey);
2383
2384 // overwrite the part of the (double!) border above this tab
2385 dc.DrawLine(x + 1, y - 1, x2 - 1, y - 1);
2386 dc.DrawLine(x + 1, y - 2, x2 - 1, y - 2);
2387
2388 // and the shadow of the tab to the left of us
2389 dc.DrawLine(x + 1, y2 - CUTOFF, x + 1, y - 1);
2390 }
2391 break;
2392
2393 case wxLEFT:
2394 case wxRIGHT:
2395 wxFAIL_MSG(_T("TODO"));
2396 }
2397 }
2398
2399 // ----------------------------------------------------------------------------
2400 // slider
2401 // ----------------------------------------------------------------------------
2402
2403 wxSize wxWin32Renderer::GetSliderThumbSize(const wxRect& rect,
2404 wxOrientation orient) const
2405 {
2406 wxSize size;
2407
2408 wxRect rectShaft = GetSliderShaftRect(rect, orient);
2409 if ( orient == wxHORIZONTAL )
2410 {
2411 size.y = rect.height - 6;
2412 size.x = wxMin(size.y / 2, rectShaft.width);
2413 }
2414 else // vertical
2415 {
2416 size.x = rect.width - 6;
2417 size.y = wxMin(size.x / 2, rectShaft.height);
2418 }
2419
2420 return size;
2421 }
2422
2423 wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
2424 wxOrientation orient) const
2425 {
2426 static const wxCoord SLIDER_MARGIN = 6;
2427
2428 wxRect rect = rectOrig;
2429
2430 if ( orient == wxHORIZONTAL )
2431 {
2432 // make the rect of minimal width and centre it
2433 rect.height = 2*BORDER_THICKNESS;
2434 rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
2435 if ( rect.y < 0 )
2436 rect.y = 0;
2437
2438 // leave margins on the sides
2439 rect.Deflate(SLIDER_MARGIN, 0);
2440 }
2441 else // vertical
2442 {
2443 // same as above but in other direction
2444 rect.width = 2*BORDER_THICKNESS;
2445 rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
2446 if ( rect.x < 0 )
2447 rect.x = 0;
2448
2449 rect.Deflate(0, SLIDER_MARGIN);
2450 }
2451
2452 return rect;
2453 }
2454
2455 void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
2456 const wxRect& rectOrig,
2457 wxOrientation orient,
2458 int flags,
2459 wxRect *rectShaft)
2460 {
2461 if ( flags & wxCONTROL_FOCUSED )
2462 {
2463 DrawFocusRect(dc, rectOrig);
2464 }
2465
2466 wxRect rect = GetSliderShaftRect(rectOrig, orient);
2467
2468 if ( rectShaft )
2469 *rectShaft = rect;
2470
2471 DrawSunkenBorder(dc, &rect);
2472 }
2473
2474 void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
2475 const wxRect& rect,
2476 wxOrientation orient,
2477 int flags)
2478 {
2479 /*
2480 we are drawing a shape of this form
2481
2482 HHHHHHB <--- y
2483 H DB
2484 H DB
2485 H DB where H is hightlight colour
2486 H DB D dark grey
2487 H DB B black
2488 H DB
2489 H DB <--- y3
2490 H DB
2491 HDB
2492 B <--- y2
2493
2494 ^ ^ ^
2495 | | |
2496 x x3 x2
2497
2498 The interior of this shape is filled with the hatched brush if the thumb
2499 is pressed.
2500 */
2501
2502 DrawBackground(dc, wxNullColour, rect, flags);
2503
2504 bool transpose = orient == wxVERTICAL;
2505
2506 wxCoord x, y, x2, y2;
2507 if ( transpose )
2508 {
2509 x = rect.y;
2510 y = rect.x;
2511 x2 = rect.GetBottom();
2512 y2 = rect.GetRight();
2513 }
2514 else
2515 {
2516 x = rect.x;
2517 y = rect.y;
2518 x2 = rect.GetRight();
2519 y2 = rect.GetBottom();
2520 }
2521
2522 // the size of the pointed part of the thumb
2523 wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
2524
2525 wxCoord x3 = x + sizeArrow,
2526 y3 = y2 - sizeArrow;
2527
2528 dc.SetPen(m_penHighlight);
2529 DrawLine(dc, x, y, x2, y, transpose);
2530 DrawLine(dc, x, y + 1, x, y2 - sizeArrow, transpose);
2531 DrawLine(dc, x, y3, x3, y2, transpose);
2532
2533 dc.SetPen(m_penBlack);
2534 DrawLine(dc, x3, y2, x2, y3, transpose);
2535 DrawLine(dc, x2, y3, x2, y - 1, transpose);
2536
2537 dc.SetPen(m_penDarkGrey);
2538 DrawLine(dc, x3, y2 - 1, x2 - 1, y3, transpose);
2539 DrawLine(dc, x2 - 1, y3, x2 - 1, y, transpose);
2540
2541 if ( flags & wxCONTROL_PRESSED )
2542 {
2543 // TODO: MSW fills the entire area inside, not just the rect
2544 wxRect rectInt = rect;
2545 if ( transpose )
2546 rectInt.SetRight(y3);
2547 else
2548 rectInt.SetBottom(y3);
2549 rectInt.Deflate(2);
2550
2551 #if !defined(__WXMGL__)
2552 static const char *stipple_xpm[] = {
2553 /* columns rows colors chars-per-pixel */
2554 "2 2 2 1",
2555 " c None",
2556 "w c white",
2557 /* pixels */
2558 "w ",
2559 " w",
2560 };
2561 #else
2562 // VS: MGL can only do 8x8 stipple brushes
2563 static const char *stipple_xpm[] = {
2564 /* columns rows colors chars-per-pixel */
2565 "8 8 2 1",
2566 " c None",
2567 "w c white",
2568 /* pixels */
2569 "w w w w ",
2570 " w w w w",
2571 "w w w w ",
2572 " w w w w",
2573 "w w w w ",
2574 " w w w w",
2575 "w w w w ",
2576 " w w w w",
2577 };
2578 #endif
2579 dc.SetBrush(wxBrush(stipple_xpm));
2580
2581 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
2582 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
2583 dc.SetPen(*wxTRANSPARENT_PEN);
2584 dc.DrawRectangle(rectInt);
2585 }
2586 }
2587
2588 void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
2589 const wxRect& rect,
2590 const wxSize& sizeThumb,
2591 wxOrientation orient,
2592 int start,
2593 int end,
2594 int step,
2595 int flags)
2596 {
2597 if ( end == start )
2598 {
2599 // empty slider?
2600 return;
2601 }
2602
2603 // the variable names correspond to horizontal case, but they can be used
2604 // for both orientations
2605 wxCoord x1, x2, y1, y2, len, widthThumb;
2606 if ( orient == wxHORIZONTAL )
2607 {
2608 x1 = rect.GetLeft();
2609 x2 = rect.GetRight();
2610
2611 // draw from bottom to top to leave one pixel space between the ticks
2612 // and the slider as Windows do
2613 y1 = rect.GetBottom();
2614 y2 = rect.GetTop();
2615
2616 len = rect.width;
2617
2618 widthThumb = sizeThumb.x;
2619 }
2620 else // vertical
2621 {
2622 x1 = rect.GetTop();
2623 x2 = rect.GetBottom();
2624
2625 y1 = rect.GetRight();
2626 y2 = rect.GetLeft();
2627
2628 len = rect.height;
2629
2630 widthThumb = sizeThumb.y;
2631 }
2632
2633 // the first tick should be positioned in such way that a thumb drawn in
2634 // the first position points down directly to it
2635 x1 += widthThumb / 2;
2636 x2 -= widthThumb / 2;
2637
2638 // this also means that we have slightly less space for the ticks in
2639 // between the first and the last
2640 len -= widthThumb;
2641
2642 dc.SetPen(m_penBlack);
2643
2644 int range = end - start;
2645 for ( int n = 0; n < range; n += step )
2646 {
2647 wxCoord x = x1 + (len*n) / range;
2648
2649 DrawLine(dc, x, y1, x, y2, orient == wxVERTICAL);
2650 }
2651
2652 // always draw the line at the end position
2653 DrawLine(dc, x2, y1, x2, y2, orient == wxVERTICAL);
2654 }
2655
2656 // ----------------------------------------------------------------------------
2657 // menu and menubar
2658 // ----------------------------------------------------------------------------
2659
2660 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2661 class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo
2662 {
2663 public:
2664 virtual wxSize GetSize() const { return m_size; }
2665
2666 wxCoord GetLabelOffset() const { return m_ofsLabel; }
2667 wxCoord GetAccelOffset() const { return m_ofsAccel; }
2668
2669 wxCoord GetItemHeight() const { return m_heightItem; }
2670
2671 private:
2672 // the total size of the menu
2673 wxSize m_size;
2674
2675 // the offset of the start of the menu item label
2676 wxCoord m_ofsLabel;
2677
2678 // the offset of the start of the accel label
2679 wxCoord m_ofsAccel;
2680
2681 // the height of a normal (not separator) item
2682 wxCoord m_heightItem;
2683
2684 friend wxMenuGeometryInfo *
2685 wxWin32Renderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
2686 };
2687
2688 // FIXME: all constants are hardcoded but shouldn't be
2689 static const wxCoord MENU_LEFT_MARGIN = 9;
2690 static const wxCoord MENU_RIGHT_MARGIN = 18;
2691 static const wxCoord MENU_VERT_MARGIN = 3;
2692
2693 // the margin around bitmap/check marks (on each side)
2694 static const wxCoord MENU_BMP_MARGIN = 2;
2695
2696 // the margin between the labels and accel strings
2697 static const wxCoord MENU_ACCEL_MARGIN = 8;
2698
2699 // the separator height in pixels: in fact, strangely enough, the real height
2700 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2701 // account here
2702 static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
2703
2704 // the size of the standard checkmark bitmap
2705 static const wxCoord MENU_CHECK_SIZE = 9;
2706
2707 void wxWin32Renderer::DrawMenuBarItem(wxDC& dc,
2708 const wxRect& rectOrig,
2709 const wxString& label,
2710 int flags,
2711 int indexAccel)
2712 {
2713 wxRect rect = rectOrig;
2714 rect.height--;
2715
2716 wxDCTextColourChanger colChanger(dc);
2717
2718 if ( flags & wxCONTROL_SELECTED )
2719 {
2720 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2721
2722 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2723 dc.SetBrush(wxBrush(colBg, wxSOLID));
2724 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2725 dc.DrawRectangle(rect);
2726 }
2727
2728 // don't draw the focus rect around menu bar items
2729 DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
2730 wxALIGN_CENTRE, indexAccel);
2731 }
2732
2733 void wxWin32Renderer::DrawMenuItem(wxDC& dc,
2734 wxCoord y,
2735 const wxMenuGeometryInfo& gi,
2736 const wxString& label,
2737 const wxString& accel,
2738 const wxBitmap& bitmap,
2739 int flags,
2740 int indexAccel)
2741 {
2742 const wxWin32MenuGeometryInfo& geometryInfo =
2743 (const wxWin32MenuGeometryInfo&)gi;
2744
2745 wxRect rect;
2746 rect.x = 0;
2747 rect.y = y;
2748 rect.width = geometryInfo.GetSize().x;
2749 rect.height = geometryInfo.GetItemHeight();
2750
2751 // draw the selected item specially
2752 wxDCTextColourChanger colChanger(dc);
2753 if ( flags & wxCONTROL_SELECTED )
2754 {
2755 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2756
2757 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2758 dc.SetBrush(wxBrush(colBg, wxSOLID));
2759 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2760 dc.DrawRectangle(rect);
2761 }
2762
2763 // draw the bitmap: use the bitmap provided or the standard checkmark for
2764 // the checkable items
2765 wxBitmap bmp = bitmap;
2766 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKED) )
2767 {
2768 bmp = GetIndicator(IndicatorType_Menu, flags);
2769 }
2770
2771 if ( bmp.Ok() )
2772 {
2773 rect.SetRight(geometryInfo.GetLabelOffset());
2774 wxControlRenderer::DrawBitmap(dc, bmp, rect);
2775 }
2776
2777 // draw the label
2778 rect.x = geometryInfo.GetLabelOffset();
2779 rect.SetRight(geometryInfo.GetAccelOffset());
2780
2781 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
2782
2783 // draw the accel string
2784 rect.x = geometryInfo.GetAccelOffset();
2785 rect.SetRight(geometryInfo.GetSize().x);
2786
2787 // NB: no accel index here
2788 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
2789
2790 // draw the submenu indicator
2791 if ( flags & wxCONTROL_ISSUBMENU )
2792 {
2793 rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
2794 rect.width = MENU_RIGHT_MARGIN;
2795
2796 wxArrowStyle arrowStyle;
2797 if ( flags & wxCONTROL_DISABLED )
2798 arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InversedDisabled
2799 : Arrow_Disabled;
2800 else if ( flags & wxCONTROL_SELECTED )
2801 arrowStyle = Arrow_Inversed;
2802 else
2803 arrowStyle = Arrow_Normal;
2804
2805 DrawArrow(dc, rect, Arrow_Right, arrowStyle);
2806 }
2807 }
2808
2809 void wxWin32Renderer::DrawMenuSeparator(wxDC& dc,
2810 wxCoord y,
2811 const wxMenuGeometryInfo& geomInfo)
2812 {
2813 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
2814 }
2815
2816 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& sizeText) const
2817 {
2818 wxSize size = sizeText;
2819
2820 // FIXME: menubar height is configurable under Windows
2821 size.x += 12;
2822 size.y += 6;
2823
2824 return size;
2825 }
2826
2827 wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win,
2828 const wxMenu& menu) const
2829 {
2830 // prepare the dc: for now we draw all the items with the system font
2831 wxClientDC dc(win);
2832 dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
2833
2834 // the height of a normal item
2835 wxCoord heightText = dc.GetCharHeight();
2836
2837 // the total height
2838 wxCoord height = 0;
2839
2840 // the max length of label and accel strings: the menu width is the sum of
2841 // them, even if they're for different items (as the accels should be
2842 // aligned)
2843 //
2844 // the max length of the bitmap is never 0 as Windows always leaves enough
2845 // space for a check mark indicator
2846 wxCoord widthLabelMax = 0,
2847 widthAccelMax = 0,
2848 widthBmpMax = MENU_LEFT_MARGIN;
2849
2850 for ( wxMenuItemList::Node *node = menu.GetMenuItems().GetFirst();
2851 node;
2852 node = node->GetNext() )
2853 {
2854 // height of this item
2855 wxCoord h;
2856
2857 wxMenuItem *item = node->GetData();
2858 if ( item->IsSeparator() )
2859 {
2860 h = MENU_SEPARATOR_HEIGHT;
2861 }
2862 else // not separator
2863 {
2864 h = heightText;
2865
2866 wxCoord widthLabel;
2867 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
2868 if ( widthLabel > widthLabelMax )
2869 {
2870 widthLabelMax = widthLabel;
2871 }
2872
2873 wxCoord widthAccel;
2874 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
2875 if ( widthAccel > widthAccelMax )
2876 {
2877 widthAccelMax = widthAccel;
2878 }
2879
2880 const wxBitmap& bmp = item->GetBitmap();
2881 if ( bmp.Ok() )
2882 {
2883 wxCoord widthBmp = bmp.GetWidth();
2884 if ( widthBmp > widthBmpMax )
2885 widthBmpMax = widthBmp;
2886 }
2887 //else if ( item->IsCheckable() ): no need to check for this as
2888 // MENU_LEFT_MARGIN is big enough to show the check mark
2889 }
2890
2891 h += 2*MENU_VERT_MARGIN;
2892
2893 // remember the item position and height
2894 item->SetGeometry(height, h);
2895
2896 height += h;
2897 }
2898
2899 // bundle the metrics into a struct and return it
2900 wxWin32MenuGeometryInfo *gi = new wxWin32MenuGeometryInfo;
2901
2902 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
2903 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
2904 if ( widthAccelMax > 0 )
2905 {
2906 // if we actually have any accesl, add a margin
2907 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
2908 }
2909
2910 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
2911
2912 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
2913 gi->m_size.y = height;
2914
2915 return gi;
2916 }
2917
2918 // ----------------------------------------------------------------------------
2919 // status bar
2920 // ----------------------------------------------------------------------------
2921
2922 static const wxCoord STATBAR_BORDER_X = 2;
2923 static const wxCoord STATBAR_BORDER_Y = 2;
2924
2925 wxSize wxWin32Renderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const
2926 {
2927 if ( borderBetweenFields )
2928 *borderBetweenFields = 2;
2929
2930 return wxSize(STATBAR_BORDER_X, STATBAR_BORDER_Y);
2931 }
2932
2933 void wxWin32Renderer::DrawStatusField(wxDC& dc,
2934 const wxRect& rect,
2935 const wxString& label,
2936 int flags)
2937 {
2938 wxRect rectIn;
2939
2940 if ( flags & wxCONTROL_ISDEFAULT )
2941 {
2942 // draw the size grip: it is a normal rect except that in the lower
2943 // right corner we have several bands which may be used for dragging
2944 // the status bar corner
2945 //
2946 // each band consists of 4 stripes: m_penHighlight, double
2947 // m_penDarkGrey and transparent one
2948 wxCoord x2 = rect.GetRight(),
2949 y2 = rect.GetBottom();
2950
2951 // draw the upper left part of the rect normally
2952 dc.SetPen(m_penDarkGrey);
2953 dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2);
2954 dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop());
2955
2956 // draw the grey stripes of the grip
2957 size_t n;
2958 wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1;
2959 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
2960 {
2961 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
2962 dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1);
2963 }
2964
2965 // draw the white stripes
2966 dc.SetPen(m_penHighlight);
2967 ofs = WIDTH_STATUSBAR_GRIP_BAND + 1;
2968 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
2969 {
2970 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
2971 }
2972
2973 // draw the remaining rect boundaries
2974 ofs -= WIDTH_STATUSBAR_GRIP_BAND;
2975 dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1);
2976 dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2);
2977
2978 rectIn = rect;
2979 rectIn.Deflate(1);
2980
2981 rectIn.width -= STATUSBAR_GRIP_SIZE;
2982 }
2983 else // normal pane
2984 {
2985 DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
2986 }
2987
2988 rectIn.Deflate(STATBAR_BORDER_X, STATBAR_BORDER_Y);
2989
2990 wxDCClipper clipper(dc, rectIn);
2991 DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
2992 }
2993
2994 // ----------------------------------------------------------------------------
2995 // combobox
2996 // ----------------------------------------------------------------------------
2997
2998 void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal,
2999 wxBitmap *bmpFocus,
3000 wxBitmap *bmpPressed,
3001 wxBitmap *bmpDisabled)
3002 {
3003 static const wxCoord widthCombo = 16;
3004 static const wxCoord heightCombo = 17;
3005
3006 wxMemoryDC dcMem;
3007
3008 if ( bmpNormal )
3009 {
3010 bmpNormal->Create(widthCombo, heightCombo);
3011 dcMem.SelectObject(*bmpNormal);
3012 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3013 Arrow_Down, Arrow_Normal);
3014 }
3015
3016 if ( bmpPressed )
3017 {
3018 bmpPressed->Create(widthCombo, heightCombo);
3019 dcMem.SelectObject(*bmpPressed);
3020 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3021 Arrow_Down, Arrow_Pressed);
3022 }
3023
3024 if ( bmpDisabled )
3025 {
3026 bmpDisabled->Create(widthCombo, heightCombo);
3027 dcMem.SelectObject(*bmpDisabled);
3028 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3029 Arrow_Down, Arrow_Disabled);
3030 }
3031 }
3032
3033 // ----------------------------------------------------------------------------
3034 // background
3035 // ----------------------------------------------------------------------------
3036
3037 void wxWin32Renderer::DoDrawBackground(wxDC& dc,
3038 const wxColour& col,
3039 const wxRect& rect)
3040 {
3041 wxBrush brush(col, wxSOLID);
3042 dc.SetBrush(brush);
3043 dc.SetPen(*wxTRANSPARENT_PEN);
3044 dc.DrawRectangle(rect);
3045 }
3046
3047 void wxWin32Renderer::DrawBackground(wxDC& dc,
3048 const wxColour& col,
3049 const wxRect& rect,
3050 int flags)
3051 {
3052 // just fill it with the given or default bg colour
3053 wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL);
3054 DoDrawBackground(dc, colBg, rect);
3055 }
3056
3057 // ----------------------------------------------------------------------------
3058 // scrollbar
3059 // ----------------------------------------------------------------------------
3060
3061 void wxWin32Renderer::DrawArrow(wxDC& dc,
3062 wxDirection dir,
3063 const wxRect& rect,
3064 int flags)
3065 {
3066 // get the bitmap for this arrow
3067 wxArrowDirection arrowDir;
3068 switch ( dir )
3069 {
3070 case wxLEFT: arrowDir = Arrow_Left; break;
3071 case wxRIGHT: arrowDir = Arrow_Right; break;
3072 case wxUP: arrowDir = Arrow_Up; break;
3073 case wxDOWN: arrowDir = Arrow_Down; break;
3074
3075 default:
3076 wxFAIL_MSG(_T("unknown arrow direction"));
3077 return;
3078 }
3079
3080 wxArrowStyle arrowStyle;
3081 if ( flags & wxCONTROL_PRESSED )
3082 {
3083 // can't be pressed and disabled
3084 arrowStyle = Arrow_Pressed;
3085 }
3086 else
3087 {
3088 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
3089 }
3090
3091 DrawArrowButton(dc, rect, arrowDir, arrowStyle);
3092 }
3093
3094 void wxWin32Renderer::DrawArrow(wxDC& dc,
3095 const wxRect& rect,
3096 wxArrowDirection arrowDir,
3097 wxArrowStyle arrowStyle)
3098 {
3099 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
3100
3101 // under Windows the arrows always have the same size so just centre it in
3102 // the provided rectangle
3103 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
3104 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
3105
3106 // Windows does it like this...
3107 if ( arrowDir == Arrow_Left )
3108 x--;
3109
3110 // draw it
3111 dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
3112 }
3113
3114 void wxWin32Renderer::DrawArrowButton(wxDC& dc,
3115 const wxRect& rectAll,
3116 wxArrowDirection arrowDir,
3117 wxArrowStyle arrowStyle)
3118 {
3119 wxRect rect = rectAll;
3120 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3121 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
3122 DrawArrow(dc, rect, arrowDir, arrowStyle);
3123 }
3124
3125 void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
3126 wxOrientation orient,
3127 const wxRect& rect,
3128 int flags)
3129 {
3130 // we don't use the flags, the thumb never changes appearance
3131 wxRect rectThumb = rect;
3132 DrawArrowBorder(dc, &rectThumb);
3133 DrawBackground(dc, wxNullColour, rectThumb);
3134 }
3135
3136 void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
3137 wxOrientation orient,
3138 const wxRect& rectBar,
3139 int flags)
3140 {
3141 wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
3142 ? wxColourScheme::SCROLLBAR_PRESSED
3143 : wxColourScheme::SCROLLBAR;
3144 DoDrawBackground(dc, m_scheme->Get(col), rectBar);
3145 }
3146
3147 void wxWin32Renderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
3148 {
3149 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3150 }
3151
3152 wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar,
3153 wxScrollBar::Element elem,
3154 int thumbPos) const
3155 {
3156 return StandardGetScrollbarRect(scrollbar, elem,
3157 thumbPos, m_sizeScrollbarArrow);
3158 }
3159
3160 wxCoord wxWin32Renderer::GetScrollbarSize(const wxScrollBar *scrollbar)
3161 {
3162 return StandardScrollBarSize(scrollbar, m_sizeScrollbarArrow);
3163 }
3164
3165 wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
3166 const wxPoint& pt) const
3167 {
3168 return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow);
3169 }
3170
3171 wxCoord wxWin32Renderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
3172 int thumbPos)
3173 {
3174 return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow);
3175 }
3176
3177 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar,
3178 wxCoord coord)
3179 {
3180 return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow);
3181 }
3182
3183 // ----------------------------------------------------------------------------
3184 // top level windows
3185 // ----------------------------------------------------------------------------
3186
3187 int wxWin32Renderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
3188 {
3189 wxRect client = GetFrameClientArea(rect, flags);
3190
3191 if ( client.Inside(pt) )
3192 return wxHT_TOPLEVEL_CLIENT_AREA;
3193
3194 if ( flags & wxTOPLEVEL_TITLEBAR )
3195 {
3196 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3197
3198 if ( flags & wxTOPLEVEL_ICON )
3199 {
3200 if ( wxRect(client.GetPosition(), GetFrameIconSize()).Inside(pt) )
3201 return wxHT_TOPLEVEL_ICON;
3202 }
3203
3204 wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
3205 client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
3206 FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
3207
3208 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3209 {
3210 if ( btnRect.Inside(pt) )
3211 return wxHT_TOPLEVEL_BUTTON_CLOSE;
3212 btnRect.x -= FRAME_BUTTON_WIDTH + 2;
3213 }
3214 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3215 {
3216 if ( btnRect.Inside(pt) )
3217 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
3218 btnRect.x -= FRAME_BUTTON_WIDTH;
3219 }
3220 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3221 {
3222 if ( btnRect.Inside(pt) )
3223 return wxHT_TOPLEVEL_BUTTON_RESTORE;
3224 btnRect.x -= FRAME_BUTTON_WIDTH;
3225 }
3226 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3227 {
3228 if ( btnRect.Inside(pt) )
3229 return wxHT_TOPLEVEL_BUTTON_ICONIZE;
3230 btnRect.x -= FRAME_BUTTON_WIDTH;
3231 }
3232 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3233 {
3234 if ( btnRect.Inside(pt) )
3235 return wxHT_TOPLEVEL_BUTTON_HELP;
3236 btnRect.x -= FRAME_BUTTON_WIDTH;
3237 }
3238
3239 if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
3240 return wxHT_TOPLEVEL_TITLEBAR;
3241 }
3242
3243 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3244 {
3245 // we are certainly at one of borders, lets decide which one:
3246
3247 int border = 0;
3248 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3249 if ( pt.x < client.x )
3250 border |= wxHT_TOPLEVEL_BORDER_W;
3251 else if ( pt.x >= client.width + client.x )
3252 border |= wxHT_TOPLEVEL_BORDER_E;
3253 if ( pt.y < client.y )
3254 border |= wxHT_TOPLEVEL_BORDER_N;
3255 else if ( pt.y >= client.height + client.y )
3256 border |= wxHT_TOPLEVEL_BORDER_S;
3257 return border;
3258 }
3259
3260 return wxHT_NOWHERE;
3261 }
3262
3263 void wxWin32Renderer::DrawFrameTitleBar(wxDC& dc,
3264 const wxRect& rect,
3265 const wxString& title,
3266 const wxIcon& icon,
3267 int flags,
3268 int specialButton,
3269 int specialButtonFlags)
3270 {
3271 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3272 {
3273 DrawFrameBorder(dc, rect, flags);
3274 }
3275 if ( flags & wxTOPLEVEL_TITLEBAR )
3276 {
3277 DrawFrameBackground(dc, rect, flags);
3278 if ( flags & wxTOPLEVEL_ICON )
3279 DrawFrameIcon(dc, rect, icon, flags);
3280 DrawFrameTitle(dc, rect, title, flags);
3281
3282 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3283 wxCoord x,y;
3284 x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
3285 y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
3286
3287 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3288 {
3289 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
3290 (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
3291 specialButtonFlags : 0);
3292 x -= FRAME_BUTTON_WIDTH + 2;
3293 }
3294 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3295 {
3296 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
3297 (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
3298 specialButtonFlags : 0);
3299 x -= FRAME_BUTTON_WIDTH;
3300 }
3301 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3302 {
3303 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
3304 (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
3305 specialButtonFlags : 0);
3306 x -= FRAME_BUTTON_WIDTH;
3307 }
3308 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3309 {
3310 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
3311 (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
3312 specialButtonFlags : 0);
3313 x -= FRAME_BUTTON_WIDTH;
3314 }
3315 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3316 {
3317 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
3318 (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
3319 specialButtonFlags : 0);
3320 x -= FRAME_BUTTON_WIDTH;
3321 }
3322 }
3323 }
3324
3325 void wxWin32Renderer::DrawFrameBorder(wxDC& dc,
3326 const wxRect& rect,
3327 int flags)
3328 {
3329 if ( !(flags & wxTOPLEVEL_BORDER) ) return;
3330
3331 wxRect r(rect);
3332
3333 DrawShadedRect(dc, &r, m_penLightGrey, m_penBlack);
3334 DrawShadedRect(dc, &r, m_penHighlight, m_penDarkGrey);
3335 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3336 if ( flags & wxTOPLEVEL_RESIZEABLE )
3337 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3338 }
3339
3340 void wxWin32Renderer::DrawFrameBackground(wxDC& dc,
3341 const wxRect& rect,
3342 int flags)
3343 {
3344 if ( !(flags & wxTOPLEVEL_TITLEBAR) ) return;
3345
3346 wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
3347 wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE) :
3348 wxSCHEME_COLOUR(m_scheme, TITLEBAR);
3349
3350 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3351 r.height = FRAME_TITLEBAR_HEIGHT;
3352
3353 DrawBackground(dc, col, r);
3354 }
3355
3356 void wxWin32Renderer::DrawFrameTitle(wxDC& dc,
3357 const wxRect& rect,
3358 const wxString& title,
3359 int flags)
3360 {
3361 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3362 r.height = FRAME_TITLEBAR_HEIGHT;
3363 if ( flags & wxTOPLEVEL_ICON )
3364 r.x += FRAME_TITLEBAR_HEIGHT;
3365 else
3366 r.x += 1;
3367
3368 dc.SetFont(m_titlebarFont);
3369 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, TITLEBAR_TEXT));
3370 dc.DrawLabel(title, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3371 }
3372
3373 void wxWin32Renderer::DrawFrameIcon(wxDC& dc,
3374 const wxRect& rect,
3375 const wxIcon& icon,
3376 int flags)
3377 {
3378 if ( icon.Ok() )
3379 {
3380 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3381 dc.DrawIcon(icon, r.x, r.y);
3382 }
3383 }
3384
3385 void wxWin32Renderer::DrawFrameButton(wxDC& dc,
3386 wxCoord x, wxCoord y,
3387 int button,
3388 int flags)
3389 {
3390 wxRect r(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
3391
3392 size_t idx = 0;
3393 switch (button)
3394 {
3395 case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
3396 case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
3397 case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
3398 case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
3399 case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
3400 default:
3401 wxFAIL_MSG(wxT("incorrect button specification"));
3402 }
3403
3404 if ( flags & wxCONTROL_PRESSED )
3405 {
3406 DrawShadedRect(dc, &r, m_penBlack, m_penHighlight);
3407 DrawShadedRect(dc, &r, m_penDarkGrey, m_penLightGrey);
3408 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
3409 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x+1, r.y+1, TRUE);
3410 }
3411 else
3412 {
3413 DrawShadedRect(dc, &r, m_penHighlight, m_penBlack);
3414 DrawShadedRect(dc, &r, m_penLightGrey, m_penDarkGrey);
3415 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
3416 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x, r.y, TRUE);
3417 }
3418 }
3419
3420
3421 wxRect wxWin32Renderer::GetFrameClientArea(const wxRect& rect,
3422 int flags) const
3423 {
3424 wxRect r(rect);
3425
3426 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3427 {
3428 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3429 RESIZEABLE_FRAME_BORDER_THICKNESS :
3430 FRAME_BORDER_THICKNESS;
3431 r.Inflate(-border);
3432 }
3433 if ( flags & wxTOPLEVEL_TITLEBAR )
3434 {
3435 r.y += FRAME_TITLEBAR_HEIGHT;
3436 r.height -= FRAME_TITLEBAR_HEIGHT;
3437 }
3438
3439 return r;
3440 }
3441
3442 wxSize wxWin32Renderer::GetFrameTotalSize(const wxSize& clientSize,
3443 int flags) const
3444 {
3445 wxSize s(clientSize);
3446
3447 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3448 {
3449 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3450 RESIZEABLE_FRAME_BORDER_THICKNESS :
3451 FRAME_BORDER_THICKNESS;
3452 s.x += 2*border;
3453 s.y += 2*border;
3454 }
3455 if ( flags & wxTOPLEVEL_TITLEBAR )
3456 s.y += FRAME_TITLEBAR_HEIGHT;
3457
3458 return s;
3459 }
3460
3461 wxSize wxWin32Renderer::GetFrameIconSize() const
3462 {
3463 return wxSize(16, 16);
3464 }
3465
3466
3467 // ----------------------------------------------------------------------------
3468 // standard icons
3469 // ----------------------------------------------------------------------------
3470
3471 static char *error_xpm[]={
3472 "32 32 5 1",
3473 ". c None",
3474 "# c #800000",
3475 "b c #808080",
3476 "a c #ff0000",
3477 "c c #ffffff",
3478 "...........########.............",
3479 "........###aaaaaaaa###..........",
3480 ".......#aaaaaaaaaaaaaa#.........",
3481 ".....##aaaaaaaaaaaaaaaa##.......",
3482 "....#aaaaaaaaaaaaaaaaaaaa#......",
3483 "...#aaaaaaaaaaaaaaaaaaaaaa#.....",
3484 "...#aaaaaaaaaaaaaaaaaaaaaa#b....",
3485 "..#aaaaaacaaaaaaaaaacaaaaaa#b...",
3486 ".#aaaaaacccaaaaaaaacccaaaaaa#...",
3487 ".#aaaaacccccaaaaaacccccaaaaa#b..",
3488 ".#aaaaaacccccaaaacccccaaaaaa#bb.",
3489 "#aaaaaaaacccccaacccccaaaaaaaa#b.",
3490 "#aaaaaaaaaccccccccccaaaaaaaaa#b.",
3491 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3492 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3493 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3494 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3495 "#aaaaaaaaaccccccccccaaaaaaaaa#bb",
3496 "#aaaaaaaacccccaacccccaaaaaaaa#bb",
3497 ".#aaaaaacccccaaaacccccaaaaaa#bbb",
3498 ".#aaaaacccccaaaaaacccccaaaaa#bbb",
3499 ".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
3500 "..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
3501 "...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
3502 "...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
3503 "....#aaaaaaaaaaaaaaaaaaaa#bbb...",
3504 ".....##aaaaaaaaaaaaaaaa##bbbb...",
3505 "......b#aaaaaaaaaaaaaa#bbbbb....",
3506 ".......b###aaaaaaaa###bbbbb.....",
3507 ".........bb########bbbbbb.......",
3508 "..........bbbbbbbbbbbbbb........",
3509 ".............bbbbbbbb..........."};
3510
3511 static char *info_xpm[]={
3512 "32 32 6 1",
3513 ". c None",
3514 "d c #000000",
3515 "c c #0000ff",
3516 "# c #808080",
3517 "a c #c0c0c0",
3518 "b c #ffffff",
3519 "...........########.............",
3520 "........###abbbbbba###..........",
3521 "......##abbbbbbbbbbbba##........",
3522 ".....#abbbbbbbbbbbbbbbba#.......",
3523 "....#bbbbbbbaccccabbbbbbbd......",
3524 "...#bbbbbbbbccccccbbbbbbbbd.....",
3525 "..#bbbbbbbbbccccccbbbbbbbbbd....",
3526 ".#abbbbbbbbbaccccabbbbbbbbbad...",
3527 ".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
3528 "#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
3529 "#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
3530 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3531 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3532 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3533 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3534 "#abbbbbbbbbbbcccccbbbbbbbbbbad##",
3535 ".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
3536 ".#abbbbbbbbbbcccccbbbbbbbbbad###",
3537 "..#bbbbbbbbcccccccccbbbbbbbd###.",
3538 "...dbbbbbbbbbbbbbbbbbbbbbbd####.",
3539 "....dbbbbbbbbbbbbbbbbbbbbd####..",
3540 ".....dabbbbbbbbbbbbbbbbad####...",
3541 "......ddabbbbbbbbbbbbadd####....",
3542 ".......#dddabbbbbbaddd#####.....",
3543 "........###dddabbbd#######......",
3544 "..........####dbbbd#####........",
3545 ".............#dbbbd##...........",
3546 "...............dbbd##...........",
3547 "................dbd##...........",
3548 ".................dd##...........",
3549 "..................###...........",
3550 "...................##..........."};
3551
3552 static char *question_xpm[]={
3553 "32 32 6 1",
3554 ". c None",
3555 "c c #000000",
3556 "d c #0000ff",
3557 "# c #808080",
3558 "a c #c0c0c0",
3559 "b c #ffffff",
3560 "...........########.............",
3561 "........###abbbbbba###..........",
3562 "......##abbbbbbbbbbbba##........",
3563 ".....#abbbbbbbbbbbbbbbba#.......",
3564 "....#bbbbbbbbbbbbbbbbbbbbc......",
3565 "...#bbbbbbbaddddddabbbbbbbc.....",
3566 "..#bbbbbbbadabbddddabbbbbbbc....",
3567 ".#abbbbbbbddbbbbddddbbbbbbbac...",
3568 ".#bbbbbbbbddddbbddddbbbbbbbbc#..",
3569 "#abbbbbbbbddddbaddddbbbbbbbbac#.",
3570 "#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
3571 "#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
3572 "#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
3573 "#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
3574 "#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
3575 "#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
3576 ".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
3577 ".#abbbbbbbbbbddddbbbbbbbbbbac###",
3578 "..#bbbbbbbbbbddddbbbbbbbbbbc###.",
3579 "...cbbbbbbbbbaddabbbbbbbbbc####.",
3580 "....cbbbbbbbbbbbbbbbbbbbbc####..",
3581 ".....cabbbbbbbbbbbbbbbbac####...",
3582 "......ccabbbbbbbbbbbbacc####....",
3583 ".......#cccabbbbbbaccc#####.....",
3584 "........###cccabbbc#######......",
3585 "..........####cbbbc#####........",
3586 ".............#cbbbc##...........",
3587 "...............cbbc##...........",
3588 "................cbc##...........",
3589 ".................cc##...........",
3590 "..................###...........",
3591 "...................##..........."};
3592
3593 static char *warning_xpm[]={
3594 "32 32 6 1",
3595 ". c None",
3596 "c c #000000",
3597 "# c #808000",
3598 "d c #808080",
3599 "b c #c0c0c0",
3600 "a c #ffff00",
3601 ".............###................",
3602 "............#aabc...............",
3603 "...........#aaaabcd.............",
3604 "...........#aaaaacdd............",
3605 "..........#aaaaaabcdd...........",
3606 "..........#aaaaaaacdd...........",
3607 ".........#aaaaaaaabcdd..........",
3608 ".........#aaaaaaaaacdd..........",
3609 "........#aaaaaaaaaabcdd.........",
3610 "........#aaabcccbaaacdd.........",
3611 ".......#aaaacccccaaabcdd........",
3612 ".......#aaaacccccaaaacdd........",
3613 "......#aaaaacccccaaaabcdd.......",
3614 "......#aaaaacccccaaaaacdd.......",
3615 ".....#aaaaaacccccaaaaabcdd......",
3616 ".....#aaaaaa#ccc#aaaaaacdd......",
3617 "....#aaaaaaabcccbaaaaaabcdd.....",
3618 "....#aaaaaaaacccaaaaaaaacdd.....",
3619 "...#aaaaaaaaa#c#aaaaaaaabcdd....",
3620 "...#aaaaaaaaabcbaaaaaaaaacdd....",
3621 "..#aaaaaaaaaaacaaaaaaaaaabcdd...",
3622 "..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
3623 ".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
3624 ".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
3625 "#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
3626 "#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
3627 "#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
3628 "#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
3629 ".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
3630 "..#ccccccccccccccccccccccccddddd",
3631 "....ddddddddddddddddddddddddddd.",
3632 ".....ddddddddddddddddddddddddd.."};
3633
3634 wxIcon wxWin32Renderer::GetStdIcon(int which) const
3635 {
3636 switch(which)
3637 {
3638 case wxICON_INFORMATION:
3639 return wxIcon(info_xpm);
3640
3641 case wxICON_QUESTION:
3642 return wxIcon(question_xpm);
3643
3644 case wxICON_EXCLAMATION:
3645 return wxIcon(warning_xpm);
3646
3647 default:
3648 wxFAIL_MSG(wxT("requested non existent standard icon"));
3649 // still fall through
3650
3651 case wxICON_HAND:
3652 return wxIcon(error_xpm);
3653 }
3654 }
3655
3656
3657 // ----------------------------------------------------------------------------
3658 // text control geometry
3659 // ----------------------------------------------------------------------------
3660
3661 static inline int GetTextBorderWidth()
3662 {
3663 return 1;
3664 }
3665
3666 wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
3667 const wxRect& rect)
3668 {
3669 wxRect rectTotal = rect;
3670
3671 wxCoord widthBorder = GetTextBorderWidth();
3672 rectTotal.Inflate(widthBorder);
3673
3674 // this is what Windows does
3675 rectTotal.height++;
3676
3677 return rectTotal;
3678 }
3679
3680 wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
3681 const wxRect& rect,
3682 wxCoord *extraSpaceBeyond)
3683 {
3684 wxRect rectText = rect;
3685
3686 // undo GetTextTotalArea()
3687 if ( rectText.height > 0 )
3688 rectText.height--;
3689
3690 wxCoord widthBorder = GetTextBorderWidth();
3691 rectText.Inflate(-widthBorder);
3692
3693 if ( extraSpaceBeyond )
3694 *extraSpaceBeyond = 0;
3695
3696 return rectText;
3697 }
3698
3699 // ----------------------------------------------------------------------------
3700 // size adjustments
3701 // ----------------------------------------------------------------------------
3702
3703 void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
3704 {
3705 #if wxUSE_SCROLLBAR
3706 if ( wxDynamicCast(window, wxScrollBar) )
3707 {
3708 // we only set the width of vert scrollbars and height of the
3709 // horizontal ones
3710 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
3711 size->y = m_sizeScrollbarArrow.y;
3712 else
3713 size->x = m_sizeScrollbarArrow.x;
3714
3715 // skip border width adjustments, they don't make sense for us
3716 return;
3717 }
3718 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3719
3720 #if wxUSE_BUTTON
3721 if ( wxDynamicCast(window, wxButton) )
3722 {
3723 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3724 {
3725 // TODO: don't harcode all this
3726 size->x += 3*window->GetCharWidth();
3727
3728 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
3729 if ( size->y < heightBtn - 8 )
3730 size->y = heightBtn;
3731 else
3732 size->y += 9;
3733 }
3734
3735 // no border width adjustments for buttons
3736 return;
3737 }
3738 #endif // wxUSE_BUTTON
3739
3740 // take into account the border width
3741 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
3742 size->x += rectBorder.x + rectBorder.width;
3743 size->y += rectBorder.y + rectBorder.height;
3744 }
3745
3746 // ============================================================================
3747 // wxInputHandler
3748 // ============================================================================
3749
3750 // ----------------------------------------------------------------------------
3751 // wxWin32InputHandler
3752 // ----------------------------------------------------------------------------
3753
3754 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer)
3755 {
3756 m_renderer = renderer;
3757 }
3758
3759 bool wxWin32InputHandler::HandleKey(wxInputConsumer *control,
3760 const wxKeyEvent& event,
3761 bool pressed)
3762 {
3763 return FALSE;
3764 }
3765
3766 bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control,
3767 const wxMouseEvent& event)
3768 {
3769 // clicking on the control gives it focus
3770 if ( event.ButtonDown() )
3771 {
3772 wxWindow *win = control->GetInputWindow();
3773 if ( wxWindow::FindFocus() != control->GetInputWindow() )
3774 {
3775 win->SetFocus();
3776
3777 return TRUE;
3778 }
3779 }
3780
3781 return FALSE;
3782 }
3783
3784 // ----------------------------------------------------------------------------
3785 // wxWin32ScrollBarInputHandler
3786 // ----------------------------------------------------------------------------
3787
3788 wxWin32ScrollBarInputHandler::
3789 wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
3790 wxInputHandler *handler)
3791 : wxStdScrollBarInputHandler(renderer, handler)
3792 {
3793 m_scrollPaused = FALSE;
3794 m_interval = 0;
3795 }
3796
3797 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
3798 const wxControlAction& action)
3799 {
3800 // stop if went beyond the position of the original click (this can only
3801 // happen when we scroll by pages)
3802 bool stop = FALSE;
3803 if ( action == wxACTION_SCROLL_PAGE_DOWN )
3804 {
3805 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
3806 != wxHT_SCROLLBAR_BAR_2;
3807 }
3808 else if ( action == wxACTION_SCROLL_PAGE_UP )
3809 {
3810 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
3811 != wxHT_SCROLLBAR_BAR_1;
3812 }
3813
3814 if ( stop )
3815 {
3816 StopScrolling(scrollbar);
3817
3818 scrollbar->Refresh();
3819
3820 return FALSE;
3821 }
3822
3823 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
3824 }
3825
3826 bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
3827 const wxMouseEvent& event)
3828 {
3829 // remember the current state
3830 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
3831
3832 // do process the message
3833 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
3834
3835 // analyse the changes
3836 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
3837 {
3838 // we just started dragging the thumb, remember its initial position to
3839 // be able to restore it if the drag is cancelled later
3840 m_eventStartDrag = event;
3841 }
3842
3843 return rc;
3844 }
3845
3846 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
3847 const wxMouseEvent& event)
3848 {
3849 // we don't highlight scrollbar elements, so there is no need to process
3850 // mouse move events normally - only do it while mouse is captured (i.e.
3851 // when we're dragging the thumb or pressing on something)
3852 if ( !m_winCapture )
3853 return FALSE;
3854
3855 if ( event.Entering() )
3856 {
3857 // we're not interested in this at all
3858 return FALSE;
3859 }
3860
3861 wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
3862 wxHitTest ht;
3863 if ( m_scrollPaused )
3864 {
3865 // check if the mouse returned to its original location
3866
3867 if ( event.Leaving() )
3868 {
3869 // it surely didn't
3870 return FALSE;
3871 }
3872
3873 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
3874 if ( ht == m_htLast )
3875 {
3876 // yes it did, resume scrolling
3877 m_scrollPaused = FALSE;
3878 if ( m_timerScroll )
3879 {
3880 // we were scrolling by line/page, restart timer
3881 m_timerScroll->Start(m_interval);
3882
3883 Press(scrollbar, TRUE);
3884 }
3885 else // we were dragging the thumb
3886 {
3887 // restore its last location
3888 HandleThumbMove(scrollbar, m_eventLastDrag);
3889 }
3890
3891 return TRUE;
3892 }
3893 }
3894 else // normal case, scrolling hasn't been paused
3895 {
3896 // if we're scrolling the scrollbar because the arrow or the shaft was
3897 // pressed, check that the mouse stays on the same scrollbar element
3898
3899 if ( event.Moving() )
3900 {
3901 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
3902 }
3903 else // event.Leaving()
3904 {
3905 ht = wxHT_NOWHERE;
3906 }
3907
3908 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3909 // is still ok - we only want to catch the case when the mouse leaves
3910 // the scrollbar here
3911 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
3912 {
3913 ht = wxHT_SCROLLBAR_THUMB;
3914 }
3915
3916 if ( ht != m_htLast )
3917 {
3918 // what were we doing? 2 possibilities: either an arrow/shaft was
3919 // pressed in which case we have a timer and so we just stop it or
3920 // we were dragging the thumb
3921 if ( m_timerScroll )
3922 {
3923 // pause scrolling
3924 m_interval = m_timerScroll->GetInterval();
3925 m_timerScroll->Stop();
3926 m_scrollPaused = TRUE;
3927
3928 // unpress the arrow
3929 Press(scrollbar, FALSE);
3930 }
3931 else // we were dragging the thumb
3932 {
3933 // remember the current thumb position to be able to restore it
3934 // if the mouse returns to it later
3935 m_eventLastDrag = event;
3936
3937 // and restore the original position (before dragging) of the
3938 // thumb for now
3939 HandleThumbMove(scrollbar, m_eventStartDrag);
3940 }
3941
3942 return TRUE;
3943 }
3944 }
3945
3946 return wxStdScrollBarInputHandler::HandleMouseMove(control, event);
3947 }
3948
3949 // ----------------------------------------------------------------------------
3950 // wxWin32CheckboxInputHandler
3951 // ----------------------------------------------------------------------------
3952
3953 bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control,
3954 const wxKeyEvent& event,
3955 bool pressed)
3956 {
3957 if ( pressed )
3958 {
3959 wxControlAction action;
3960 int keycode = event.GetKeyCode();
3961 switch ( keycode )
3962 {
3963 case WXK_SPACE:
3964 action = wxACTION_CHECKBOX_TOGGLE;
3965 break;
3966
3967 case WXK_SUBTRACT:
3968 case WXK_NUMPAD_SUBTRACT:
3969 action = wxACTION_CHECKBOX_CHECK;
3970 break;
3971
3972 case WXK_ADD:
3973 case WXK_NUMPAD_ADD:
3974 case WXK_NUMPAD_EQUAL:
3975 action = wxACTION_CHECKBOX_CLEAR;
3976 break;
3977 }
3978
3979 if ( !!action )
3980 {
3981 control->PerformAction(action);
3982
3983 return TRUE;
3984 }
3985 }
3986
3987 return FALSE;
3988 }
3989
3990 // ----------------------------------------------------------------------------
3991 // wxWin32TextCtrlInputHandler
3992 // ----------------------------------------------------------------------------
3993
3994 bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control,
3995 const wxKeyEvent& event,
3996 bool pressed)
3997 {
3998 // handle only MSW-specific text bindings here, the others are handled in
3999 // the base class
4000 if ( pressed )
4001 {
4002 int keycode = event.GetKeyCode();
4003
4004 wxControlAction action;
4005 if ( keycode == WXK_DELETE && event.ShiftDown() )
4006 {
4007 action = wxACTION_TEXT_CUT;
4008 }
4009 else if ( keycode == WXK_INSERT )
4010 {
4011 if ( event.ControlDown() )
4012 action = wxACTION_TEXT_COPY;
4013 else if ( event.ShiftDown() )
4014 action = wxACTION_TEXT_PASTE;
4015 }
4016
4017 if ( action != wxACTION_NONE )
4018 {
4019 control->PerformAction(action);
4020
4021 return TRUE;
4022 }
4023 }
4024
4025 return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed);
4026 }
4027
4028 // ----------------------------------------------------------------------------
4029 // wxWin32StatusBarInputHandler
4030 // ----------------------------------------------------------------------------
4031
4032 wxWin32StatusBarInputHandler::
4033 wxWin32StatusBarInputHandler(wxInputHandler *handler)
4034 : wxStdInputHandler(handler)
4035 {
4036 m_isOnGrip = FALSE;
4037 }
4038
4039 bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar,
4040 const wxPoint& pt) const
4041 {
4042 if ( statbar->HasFlag(wxST_SIZEGRIP) &&
4043 statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
4044 {
4045 wxSize sizeSbar = statbar->GetSize();
4046
4047 return (sizeSbar.x - pt.x) < STATUSBAR_GRIP_SIZE &&
4048 (sizeSbar.y - pt.y) < STATUSBAR_GRIP_SIZE;
4049 }
4050
4051 return FALSE;
4052 }
4053
4054 bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
4055 const wxMouseEvent& event)
4056 {
4057 if ( event.Button(1) )
4058 {
4059 if ( event.ButtonDown(1) )
4060 {
4061 wxWindow *statbar = consumer->GetInputWindow();
4062
4063 if ( IsOnGrip(statbar, event.GetPosition()) )
4064 {
4065 wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
4066 wxTopLevelWindow);
4067 if ( tlw )
4068 {
4069 tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
4070 wxHT_TOPLEVEL_BORDER_SE);
4071
4072 statbar->SetCursor(m_cursorOld);
4073
4074 return TRUE;
4075 }
4076 }
4077 }
4078 }
4079
4080 return wxStdInputHandler::HandleMouse(consumer, event);
4081 }
4082
4083 bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
4084 const wxMouseEvent& event)
4085 {
4086 wxWindow *statbar = consumer->GetInputWindow();
4087
4088 bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
4089 if ( isOnGrip != m_isOnGrip )
4090 {
4091 m_isOnGrip = isOnGrip;
4092 if ( isOnGrip )
4093 {
4094 m_cursorOld = statbar->GetCursor();
4095 statbar->SetCursor(wxCURSOR_SIZENWSE);
4096 }
4097 else
4098 {
4099 statbar->SetCursor(m_cursorOld);
4100 }
4101 }
4102
4103 return wxStdInputHandler::HandleMouseMove(consumer, event);
4104 }
4105