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