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