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