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