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