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