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