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