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