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