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