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