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