no changes (de-TABified, undid some horrors with which someone replaced my ?: operators
[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 wxBitmap bmp;
2277 if ( bitmap.Ok() )
2278 bmp = bitmap;
2279 else
2280 bmp = GetRadioBitmap(flags);
2281
2282 DrawCheckOrRadioButton(dc, label,
2283 bmp,
2284 rect, flags, align, indexAccel,
2285 FOCUS_RECT_OFFSET_Y); // default focus rect offset
2286 }
2287
2288 void wxWin32Renderer::DrawCheckButton(wxDC& dc,
2289 const wxString& label,
2290 const wxBitmap& bitmap,
2291 const wxRect& rect,
2292 int flags,
2293 wxAlignment align,
2294 int indexAccel)
2295 {
2296 wxBitmap bmp;
2297 if ( bitmap.Ok() )
2298 bmp = bitmap;
2299 else
2300 bmp = GetCheckBitmap(flags);
2301
2302 DrawCheckOrRadioButton(dc, label,
2303 bmp,
2304 rect, flags, align, indexAccel,
2305 0); // no focus rect offset for checkboxes
2306 }
2307
2308 // ----------------------------------------------------------------------------
2309 // text control
2310 // ----------------------------------------------------------------------------
2311
2312 void wxWin32Renderer::DrawTextLine(wxDC& dc,
2313 const wxString& text,
2314 const wxRect& rect,
2315 int selStart,
2316 int selEnd,
2317 int flags)
2318 {
2319 // nothing special to do here
2320 StandardDrawTextLine(dc, text, rect, selStart, selEnd, flags);
2321 }
2322
2323 void wxWin32Renderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
2324 {
2325 // we don't draw them
2326 }
2327
2328 // ----------------------------------------------------------------------------
2329 // notebook
2330 // ----------------------------------------------------------------------------
2331
2332 void wxWin32Renderer::DrawTab(wxDC& dc,
2333 const wxRect& rectOrig,
2334 wxDirection dir,
2335 const wxString& label,
2336 const wxBitmap& bitmap,
2337 int flags,
2338 int indexAccel)
2339 {
2340 wxRect rect = rectOrig;
2341
2342 // the current tab is drawn indented (to the top for default case) and
2343 // bigger than the other ones
2344 const wxSize indent = GetTabIndent();
2345 if ( flags & wxCONTROL_SELECTED )
2346 {
2347 switch ( dir )
2348 {
2349 default:
2350 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2351 // fall through
2352
2353 case wxTOP:
2354 rect.Inflate(indent.x, 0);
2355 rect.y -= indent.y;
2356 rect.height += indent.y;
2357 break;
2358
2359 case wxBOTTOM:
2360 rect.Inflate(indent.x, 0);
2361 rect.height += indent.y;
2362 break;
2363
2364 case wxLEFT:
2365 case wxRIGHT:
2366 wxFAIL_MSG(_T("TODO"));
2367 break;
2368 }
2369 }
2370
2371 // draw the text, image and the focus around them (if necessary)
2372 wxRect rectLabel = rect;
2373 rectLabel.Deflate(1, 1);
2374 DrawButtonLabel(dc, label, bitmap, rectLabel,
2375 flags, wxALIGN_CENTRE, indexAccel);
2376
2377 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2378 static const wxCoord CUTOFF = 2; // radius of the rounded corner
2379 wxCoord x = rect.x,
2380 y = rect.y,
2381 x2 = rect.GetRight(),
2382 y2 = rect.GetBottom();
2383
2384 // FIXME: all this code will break if the tab indent or the border width,
2385 // it is tied to the fact that both of them are equal to 2
2386 switch ( dir )
2387 {
2388 default:
2389 case wxTOP:
2390 dc.SetPen(m_penHighlight);
2391 dc.DrawLine(x, y2, x, y + CUTOFF);
2392 dc.DrawLine(x, y + CUTOFF, x + CUTOFF, y);
2393 dc.DrawLine(x + CUTOFF, y, x2 - CUTOFF + 1, y);
2394
2395 dc.SetPen(m_penBlack);
2396 dc.DrawLine(x2, y2, x2, y + CUTOFF);
2397 dc.DrawLine(x2, y + CUTOFF, x2 - CUTOFF, y);
2398
2399 dc.SetPen(m_penDarkGrey);
2400 dc.DrawLine(x2 - 1, y2, x2 - 1, y + CUTOFF - 1);
2401
2402 if ( flags & wxCONTROL_SELECTED )
2403 {
2404 dc.SetPen(m_penLightGrey);
2405
2406 // overwrite the part of the border below this tab
2407 dc.DrawLine(x + 1, y2 + 1, x2 - 1, y2 + 1);
2408
2409 // and the shadow of the tab to the left of us
2410 dc.DrawLine(x + 1, y + CUTOFF + 1, x + 1, y2 + 1);
2411 }
2412 break;
2413
2414 case wxBOTTOM:
2415 dc.SetPen(m_penHighlight);
2416 // we need to continue one pixel further to overwrite the corner of
2417 // the border for the selected tab
2418 dc.DrawLine(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0),
2419 x, y2 - CUTOFF);
2420 dc.DrawLine(x, y2 - CUTOFF, x + CUTOFF, y2);
2421
2422 dc.SetPen(m_penBlack);
2423 dc.DrawLine(x + CUTOFF, y2, x2 - CUTOFF + 1, y2);
2424 dc.DrawLine(x2, y, x2, y2 - CUTOFF);
2425 dc.DrawLine(x2, y2 - CUTOFF, x2 - CUTOFF, y2);
2426
2427 dc.SetPen(m_penDarkGrey);
2428 dc.DrawLine(x + CUTOFF, y2 - 1, x2 - CUTOFF + 1, y2 - 1);
2429 dc.DrawLine(x2 - 1, y, x2 - 1, y2 - CUTOFF + 1);
2430
2431 if ( flags & wxCONTROL_SELECTED )
2432 {
2433 dc.SetPen(m_penLightGrey);
2434
2435 // overwrite the part of the (double!) border above this tab
2436 dc.DrawLine(x + 1, y - 1, x2 - 1, y - 1);
2437 dc.DrawLine(x + 1, y - 2, x2 - 1, y - 2);
2438
2439 // and the shadow of the tab to the left of us
2440 dc.DrawLine(x + 1, y2 - CUTOFF, x + 1, y - 1);
2441 }
2442 break;
2443
2444 case wxLEFT:
2445 case wxRIGHT:
2446 wxFAIL_MSG(_T("TODO"));
2447 }
2448 }
2449
2450 // ----------------------------------------------------------------------------
2451 // slider
2452 // ----------------------------------------------------------------------------
2453
2454 wxSize wxWin32Renderer::GetSliderThumbSize(const wxRect& rect,
2455 wxOrientation orient) const
2456 {
2457 wxSize size;
2458
2459 wxRect rectShaft = GetSliderShaftRect(rect, orient);
2460 if ( orient == wxHORIZONTAL )
2461 {
2462 size.y = rect.height - 6;
2463 size.x = wxMin(size.y / 2, rectShaft.width);
2464 }
2465 else // vertical
2466 {
2467 size.x = rect.width - 6;
2468 size.y = wxMin(size.x / 2, rectShaft.height);
2469 }
2470
2471 return size;
2472 }
2473
2474 wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
2475 wxOrientation orient) const
2476 {
2477 static const wxCoord SLIDER_MARGIN = 6;
2478
2479 wxRect rect = rectOrig;
2480
2481 if ( orient == wxHORIZONTAL )
2482 {
2483 // make the rect of minimal width and centre it
2484 rect.height = 2*BORDER_THICKNESS;
2485 rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
2486 if ( rect.y < 0 )
2487 rect.y = 0;
2488
2489 // leave margins on the sides
2490 rect.Deflate(SLIDER_MARGIN, 0);
2491 }
2492 else // vertical
2493 {
2494 // same as above but in other direction
2495 rect.width = 2*BORDER_THICKNESS;
2496 rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
2497 if ( rect.x < 0 )
2498 rect.x = 0;
2499
2500 rect.Deflate(0, SLIDER_MARGIN);
2501 }
2502
2503 return rect;
2504 }
2505
2506 void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
2507 const wxRect& rectOrig,
2508 wxOrientation orient,
2509 int flags,
2510 wxRect *rectShaft)
2511 {
2512 if ( flags & wxCONTROL_FOCUSED )
2513 {
2514 DrawFocusRect(dc, rectOrig);
2515 }
2516
2517 wxRect rect = GetSliderShaftRect(rectOrig, orient);
2518
2519 if ( rectShaft )
2520 *rectShaft = rect;
2521
2522 DrawSunkenBorder(dc, &rect);
2523 }
2524
2525 void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
2526 const wxRect& rect,
2527 wxOrientation orient,
2528 int flags)
2529 {
2530 /*
2531 we are drawing a shape of this form
2532
2533 HHHHHHB <--- y
2534 H DB
2535 H DB
2536 H DB where H is hightlight colour
2537 H DB D dark grey
2538 H DB B black
2539 H DB
2540 H DB <--- y3
2541 H DB
2542 HDB
2543 B <--- y2
2544
2545 ^ ^ ^
2546 | | |
2547 x x3 x2
2548
2549 The interior of this shape is filled with the hatched brush if the thumb
2550 is pressed.
2551 */
2552
2553 DrawBackground(dc, wxNullColour, rect, flags);
2554
2555 bool transpose = orient == wxVERTICAL;
2556
2557 wxCoord x, y, x2, y2;
2558 if ( transpose )
2559 {
2560 x = rect.y;
2561 y = rect.x;
2562 x2 = rect.GetBottom();
2563 y2 = rect.GetRight();
2564 }
2565 else
2566 {
2567 x = rect.x;
2568 y = rect.y;
2569 x2 = rect.GetRight();
2570 y2 = rect.GetBottom();
2571 }
2572
2573 // the size of the pointed part of the thumb
2574 wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
2575
2576 wxCoord x3 = x + sizeArrow,
2577 y3 = y2 - sizeArrow;
2578
2579 dc.SetPen(m_penHighlight);
2580 DrawLine(dc, x, y, x2, y, transpose);
2581 DrawLine(dc, x, y + 1, x, y2 - sizeArrow, transpose);
2582 DrawLine(dc, x, y3, x3, y2, transpose);
2583
2584 dc.SetPen(m_penBlack);
2585 DrawLine(dc, x3, y2, x2, y3, transpose);
2586 DrawLine(dc, x2, y3, x2, y - 1, transpose);
2587
2588 dc.SetPen(m_penDarkGrey);
2589 DrawLine(dc, x3, y2 - 1, x2 - 1, y3, transpose);
2590 DrawLine(dc, x2 - 1, y3, x2 - 1, y, transpose);
2591
2592 if ( flags & wxCONTROL_PRESSED )
2593 {
2594 // TODO: MSW fills the entire area inside, not just the rect
2595 wxRect rectInt = rect;
2596 if ( transpose )
2597 rectInt.SetRight(y3);
2598 else
2599 rectInt.SetBottom(y3);
2600 rectInt.Deflate(2);
2601
2602 #if !defined(__WXMGL__)
2603 static const char *stipple_xpm[] = {
2604 /* columns rows colors chars-per-pixel */
2605 "2 2 2 1",
2606 " c None",
2607 "w c white",
2608 /* pixels */
2609 "w ",
2610 " w",
2611 };
2612 #else
2613 // VS: MGL can only do 8x8 stipple brushes
2614 static const char *stipple_xpm[] = {
2615 /* columns rows colors chars-per-pixel */
2616 "8 8 2 1",
2617 " c None",
2618 "w c white",
2619 /* pixels */
2620 "w w w w ",
2621 " w w w w",
2622 "w w w w ",
2623 " w w w w",
2624 "w w w w ",
2625 " w w w w",
2626 "w w w w ",
2627 " w w w w",
2628 };
2629 #endif
2630 dc.SetBrush(wxBrush(stipple_xpm));
2631
2632 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
2633 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
2634 dc.SetPen(*wxTRANSPARENT_PEN);
2635 dc.DrawRectangle(rectInt);
2636 }
2637 }
2638
2639 void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
2640 const wxRect& rect,
2641 const wxSize& sizeThumb,
2642 wxOrientation orient,
2643 int start,
2644 int end,
2645 int step,
2646 int flags)
2647 {
2648 if ( end == start )
2649 {
2650 // empty slider?
2651 return;
2652 }
2653
2654 // the variable names correspond to horizontal case, but they can be used
2655 // for both orientations
2656 wxCoord x1, x2, y1, y2, len, widthThumb;
2657 if ( orient == wxHORIZONTAL )
2658 {
2659 x1 = rect.GetLeft();
2660 x2 = rect.GetRight();
2661
2662 // draw from bottom to top to leave one pixel space between the ticks
2663 // and the slider as Windows do
2664 y1 = rect.GetBottom();
2665 y2 = rect.GetTop();
2666
2667 len = rect.width;
2668
2669 widthThumb = sizeThumb.x;
2670 }
2671 else // vertical
2672 {
2673 x1 = rect.GetTop();
2674 x2 = rect.GetBottom();
2675
2676 y1 = rect.GetRight();
2677 y2 = rect.GetLeft();
2678
2679 len = rect.height;
2680
2681 widthThumb = sizeThumb.y;
2682 }
2683
2684 // the first tick should be positioned in such way that a thumb drawn in
2685 // the first position points down directly to it
2686 x1 += widthThumb / 2;
2687 x2 -= widthThumb / 2;
2688
2689 // this also means that we have slightly less space for the ticks in
2690 // between the first and the last
2691 len -= widthThumb;
2692
2693 dc.SetPen(m_penBlack);
2694
2695 int range = end - start;
2696 for ( int n = 0; n < range; n += step )
2697 {
2698 wxCoord x = x1 + (len*n) / range;
2699
2700 DrawLine(dc, x, y1, x, y2, orient == wxVERTICAL);
2701 }
2702
2703 // always draw the line at the end position
2704 DrawLine(dc, x2, y1, x2, y2, orient == wxVERTICAL);
2705 }
2706
2707 // ----------------------------------------------------------------------------
2708 // menu and menubar
2709 // ----------------------------------------------------------------------------
2710
2711 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2712 class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo
2713 {
2714 public:
2715 virtual wxSize GetSize() const { return m_size; }
2716
2717 wxCoord GetLabelOffset() const { return m_ofsLabel; }
2718 wxCoord GetAccelOffset() const { return m_ofsAccel; }
2719
2720 wxCoord GetItemHeight() const { return m_heightItem; }
2721
2722 private:
2723 // the total size of the menu
2724 wxSize m_size;
2725
2726 // the offset of the start of the menu item label
2727 wxCoord m_ofsLabel;
2728
2729 // the offset of the start of the accel label
2730 wxCoord m_ofsAccel;
2731
2732 // the height of a normal (not separator) item
2733 wxCoord m_heightItem;
2734
2735 friend wxMenuGeometryInfo *
2736 wxWin32Renderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
2737 };
2738
2739 // FIXME: all constants are hardcoded but shouldn't be
2740 static const wxCoord MENU_LEFT_MARGIN = 9;
2741 static const wxCoord MENU_RIGHT_MARGIN = 18;
2742 static const wxCoord MENU_VERT_MARGIN = 3;
2743
2744 // the margin around bitmap/check marks (on each side)
2745 static const wxCoord MENU_BMP_MARGIN = 2;
2746
2747 // the margin between the labels and accel strings
2748 static const wxCoord MENU_ACCEL_MARGIN = 8;
2749
2750 // the separator height in pixels: in fact, strangely enough, the real height
2751 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2752 // account here
2753 static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
2754
2755 // the size of the standard checkmark bitmap
2756 static const wxCoord MENU_CHECK_SIZE = 9;
2757
2758 void wxWin32Renderer::DrawMenuBarItem(wxDC& dc,
2759 const wxRect& rectOrig,
2760 const wxString& label,
2761 int flags,
2762 int indexAccel)
2763 {
2764 wxRect rect = rectOrig;
2765 rect.height--;
2766
2767 wxDCTextColourChanger colChanger(dc);
2768
2769 if ( flags & wxCONTROL_SELECTED )
2770 {
2771 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2772
2773 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2774 dc.SetBrush(wxBrush(colBg, wxSOLID));
2775 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2776 dc.DrawRectangle(rect);
2777 }
2778
2779 // don't draw the focus rect around menu bar items
2780 DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
2781 wxALIGN_CENTRE, indexAccel);
2782 }
2783
2784 void wxWin32Renderer::DrawMenuItem(wxDC& dc,
2785 wxCoord y,
2786 const wxMenuGeometryInfo& gi,
2787 const wxString& label,
2788 const wxString& accel,
2789 const wxBitmap& bitmap,
2790 int flags,
2791 int indexAccel)
2792 {
2793 const wxWin32MenuGeometryInfo& geometryInfo =
2794 (const wxWin32MenuGeometryInfo&)gi;
2795
2796 wxRect rect;
2797 rect.x = 0;
2798 rect.y = y;
2799 rect.width = geometryInfo.GetSize().x;
2800 rect.height = geometryInfo.GetItemHeight();
2801
2802 // draw the selected item specially
2803 wxDCTextColourChanger colChanger(dc);
2804 if ( flags & wxCONTROL_SELECTED )
2805 {
2806 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2807
2808 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2809 dc.SetBrush(wxBrush(colBg, wxSOLID));
2810 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2811 dc.DrawRectangle(rect);
2812 }
2813
2814 // draw the bitmap: use the bitmap provided or the standard checkmark for
2815 // the checkable items
2816 wxBitmap bmp = bitmap;
2817 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKED) )
2818 {
2819 bmp = GetIndicator(IndicatorType_Menu, flags);
2820 }
2821
2822 if ( bmp.Ok() )
2823 {
2824 rect.SetRight(geometryInfo.GetLabelOffset());
2825 wxControlRenderer::DrawBitmap(dc, bmp, rect);
2826 }
2827
2828 // draw the label
2829 rect.x = geometryInfo.GetLabelOffset();
2830 rect.SetRight(geometryInfo.GetAccelOffset());
2831
2832 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
2833
2834 // draw the accel string
2835 rect.x = geometryInfo.GetAccelOffset();
2836 rect.SetRight(geometryInfo.GetSize().x);
2837
2838 // NB: no accel index here
2839 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
2840
2841 // draw the submenu indicator
2842 if ( flags & wxCONTROL_ISSUBMENU )
2843 {
2844 rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
2845 rect.width = MENU_RIGHT_MARGIN;
2846
2847 wxArrowStyle arrowStyle;
2848 if ( flags & wxCONTROL_DISABLED )
2849 arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InversedDisabled
2850 : Arrow_Disabled;
2851 else if ( flags & wxCONTROL_SELECTED )
2852 arrowStyle = Arrow_Inversed;
2853 else
2854 arrowStyle = Arrow_Normal;
2855
2856 DrawArrow(dc, rect, Arrow_Right, arrowStyle);
2857 }
2858 }
2859
2860 void wxWin32Renderer::DrawMenuSeparator(wxDC& dc,
2861 wxCoord y,
2862 const wxMenuGeometryInfo& geomInfo)
2863 {
2864 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
2865 }
2866
2867 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& sizeText) const
2868 {
2869 wxSize size = sizeText;
2870
2871 // FIXME: menubar height is configurable under Windows
2872 size.x += 12;
2873 size.y += 6;
2874
2875 return size;
2876 }
2877
2878 wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win,
2879 const wxMenu& menu) const
2880 {
2881 // prepare the dc: for now we draw all the items with the system font
2882 wxClientDC dc(win);
2883 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
2884
2885 // the height of a normal item
2886 wxCoord heightText = dc.GetCharHeight();
2887
2888 // the total height
2889 wxCoord height = 0;
2890
2891 // the max length of label and accel strings: the menu width is the sum of
2892 // them, even if they're for different items (as the accels should be
2893 // aligned)
2894 //
2895 // the max length of the bitmap is never 0 as Windows always leaves enough
2896 // space for a check mark indicator
2897 wxCoord widthLabelMax = 0,
2898 widthAccelMax = 0,
2899 widthBmpMax = MENU_LEFT_MARGIN;
2900
2901 for ( wxMenuItemList::Node *node = menu.GetMenuItems().GetFirst();
2902 node;
2903 node = node->GetNext() )
2904 {
2905 // height of this item
2906 wxCoord h;
2907
2908 wxMenuItem *item = node->GetData();
2909 if ( item->IsSeparator() )
2910 {
2911 h = MENU_SEPARATOR_HEIGHT;
2912 }
2913 else // not separator
2914 {
2915 h = heightText;
2916
2917 wxCoord widthLabel;
2918 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
2919 if ( widthLabel > widthLabelMax )
2920 {
2921 widthLabelMax = widthLabel;
2922 }
2923
2924 wxCoord widthAccel;
2925 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
2926 if ( widthAccel > widthAccelMax )
2927 {
2928 widthAccelMax = widthAccel;
2929 }
2930
2931 const wxBitmap& bmp = item->GetBitmap();
2932 if ( bmp.Ok() )
2933 {
2934 wxCoord widthBmp = bmp.GetWidth();
2935 if ( widthBmp > widthBmpMax )
2936 widthBmpMax = widthBmp;
2937 }
2938 //else if ( item->IsCheckable() ): no need to check for this as
2939 // MENU_LEFT_MARGIN is big enough to show the check mark
2940 }
2941
2942 h += 2*MENU_VERT_MARGIN;
2943
2944 // remember the item position and height
2945 item->SetGeometry(height, h);
2946
2947 height += h;
2948 }
2949
2950 // bundle the metrics into a struct and return it
2951 wxWin32MenuGeometryInfo *gi = new wxWin32MenuGeometryInfo;
2952
2953 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
2954 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
2955 if ( widthAccelMax > 0 )
2956 {
2957 // if we actually have any accesl, add a margin
2958 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
2959 }
2960
2961 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
2962
2963 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
2964 gi->m_size.y = height;
2965
2966 return gi;
2967 }
2968
2969 // ----------------------------------------------------------------------------
2970 // status bar
2971 // ----------------------------------------------------------------------------
2972
2973 static const wxCoord STATBAR_BORDER_X = 2;
2974 static const wxCoord STATBAR_BORDER_Y = 2;
2975
2976 wxSize wxWin32Renderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const
2977 {
2978 if ( borderBetweenFields )
2979 *borderBetweenFields = 2;
2980
2981 return wxSize(STATBAR_BORDER_X, STATBAR_BORDER_Y);
2982 }
2983
2984 void wxWin32Renderer::DrawStatusField(wxDC& dc,
2985 const wxRect& rect,
2986 const wxString& label,
2987 int flags)
2988 {
2989 wxRect rectIn;
2990
2991 if ( flags & wxCONTROL_ISDEFAULT )
2992 {
2993 // draw the size grip: it is a normal rect except that in the lower
2994 // right corner we have several bands which may be used for dragging
2995 // the status bar corner
2996 //
2997 // each band consists of 4 stripes: m_penHighlight, double
2998 // m_penDarkGrey and transparent one
2999 wxCoord x2 = rect.GetRight(),
3000 y2 = rect.GetBottom();
3001
3002 // draw the upper left part of the rect normally
3003 dc.SetPen(m_penDarkGrey);
3004 dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2);
3005 dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop());
3006
3007 // draw the grey stripes of the grip
3008 size_t n;
3009 wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1;
3010 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
3011 {
3012 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
3013 dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1);
3014 }
3015
3016 // draw the white stripes
3017 dc.SetPen(m_penHighlight);
3018 ofs = WIDTH_STATUSBAR_GRIP_BAND + 1;
3019 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
3020 {
3021 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
3022 }
3023
3024 // draw the remaining rect boundaries
3025 ofs -= WIDTH_STATUSBAR_GRIP_BAND;
3026 dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1);
3027 dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2);
3028
3029 rectIn = rect;
3030 rectIn.Deflate(1);
3031
3032 rectIn.width -= STATUSBAR_GRIP_SIZE;
3033 }
3034 else // normal pane
3035 {
3036 DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
3037 }
3038
3039 rectIn.Deflate(STATBAR_BORDER_X, STATBAR_BORDER_Y);
3040
3041 wxDCClipper clipper(dc, rectIn);
3042 DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3043 }
3044
3045 // ----------------------------------------------------------------------------
3046 // combobox
3047 // ----------------------------------------------------------------------------
3048
3049 void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal,
3050 wxBitmap *bmpFocus,
3051 wxBitmap *bmpPressed,
3052 wxBitmap *bmpDisabled)
3053 {
3054 static const wxCoord widthCombo = 16;
3055 static const wxCoord heightCombo = 17;
3056
3057 wxMemoryDC dcMem;
3058
3059 if ( bmpNormal )
3060 {
3061 bmpNormal->Create(widthCombo, heightCombo);
3062 dcMem.SelectObject(*bmpNormal);
3063 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3064 Arrow_Down, Arrow_Normal);
3065 }
3066
3067 if ( bmpPressed )
3068 {
3069 bmpPressed->Create(widthCombo, heightCombo);
3070 dcMem.SelectObject(*bmpPressed);
3071 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3072 Arrow_Down, Arrow_Pressed);
3073 }
3074
3075 if ( bmpDisabled )
3076 {
3077 bmpDisabled->Create(widthCombo, heightCombo);
3078 dcMem.SelectObject(*bmpDisabled);
3079 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3080 Arrow_Down, Arrow_Disabled);
3081 }
3082 }
3083
3084 // ----------------------------------------------------------------------------
3085 // background
3086 // ----------------------------------------------------------------------------
3087
3088 void wxWin32Renderer::DoDrawBackground(wxDC& dc,
3089 const wxColour& col,
3090 const wxRect& rect)
3091 {
3092 wxBrush brush(col, wxSOLID);
3093 dc.SetBrush(brush);
3094 dc.SetPen(*wxTRANSPARENT_PEN);
3095 dc.DrawRectangle(rect);
3096 }
3097
3098 void wxWin32Renderer::DrawBackground(wxDC& dc,
3099 const wxColour& col,
3100 const wxRect& rect,
3101 int flags)
3102 {
3103 // just fill it with the given or default bg colour
3104 wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL);
3105 DoDrawBackground(dc, colBg, rect);
3106 }
3107
3108 // ----------------------------------------------------------------------------
3109 // scrollbar
3110 // ----------------------------------------------------------------------------
3111
3112 void wxWin32Renderer::DrawArrow(wxDC& dc,
3113 wxDirection dir,
3114 const wxRect& rect,
3115 int flags)
3116 {
3117 // get the bitmap for this arrow
3118 wxArrowDirection arrowDir;
3119 switch ( dir )
3120 {
3121 case wxLEFT: arrowDir = Arrow_Left; break;
3122 case wxRIGHT: arrowDir = Arrow_Right; break;
3123 case wxUP: arrowDir = Arrow_Up; break;
3124 case wxDOWN: arrowDir = Arrow_Down; break;
3125
3126 default:
3127 wxFAIL_MSG(_T("unknown arrow direction"));
3128 return;
3129 }
3130
3131 wxArrowStyle arrowStyle;
3132 if ( flags & wxCONTROL_PRESSED )
3133 {
3134 // can't be pressed and disabled
3135 arrowStyle = Arrow_Pressed;
3136 }
3137 else
3138 {
3139 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
3140 }
3141
3142 DrawArrowButton(dc, rect, arrowDir, arrowStyle);
3143 }
3144
3145 void wxWin32Renderer::DrawArrow(wxDC& dc,
3146 const wxRect& rect,
3147 wxArrowDirection arrowDir,
3148 wxArrowStyle arrowStyle)
3149 {
3150 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
3151
3152 // under Windows the arrows always have the same size so just centre it in
3153 // the provided rectangle
3154 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
3155 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
3156
3157 // Windows does it like this...
3158 if ( arrowDir == Arrow_Left )
3159 x--;
3160
3161 // draw it
3162 dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
3163 }
3164
3165 void wxWin32Renderer::DrawArrowButton(wxDC& dc,
3166 const wxRect& rectAll,
3167 wxArrowDirection arrowDir,
3168 wxArrowStyle arrowStyle)
3169 {
3170 wxRect rect = rectAll;
3171 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3172 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
3173 DrawArrow(dc, rect, arrowDir, arrowStyle);
3174 }
3175
3176 void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
3177 wxOrientation orient,
3178 const wxRect& rect,
3179 int flags)
3180 {
3181 // we don't use the flags, the thumb never changes appearance
3182 wxRect rectThumb = rect;
3183 DrawArrowBorder(dc, &rectThumb);
3184 DrawBackground(dc, wxNullColour, rectThumb);
3185 }
3186
3187 void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
3188 wxOrientation orient,
3189 const wxRect& rectBar,
3190 int flags)
3191 {
3192 wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
3193 ? wxColourScheme::SCROLLBAR_PRESSED
3194 : wxColourScheme::SCROLLBAR;
3195 DoDrawBackground(dc, m_scheme->Get(col), rectBar);
3196 }
3197
3198 void wxWin32Renderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
3199 {
3200 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3201 }
3202
3203 wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar,
3204 wxScrollBar::Element elem,
3205 int thumbPos) const
3206 {
3207 return StandardGetScrollbarRect(scrollbar, elem,
3208 thumbPos, m_sizeScrollbarArrow);
3209 }
3210
3211 wxCoord wxWin32Renderer::GetScrollbarSize(const wxScrollBar *scrollbar)
3212 {
3213 return StandardScrollBarSize(scrollbar, m_sizeScrollbarArrow);
3214 }
3215
3216 wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
3217 const wxPoint& pt) const
3218 {
3219 return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow);
3220 }
3221
3222 wxCoord wxWin32Renderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
3223 int thumbPos)
3224 {
3225 return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow);
3226 }
3227
3228 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar,
3229 wxCoord coord)
3230 {
3231 return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow);
3232 }
3233
3234 // ----------------------------------------------------------------------------
3235 // top level windows
3236 // ----------------------------------------------------------------------------
3237
3238 int wxWin32Renderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
3239 {
3240 wxRect client = GetFrameClientArea(rect, flags);
3241
3242 if ( client.Inside(pt) )
3243 return wxHT_TOPLEVEL_CLIENT_AREA;
3244
3245 if ( flags & wxTOPLEVEL_TITLEBAR )
3246 {
3247 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3248
3249 if ( flags & wxTOPLEVEL_ICON )
3250 {
3251 if ( wxRect(client.GetPosition(), GetFrameIconSize()).Inside(pt) )
3252 return wxHT_TOPLEVEL_ICON;
3253 }
3254
3255 wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
3256 client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
3257 FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
3258
3259 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3260 {
3261 if ( btnRect.Inside(pt) )
3262 return wxHT_TOPLEVEL_BUTTON_CLOSE;
3263 btnRect.x -= FRAME_BUTTON_WIDTH + 2;
3264 }
3265 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3266 {
3267 if ( btnRect.Inside(pt) )
3268 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
3269 btnRect.x -= FRAME_BUTTON_WIDTH;
3270 }
3271 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3272 {
3273 if ( btnRect.Inside(pt) )
3274 return wxHT_TOPLEVEL_BUTTON_RESTORE;
3275 btnRect.x -= FRAME_BUTTON_WIDTH;
3276 }
3277 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3278 {
3279 if ( btnRect.Inside(pt) )
3280 return wxHT_TOPLEVEL_BUTTON_ICONIZE;
3281 btnRect.x -= FRAME_BUTTON_WIDTH;
3282 }
3283 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3284 {
3285 if ( btnRect.Inside(pt) )
3286 return wxHT_TOPLEVEL_BUTTON_HELP;
3287 btnRect.x -= FRAME_BUTTON_WIDTH;
3288 }
3289
3290 if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
3291 return wxHT_TOPLEVEL_TITLEBAR;
3292 }
3293
3294 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3295 {
3296 // we are certainly at one of borders, lets decide which one:
3297
3298 int border = 0;
3299 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3300 if ( pt.x < client.x )
3301 border |= wxHT_TOPLEVEL_BORDER_W;
3302 else if ( pt.x >= client.width + client.x )
3303 border |= wxHT_TOPLEVEL_BORDER_E;
3304 if ( pt.y < client.y )
3305 border |= wxHT_TOPLEVEL_BORDER_N;
3306 else if ( pt.y >= client.height + client.y )
3307 border |= wxHT_TOPLEVEL_BORDER_S;
3308 return border;
3309 }
3310
3311 return wxHT_NOWHERE;
3312 }
3313
3314 void wxWin32Renderer::DrawFrameTitleBar(wxDC& dc,
3315 const wxRect& rect,
3316 const wxString& title,
3317 const wxIcon& icon,
3318 int flags,
3319 int specialButton,
3320 int specialButtonFlags)
3321 {
3322 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3323 {
3324 DrawFrameBorder(dc, rect, flags);
3325 }
3326 if ( flags & wxTOPLEVEL_TITLEBAR )
3327 {
3328 DrawFrameBackground(dc, rect, flags);
3329 if ( flags & wxTOPLEVEL_ICON )
3330 DrawFrameIcon(dc, rect, icon, flags);
3331 DrawFrameTitle(dc, rect, title, flags);
3332
3333 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3334 wxCoord x,y;
3335 x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
3336 y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
3337
3338 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3339 {
3340 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
3341 (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
3342 specialButtonFlags : 0);
3343 x -= FRAME_BUTTON_WIDTH + 2;
3344 }
3345 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3346 {
3347 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
3348 (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
3349 specialButtonFlags : 0);
3350 x -= FRAME_BUTTON_WIDTH;
3351 }
3352 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3353 {
3354 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
3355 (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
3356 specialButtonFlags : 0);
3357 x -= FRAME_BUTTON_WIDTH;
3358 }
3359 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3360 {
3361 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
3362 (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
3363 specialButtonFlags : 0);
3364 x -= FRAME_BUTTON_WIDTH;
3365 }
3366 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3367 {
3368 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
3369 (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
3370 specialButtonFlags : 0);
3371 x -= FRAME_BUTTON_WIDTH;
3372 }
3373 }
3374 }
3375
3376 void wxWin32Renderer::DrawFrameBorder(wxDC& dc,
3377 const wxRect& rect,
3378 int flags)
3379 {
3380 if ( !(flags & wxTOPLEVEL_BORDER) ) return;
3381
3382 wxRect r(rect);
3383
3384 DrawShadedRect(dc, &r, m_penLightGrey, m_penBlack);
3385 DrawShadedRect(dc, &r, m_penHighlight, m_penDarkGrey);
3386 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3387 if ( flags & wxTOPLEVEL_RESIZEABLE )
3388 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3389 }
3390
3391 void wxWin32Renderer::DrawFrameBackground(wxDC& dc,
3392 const wxRect& rect,
3393 int flags)
3394 {
3395 if ( !(flags & wxTOPLEVEL_TITLEBAR) ) return;
3396
3397 wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
3398 wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE) :
3399 wxSCHEME_COLOUR(m_scheme, TITLEBAR);
3400
3401 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3402 r.height = FRAME_TITLEBAR_HEIGHT;
3403
3404 DrawBackground(dc, col, r);
3405 }
3406
3407 void wxWin32Renderer::DrawFrameTitle(wxDC& dc,
3408 const wxRect& rect,
3409 const wxString& title,
3410 int flags)
3411 {
3412 wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
3413 wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE_TEXT) :
3414 wxSCHEME_COLOUR(m_scheme, TITLEBAR_TEXT);
3415
3416 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3417 r.height = FRAME_TITLEBAR_HEIGHT;
3418 if ( flags & wxTOPLEVEL_ICON )
3419 {
3420 r.x += FRAME_TITLEBAR_HEIGHT;
3421 r.width -= FRAME_TITLEBAR_HEIGHT + 2;
3422 }
3423 else
3424 {
3425 r.x += 1;
3426 r.width -= 3;
3427 }
3428
3429 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3430 r.width -= FRAME_BUTTON_WIDTH + 2;
3431 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3432 r.width -= FRAME_BUTTON_WIDTH;
3433 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3434 r.width -= FRAME_BUTTON_WIDTH;
3435 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3436 r.width -= FRAME_BUTTON_WIDTH;
3437 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3438 r.width -= FRAME_BUTTON_WIDTH;
3439
3440 dc.SetFont(m_titlebarFont);
3441 dc.SetTextForeground(col);
3442
3443 wxCoord textW;
3444 dc.GetTextExtent(title, &textW, NULL);
3445 if ( textW > r.width )
3446 {
3447 // text is too big, let's shorten it and add "..." after it:
3448 size_t len = title.length();
3449 wxCoord WSoFar, letterW;
3450
3451 dc.GetTextExtent(wxT("..."), &WSoFar, NULL);
3452 if ( WSoFar > r.width )
3453 {
3454 // not enough space to draw anything
3455 return;
3456 }
3457
3458 wxString s;
3459 s.Alloc(len);
3460 for (size_t i = 0; i < len; i++)
3461 {
3462 dc.GetTextExtent(title[i], &letterW, NULL);
3463 if ( letterW + WSoFar > r.width )
3464 break;
3465 WSoFar += letterW;
3466 s << title[i];
3467 }
3468 s << wxT("...");
3469 dc.DrawLabel(s, wxNullBitmap, r,
3470 wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3471 }
3472 else
3473 dc.DrawLabel(title, wxNullBitmap, r,
3474 wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3475 }
3476
3477 void wxWin32Renderer::DrawFrameIcon(wxDC& dc,
3478 const wxRect& rect,
3479 const wxIcon& icon,
3480 int flags)
3481 {
3482 if ( icon.Ok() )
3483 {
3484 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3485 dc.DrawIcon(icon, r.x, r.y);
3486 }
3487 }
3488
3489 void wxWin32Renderer::DrawFrameButton(wxDC& dc,
3490 wxCoord x, wxCoord y,
3491 int button,
3492 int flags)
3493 {
3494 wxRect r(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
3495
3496 size_t idx = 0;
3497 switch (button)
3498 {
3499 case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
3500 case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
3501 case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
3502 case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
3503 case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
3504 default:
3505 wxFAIL_MSG(wxT("incorrect button specification"));
3506 }
3507
3508 if ( flags & wxCONTROL_PRESSED )
3509 {
3510 DrawShadedRect(dc, &r, m_penBlack, m_penHighlight);
3511 DrawShadedRect(dc, &r, m_penDarkGrey, m_penLightGrey);
3512 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
3513 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x+1, r.y+1, TRUE);
3514 }
3515 else
3516 {
3517 DrawShadedRect(dc, &r, m_penHighlight, m_penBlack);
3518 DrawShadedRect(dc, &r, m_penLightGrey, m_penDarkGrey);
3519 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
3520 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x, r.y, TRUE);
3521 }
3522 }
3523
3524
3525 wxRect wxWin32Renderer::GetFrameClientArea(const wxRect& rect,
3526 int flags) const
3527 {
3528 wxRect r(rect);
3529
3530 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3531 {
3532 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3533 RESIZEABLE_FRAME_BORDER_THICKNESS :
3534 FRAME_BORDER_THICKNESS;
3535 r.Inflate(-border);
3536 }
3537 if ( flags & wxTOPLEVEL_TITLEBAR )
3538 {
3539 r.y += FRAME_TITLEBAR_HEIGHT;
3540 r.height -= FRAME_TITLEBAR_HEIGHT;
3541 }
3542
3543 return r;
3544 }
3545
3546 wxSize wxWin32Renderer::GetFrameTotalSize(const wxSize& clientSize,
3547 int flags) const
3548 {
3549 wxSize s(clientSize);
3550
3551 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3552 {
3553 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3554 RESIZEABLE_FRAME_BORDER_THICKNESS :
3555 FRAME_BORDER_THICKNESS;
3556 s.x += 2*border;
3557 s.y += 2*border;
3558 }
3559 if ( flags & wxTOPLEVEL_TITLEBAR )
3560 s.y += FRAME_TITLEBAR_HEIGHT;
3561
3562 return s;
3563 }
3564
3565 wxSize wxWin32Renderer::GetFrameMinSize(int flags) const
3566 {
3567 wxSize s(0, 0);
3568
3569 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3570 {
3571 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3572 RESIZEABLE_FRAME_BORDER_THICKNESS :
3573 FRAME_BORDER_THICKNESS;
3574 s.x += 2*border;
3575 s.y += 2*border;
3576 }
3577
3578 if ( flags & wxTOPLEVEL_TITLEBAR )
3579 {
3580 s.y += FRAME_TITLEBAR_HEIGHT;
3581
3582 if ( flags & wxTOPLEVEL_ICON )
3583 s.x += FRAME_TITLEBAR_HEIGHT + 2;
3584 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3585 s.x += FRAME_BUTTON_WIDTH + 2;
3586 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3587 s.x += FRAME_BUTTON_WIDTH;
3588 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3589 s.x += FRAME_BUTTON_WIDTH;
3590 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3591 s.x += FRAME_BUTTON_WIDTH;
3592 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3593 s.x += FRAME_BUTTON_WIDTH;
3594 }
3595
3596 return s;
3597 }
3598
3599 wxSize wxWin32Renderer::GetFrameIconSize() const
3600 {
3601 return wxSize(16, 16);
3602 }
3603
3604
3605 // ----------------------------------------------------------------------------
3606 // standard icons
3607 // ----------------------------------------------------------------------------
3608
3609 static char *error_xpm[]={
3610 "32 32 5 1",
3611 ". c None",
3612 "# c #800000",
3613 "b c #808080",
3614 "a c #ff0000",
3615 "c c #ffffff",
3616 "...........########.............",
3617 "........###aaaaaaaa###..........",
3618 ".......#aaaaaaaaaaaaaa#.........",
3619 ".....##aaaaaaaaaaaaaaaa##.......",
3620 "....#aaaaaaaaaaaaaaaaaaaa#......",
3621 "...#aaaaaaaaaaaaaaaaaaaaaa#.....",
3622 "...#aaaaaaaaaaaaaaaaaaaaaa#b....",
3623 "..#aaaaaacaaaaaaaaaacaaaaaa#b...",
3624 ".#aaaaaacccaaaaaaaacccaaaaaa#...",
3625 ".#aaaaacccccaaaaaacccccaaaaa#b..",
3626 ".#aaaaaacccccaaaacccccaaaaaa#bb.",
3627 "#aaaaaaaacccccaacccccaaaaaaaa#b.",
3628 "#aaaaaaaaaccccccccccaaaaaaaaa#b.",
3629 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3630 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3631 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3632 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3633 "#aaaaaaaaaccccccccccaaaaaaaaa#bb",
3634 "#aaaaaaaacccccaacccccaaaaaaaa#bb",
3635 ".#aaaaaacccccaaaacccccaaaaaa#bbb",
3636 ".#aaaaacccccaaaaaacccccaaaaa#bbb",
3637 ".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
3638 "..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
3639 "...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
3640 "...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
3641 "....#aaaaaaaaaaaaaaaaaaaa#bbb...",
3642 ".....##aaaaaaaaaaaaaaaa##bbbb...",
3643 "......b#aaaaaaaaaaaaaa#bbbbb....",
3644 ".......b###aaaaaaaa###bbbbb.....",
3645 ".........bb########bbbbbb.......",
3646 "..........bbbbbbbbbbbbbb........",
3647 ".............bbbbbbbb..........."};
3648
3649 static char *info_xpm[]={
3650 "32 32 6 1",
3651 ". c None",
3652 "d c #000000",
3653 "c c #0000ff",
3654 "# c #808080",
3655 "a c #c0c0c0",
3656 "b c #ffffff",
3657 "...........########.............",
3658 "........###abbbbbba###..........",
3659 "......##abbbbbbbbbbbba##........",
3660 ".....#abbbbbbbbbbbbbbbba#.......",
3661 "....#bbbbbbbaccccabbbbbbbd......",
3662 "...#bbbbbbbbccccccbbbbbbbbd.....",
3663 "..#bbbbbbbbbccccccbbbbbbbbbd....",
3664 ".#abbbbbbbbbaccccabbbbbbbbbad...",
3665 ".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
3666 "#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
3667 "#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
3668 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3669 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3670 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3671 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3672 "#abbbbbbbbbbbcccccbbbbbbbbbbad##",
3673 ".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
3674 ".#abbbbbbbbbbcccccbbbbbbbbbad###",
3675 "..#bbbbbbbbcccccccccbbbbbbbd###.",
3676 "...dbbbbbbbbbbbbbbbbbbbbbbd####.",
3677 "....dbbbbbbbbbbbbbbbbbbbbd####..",
3678 ".....dabbbbbbbbbbbbbbbbad####...",
3679 "......ddabbbbbbbbbbbbadd####....",
3680 ".......#dddabbbbbbaddd#####.....",
3681 "........###dddabbbd#######......",
3682 "..........####dbbbd#####........",
3683 ".............#dbbbd##...........",
3684 "...............dbbd##...........",
3685 "................dbd##...........",
3686 ".................dd##...........",
3687 "..................###...........",
3688 "...................##..........."};
3689
3690 static char *question_xpm[]={
3691 "32 32 6 1",
3692 ". c None",
3693 "c c #000000",
3694 "d c #0000ff",
3695 "# c #808080",
3696 "a c #c0c0c0",
3697 "b c #ffffff",
3698 "...........########.............",
3699 "........###abbbbbba###..........",
3700 "......##abbbbbbbbbbbba##........",
3701 ".....#abbbbbbbbbbbbbbbba#.......",
3702 "....#bbbbbbbbbbbbbbbbbbbbc......",
3703 "...#bbbbbbbaddddddabbbbbbbc.....",
3704 "..#bbbbbbbadabbddddabbbbbbbc....",
3705 ".#abbbbbbbddbbbbddddbbbbbbbac...",
3706 ".#bbbbbbbbddddbbddddbbbbbbbbc#..",
3707 "#abbbbbbbbddddbaddddbbbbbbbbac#.",
3708 "#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
3709 "#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
3710 "#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
3711 "#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
3712 "#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
3713 "#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
3714 ".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
3715 ".#abbbbbbbbbbddddbbbbbbbbbbac###",
3716 "..#bbbbbbbbbbddddbbbbbbbbbbc###.",
3717 "...cbbbbbbbbbaddabbbbbbbbbc####.",
3718 "....cbbbbbbbbbbbbbbbbbbbbc####..",
3719 ".....cabbbbbbbbbbbbbbbbac####...",
3720 "......ccabbbbbbbbbbbbacc####....",
3721 ".......#cccabbbbbbaccc#####.....",
3722 "........###cccabbbc#######......",
3723 "..........####cbbbc#####........",
3724 ".............#cbbbc##...........",
3725 "...............cbbc##...........",
3726 "................cbc##...........",
3727 ".................cc##...........",
3728 "..................###...........",
3729 "...................##..........."};
3730
3731 static char *warning_xpm[]={
3732 "32 32 6 1",
3733 ". c None",
3734 "c c #000000",
3735 "# c #808000",
3736 "d c #808080",
3737 "b c #c0c0c0",
3738 "a c #ffff00",
3739 ".............###................",
3740 "............#aabc...............",
3741 "...........#aaaabcd.............",
3742 "...........#aaaaacdd............",
3743 "..........#aaaaaabcdd...........",
3744 "..........#aaaaaaacdd...........",
3745 ".........#aaaaaaaabcdd..........",
3746 ".........#aaaaaaaaacdd..........",
3747 "........#aaaaaaaaaabcdd.........",
3748 "........#aaabcccbaaacdd.........",
3749 ".......#aaaacccccaaabcdd........",
3750 ".......#aaaacccccaaaacdd........",
3751 "......#aaaaacccccaaaabcdd.......",
3752 "......#aaaaacccccaaaaacdd.......",
3753 ".....#aaaaaacccccaaaaabcdd......",
3754 ".....#aaaaaa#ccc#aaaaaacdd......",
3755 "....#aaaaaaabcccbaaaaaabcdd.....",
3756 "....#aaaaaaaacccaaaaaaaacdd.....",
3757 "...#aaaaaaaaa#c#aaaaaaaabcdd....",
3758 "...#aaaaaaaaabcbaaaaaaaaacdd....",
3759 "..#aaaaaaaaaaacaaaaaaaaaabcdd...",
3760 "..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
3761 ".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
3762 ".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
3763 "#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
3764 "#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
3765 "#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
3766 "#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
3767 ".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
3768 "..#ccccccccccccccccccccccccddddd",
3769 "....ddddddddddddddddddddddddddd.",
3770 ".....ddddddddddddddddddddddddd.."};
3771
3772 wxIcon wxWin32Renderer::GetStdIcon(int which) const
3773 {
3774 switch(which)
3775 {
3776 case wxICON_INFORMATION:
3777 return wxIcon(info_xpm);
3778
3779 case wxICON_QUESTION:
3780 return wxIcon(question_xpm);
3781
3782 case wxICON_EXCLAMATION:
3783 return wxIcon(warning_xpm);
3784
3785 default:
3786 wxFAIL_MSG(wxT("requested non existent standard icon"));
3787 // still fall through
3788
3789 case wxICON_HAND:
3790 return wxIcon(error_xpm);
3791 }
3792 }
3793
3794
3795 // ----------------------------------------------------------------------------
3796 // text control geometry
3797 // ----------------------------------------------------------------------------
3798
3799 static inline int GetTextBorderWidth()
3800 {
3801 return 1;
3802 }
3803
3804 wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
3805 const wxRect& rect)
3806 {
3807 wxRect rectTotal = rect;
3808
3809 wxCoord widthBorder = GetTextBorderWidth();
3810 rectTotal.Inflate(widthBorder);
3811
3812 // this is what Windows does
3813 rectTotal.height++;
3814
3815 return rectTotal;
3816 }
3817
3818 wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
3819 const wxRect& rect,
3820 wxCoord *extraSpaceBeyond)
3821 {
3822 wxRect rectText = rect;
3823
3824 // undo GetTextTotalArea()
3825 if ( rectText.height > 0 )
3826 rectText.height--;
3827
3828 wxCoord widthBorder = GetTextBorderWidth();
3829 rectText.Inflate(-widthBorder);
3830
3831 if ( extraSpaceBeyond )
3832 *extraSpaceBeyond = 0;
3833
3834 return rectText;
3835 }
3836
3837 // ----------------------------------------------------------------------------
3838 // size adjustments
3839 // ----------------------------------------------------------------------------
3840
3841 void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
3842 {
3843 #if wxUSE_SCROLLBAR
3844 if ( wxDynamicCast(window, wxScrollBar) )
3845 {
3846 // we only set the width of vert scrollbars and height of the
3847 // horizontal ones
3848 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
3849 size->y = m_sizeScrollbarArrow.y;
3850 else
3851 size->x = m_sizeScrollbarArrow.x;
3852
3853 // skip border width adjustments, they don't make sense for us
3854 return;
3855 }
3856 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3857
3858 #if wxUSE_BUTTON
3859 if ( wxDynamicCast(window, wxButton) )
3860 {
3861 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3862 {
3863 // TODO: don't harcode all this
3864 size->x += 3*window->GetCharWidth();
3865
3866 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
3867 if ( size->y < heightBtn - 8 )
3868 size->y = heightBtn;
3869 else
3870 size->y += 9;
3871 }
3872
3873 // no border width adjustments for buttons
3874 return;
3875 }
3876 #endif // wxUSE_BUTTON
3877
3878 // take into account the border width
3879 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
3880 size->x += rectBorder.x + rectBorder.width;
3881 size->y += rectBorder.y + rectBorder.height;
3882 }
3883
3884 // ============================================================================
3885 // wxInputHandler
3886 // ============================================================================
3887
3888 // ----------------------------------------------------------------------------
3889 // wxWin32InputHandler
3890 // ----------------------------------------------------------------------------
3891
3892 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer)
3893 {
3894 m_renderer = renderer;
3895 }
3896
3897 bool wxWin32InputHandler::HandleKey(wxInputConsumer *control,
3898 const wxKeyEvent& event,
3899 bool pressed)
3900 {
3901 return FALSE;
3902 }
3903
3904 bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control,
3905 const wxMouseEvent& event)
3906 {
3907 // clicking on the control gives it focus
3908 if ( event.ButtonDown() )
3909 {
3910 wxWindow *win = control->GetInputWindow();
3911 if ( wxWindow::FindFocus() != control->GetInputWindow() )
3912 {
3913 win->SetFocus();
3914
3915 return TRUE;
3916 }
3917 }
3918
3919 return FALSE;
3920 }
3921
3922 // ----------------------------------------------------------------------------
3923 // wxWin32ScrollBarInputHandler
3924 // ----------------------------------------------------------------------------
3925
3926 wxWin32ScrollBarInputHandler::
3927 wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
3928 wxInputHandler *handler)
3929 : wxStdScrollBarInputHandler(renderer, handler)
3930 {
3931 m_scrollPaused = FALSE;
3932 m_interval = 0;
3933 }
3934
3935 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
3936 const wxControlAction& action)
3937 {
3938 // stop if went beyond the position of the original click (this can only
3939 // happen when we scroll by pages)
3940 bool stop = FALSE;
3941 if ( action == wxACTION_SCROLL_PAGE_DOWN )
3942 {
3943 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
3944 != wxHT_SCROLLBAR_BAR_2;
3945 }
3946 else if ( action == wxACTION_SCROLL_PAGE_UP )
3947 {
3948 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
3949 != wxHT_SCROLLBAR_BAR_1;
3950 }
3951
3952 if ( stop )
3953 {
3954 StopScrolling(scrollbar);
3955
3956 scrollbar->Refresh();
3957
3958 return FALSE;
3959 }
3960
3961 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
3962 }
3963
3964 bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
3965 const wxMouseEvent& event)
3966 {
3967 // remember the current state
3968 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
3969
3970 // do process the message
3971 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
3972
3973 // analyse the changes
3974 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
3975 {
3976 // we just started dragging the thumb, remember its initial position to
3977 // be able to restore it if the drag is cancelled later
3978 m_eventStartDrag = event;
3979 }
3980
3981 return rc;
3982 }
3983
3984 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
3985 const wxMouseEvent& event)
3986 {
3987 // we don't highlight scrollbar elements, so there is no need to process
3988 // mouse move events normally - only do it while mouse is captured (i.e.
3989 // when we're dragging the thumb or pressing on something)
3990 if ( !m_winCapture )
3991 return FALSE;
3992
3993 if ( event.Entering() )
3994 {
3995 // we're not interested in this at all
3996 return FALSE;
3997 }
3998
3999 wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
4000 wxHitTest ht;
4001 if ( m_scrollPaused )
4002 {
4003 // check if the mouse returned to its original location
4004
4005 if ( event.Leaving() )
4006 {
4007 // it surely didn't
4008 return FALSE;
4009 }
4010
4011 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
4012 if ( ht == m_htLast )
4013 {
4014 // yes it did, resume scrolling
4015 m_scrollPaused = FALSE;
4016 if ( m_timerScroll )
4017 {
4018 // we were scrolling by line/page, restart timer
4019 m_timerScroll->Start(m_interval);
4020
4021 Press(scrollbar, TRUE);
4022 }
4023 else // we were dragging the thumb
4024 {
4025 // restore its last location
4026 HandleThumbMove(scrollbar, m_eventLastDrag);
4027 }
4028
4029 return TRUE;
4030 }
4031 }
4032 else // normal case, scrolling hasn't been paused
4033 {
4034 // if we're scrolling the scrollbar because the arrow or the shaft was
4035 // pressed, check that the mouse stays on the same scrollbar element
4036
4037 if ( event.Moving() )
4038 {
4039 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
4040 }
4041 else // event.Leaving()
4042 {
4043 ht = wxHT_NOWHERE;
4044 }
4045
4046 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4047 // is still ok - we only want to catch the case when the mouse leaves
4048 // the scrollbar here
4049 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
4050 {
4051 ht = wxHT_SCROLLBAR_THUMB;
4052 }
4053
4054 if ( ht != m_htLast )
4055 {
4056 // what were we doing? 2 possibilities: either an arrow/shaft was
4057 // pressed in which case we have a timer and so we just stop it or
4058 // we were dragging the thumb
4059 if ( m_timerScroll )
4060 {
4061 // pause scrolling
4062 m_interval = m_timerScroll->GetInterval();
4063 m_timerScroll->Stop();
4064 m_scrollPaused = TRUE;
4065
4066 // unpress the arrow
4067 Press(scrollbar, FALSE);
4068 }
4069 else // we were dragging the thumb
4070 {
4071 // remember the current thumb position to be able to restore it
4072 // if the mouse returns to it later
4073 m_eventLastDrag = event;
4074
4075 // and restore the original position (before dragging) of the
4076 // thumb for now
4077 HandleThumbMove(scrollbar, m_eventStartDrag);
4078 }
4079
4080 return TRUE;
4081 }
4082 }
4083
4084 return wxStdScrollBarInputHandler::HandleMouseMove(control, event);
4085 }
4086
4087 // ----------------------------------------------------------------------------
4088 // wxWin32CheckboxInputHandler
4089 // ----------------------------------------------------------------------------
4090
4091 bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control,
4092 const wxKeyEvent& event,
4093 bool pressed)
4094 {
4095 if ( pressed )
4096 {
4097 wxControlAction action;
4098 int keycode = event.GetKeyCode();
4099 switch ( keycode )
4100 {
4101 case WXK_SPACE:
4102 action = wxACTION_CHECKBOX_TOGGLE;
4103 break;
4104
4105 case WXK_SUBTRACT:
4106 case WXK_NUMPAD_SUBTRACT:
4107 action = wxACTION_CHECKBOX_CHECK;
4108 break;
4109
4110 case WXK_ADD:
4111 case WXK_NUMPAD_ADD:
4112 case WXK_NUMPAD_EQUAL:
4113 action = wxACTION_CHECKBOX_CLEAR;
4114 break;
4115 }
4116
4117 if ( !!action )
4118 {
4119 control->PerformAction(action);
4120
4121 return TRUE;
4122 }
4123 }
4124
4125 return FALSE;
4126 }
4127
4128 // ----------------------------------------------------------------------------
4129 // wxWin32TextCtrlInputHandler
4130 // ----------------------------------------------------------------------------
4131
4132 bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control,
4133 const wxKeyEvent& event,
4134 bool pressed)
4135 {
4136 // handle only MSW-specific text bindings here, the others are handled in
4137 // the base class
4138 if ( pressed )
4139 {
4140 int keycode = event.GetKeyCode();
4141
4142 wxControlAction action;
4143 if ( keycode == WXK_DELETE && event.ShiftDown() )
4144 {
4145 action = wxACTION_TEXT_CUT;
4146 }
4147 else if ( keycode == WXK_INSERT )
4148 {
4149 if ( event.ControlDown() )
4150 action = wxACTION_TEXT_COPY;
4151 else if ( event.ShiftDown() )
4152 action = wxACTION_TEXT_PASTE;
4153 }
4154
4155 if ( action != wxACTION_NONE )
4156 {
4157 control->PerformAction(action);
4158
4159 return TRUE;
4160 }
4161 }
4162
4163 return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed);
4164 }
4165
4166 // ----------------------------------------------------------------------------
4167 // wxWin32StatusBarInputHandler
4168 // ----------------------------------------------------------------------------
4169
4170 wxWin32StatusBarInputHandler::
4171 wxWin32StatusBarInputHandler(wxInputHandler *handler)
4172 : wxStdInputHandler(handler)
4173 {
4174 m_isOnGrip = FALSE;
4175 }
4176
4177 bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar,
4178 const wxPoint& pt) const
4179 {
4180 if ( statbar->HasFlag(wxST_SIZEGRIP) &&
4181 statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
4182 {
4183 wxSize sizeSbar = statbar->GetSize();
4184
4185 return (sizeSbar.x - pt.x) < (wxCoord)STATUSBAR_GRIP_SIZE &&
4186 (sizeSbar.y - pt.y) < (wxCoord)STATUSBAR_GRIP_SIZE;
4187 }
4188
4189 return FALSE;
4190 }
4191
4192 bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
4193 const wxMouseEvent& event)
4194 {
4195 if ( event.Button(1) )
4196 {
4197 if ( event.ButtonDown(1) )
4198 {
4199 wxWindow *statbar = consumer->GetInputWindow();
4200
4201 if ( IsOnGrip(statbar, event.GetPosition()) )
4202 {
4203 wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
4204 wxTopLevelWindow);
4205 if ( tlw )
4206 {
4207 tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
4208 wxHT_TOPLEVEL_BORDER_SE);
4209
4210 statbar->SetCursor(m_cursorOld);
4211
4212 return TRUE;
4213 }
4214 }
4215 }
4216 }
4217
4218 return wxStdInputHandler::HandleMouse(consumer, event);
4219 }
4220
4221 bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
4222 const wxMouseEvent& event)
4223 {
4224 wxWindow *statbar = consumer->GetInputWindow();
4225
4226 bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
4227 if ( isOnGrip != m_isOnGrip )
4228 {
4229 m_isOnGrip = isOnGrip;
4230 if ( isOnGrip )
4231 {
4232 m_cursorOld = statbar->GetCursor();
4233 statbar->SetCursor(wxCURSOR_SIZENWSE);
4234 }
4235 else
4236 {
4237 statbar->SetCursor(m_cursorOld);
4238 }
4239 }
4240
4241 return wxStdInputHandler::HandleMouseMove(consumer, event);
4242 }
4243
4244 // ----------------------------------------------------------------------------
4245 // wxWin32FrameInputHandler
4246 // ----------------------------------------------------------------------------
4247
4248 bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
4249 const wxMouseEvent& event)
4250 {
4251 if ( event.LeftDClick() )
4252 {
4253 wxTopLevelWindow *tlw =
4254 wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
4255
4256 long hit = tlw->HitTest(event.GetPosition());
4257
4258 if ( hit == wxHT_TOPLEVEL_TITLEBAR )
4259 {
4260 tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
4261 tlw->IsMaximized() ?
4262 wxTOPLEVEL_BUTTON_RESTORE :
4263 wxTOPLEVEL_BUTTON_MAXIMIZE);
4264 return TRUE;
4265 }
4266 }
4267
4268 return wxStdFrameInputHandler::HandleMouse(consumer, event);
4269 }
4270