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