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