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