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