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