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