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