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