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