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