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