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