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