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