Three more attempts to get metal look.
[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 }
1180
1181 wxWin32Theme::~wxWin32Theme()
1182 {
1183 size_t count = m_handlers.GetCount();
1184 for ( size_t n = 0; n < count; n++ )
1185 {
1186 if ( m_handlers[n] != m_handlerDefault )
1187 delete m_handlers[n];
1188 }
1189
1190 delete m_handlerDefault;
1191
1192 delete m_renderer;
1193 delete m_scheme;
1194 }
1195
1196 wxRenderer *wxWin32Theme::GetRenderer()
1197 {
1198 if ( !m_renderer )
1199 {
1200 m_renderer = new wxWin32Renderer(GetColourScheme());
1201 }
1202
1203 return m_renderer;
1204 }
1205
1206 wxArtProvider *wxWin32Theme::GetArtProvider()
1207 {
1208 if ( !m_artProvider )
1209 {
1210 m_artProvider = new wxWin32ArtProvider;
1211 }
1212
1213 return m_artProvider;
1214 }
1215
1216 wxInputHandler *wxWin32Theme::GetDefaultInputHandler()
1217 {
1218 if ( !m_handlerDefault )
1219 {
1220 m_handlerDefault = new wxWin32InputHandler(m_renderer);
1221 }
1222
1223 return m_handlerDefault;
1224 }
1225
1226 wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control)
1227 {
1228 wxInputHandler *handler;
1229 int n = m_handlerNames.Index(control);
1230 if ( n == wxNOT_FOUND )
1231 {
1232 // create a new handler
1233 if ( control == wxINP_HANDLER_SCROLLBAR )
1234 handler = new wxWin32ScrollBarInputHandler(m_renderer,
1235 GetDefaultInputHandler());
1236 #if wxUSE_BUTTON
1237 else if ( control == wxINP_HANDLER_BUTTON )
1238 handler = new wxStdButtonInputHandler(GetDefaultInputHandler());
1239 #endif // wxUSE_BUTTON
1240 #if wxUSE_CHECKBOX
1241 else if ( control == wxINP_HANDLER_CHECKBOX )
1242 handler = new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
1243 #endif // wxUSE_CHECKBOX
1244 #if wxUSE_COMBOBOX
1245 else if ( control == wxINP_HANDLER_COMBOBOX )
1246 handler = new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1247 #endif // wxUSE_COMBOBOX
1248 #if wxUSE_LISTBOX
1249 else if ( control == wxINP_HANDLER_LISTBOX )
1250 handler = new wxStdListboxInputHandler(GetDefaultInputHandler());
1251 #endif // wxUSE_LISTBOX
1252 #if wxUSE_CHECKLISTBOX
1253 else if ( control == wxINP_HANDLER_CHECKLISTBOX )
1254 handler = new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1255 #endif // wxUSE_CHECKLISTBOX
1256 #if wxUSE_TEXTCTRL
1257 else if ( control == wxINP_HANDLER_TEXTCTRL )
1258 handler = new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1259 #endif // wxUSE_TEXTCTRL
1260 #if wxUSE_SLIDER
1261 else if ( control == wxINP_HANDLER_SLIDER )
1262 handler = new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1263 #endif // wxUSE_SLIDER
1264 #if wxUSE_SPINBTN
1265 else if ( control == wxINP_HANDLER_SPINBTN )
1266 handler = new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1267 #endif // wxUSE_SPINBTN
1268 #if wxUSE_NOTEBOOK
1269 else if ( control == wxINP_HANDLER_NOTEBOOK )
1270 handler = new wxStdNotebookInputHandler(GetDefaultInputHandler());
1271 #endif // wxUSE_NOTEBOOK
1272 #if wxUSE_STATUSBAR
1273 else if ( control == wxINP_HANDLER_STATUSBAR )
1274 handler = new wxWin32StatusBarInputHandler(GetDefaultInputHandler());
1275 #endif // wxUSE_STATUSBAR
1276 #if wxUSE_TOOLBAR
1277 else if ( control == wxINP_HANDLER_TOOLBAR )
1278 handler = new wxStdToolbarInputHandler(GetDefaultInputHandler());
1279 #endif // wxUSE_TOOLBAR
1280 else if ( control == wxINP_HANDLER_TOPLEVEL )
1281 handler = new wxWin32FrameInputHandler(GetDefaultInputHandler());
1282 else
1283 handler = GetDefaultInputHandler();
1284
1285 n = m_handlerNames.Add(control);
1286 m_handlers.Insert(handler, n);
1287 }
1288 else // we already have it
1289 {
1290 handler = m_handlers[n];
1291 }
1292
1293 return handler;
1294 }
1295
1296 wxColourScheme *wxWin32Theme::GetColourScheme()
1297 {
1298 if ( !m_scheme )
1299 {
1300 m_scheme = new wxWin32ColourScheme;
1301 }
1302 return m_scheme;
1303 }
1304
1305 // ============================================================================
1306 // wxWin32ColourScheme
1307 // ============================================================================
1308
1309 wxColour wxWin32ColourScheme::GetBackground(wxWindow *win) const
1310 {
1311 wxColour col;
1312 if ( win->UseBgCol() )
1313 {
1314 // use the user specified colour
1315 col = win->GetBackgroundColour();
1316 }
1317
1318 if ( win->IsContainerWindow() )
1319 {
1320 wxTextCtrl *text = wxDynamicCast(win, wxTextCtrl);
1321 if ( text )
1322 {
1323 if ( !text->IsEnabled() ) // not IsEditable()
1324 col = Get(CONTROL);
1325 //else: execute code below
1326 }
1327
1328 if ( !col.Ok() )
1329 {
1330 // doesn't depend on the state
1331 col = Get(WINDOW);
1332 }
1333 }
1334 else
1335 {
1336 int flags = win->GetStateFlags();
1337
1338 // the colour set by the user should be used for the normal state
1339 // and for the states for which we don't have any specific colours
1340 if ( !col.Ok() || (flags & wxCONTROL_PRESSED) != 0 )
1341 {
1342 if ( wxDynamicCast(win, wxScrollBar) )
1343 col = Get(flags & wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
1344 : SCROLLBAR);
1345 else
1346 col = Get(CONTROL);
1347 }
1348 }
1349
1350 return col;
1351 }
1352
1353 wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const
1354 {
1355 switch ( col )
1356 {
1357 // use the system colours under Windows
1358 #if defined(__WXMSW__)
1359 case WINDOW: return wxColour(GetSysColor(COLOR_WINDOW));
1360
1361 case CONTROL_PRESSED:
1362 case CONTROL_CURRENT:
1363 case CONTROL: return wxColour(GetSysColor(COLOR_BTNFACE));
1364
1365 case CONTROL_TEXT: return wxColour(GetSysColor(COLOR_BTNTEXT));
1366
1367 #if defined(COLOR_3DLIGHT)
1368 case SCROLLBAR: return wxColour(GetSysColor(COLOR_3DLIGHT));
1369 #else
1370 case SCROLLBAR: return wxColour(0xe0e0e0);
1371 #endif
1372 case SCROLLBAR_PRESSED: return wxColour(GetSysColor(COLOR_BTNTEXT));
1373
1374 case HIGHLIGHT: return wxColour(GetSysColor(COLOR_HIGHLIGHT));
1375 case HIGHLIGHT_TEXT: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT));
1376
1377 #if defined(COLOR_3DDKSHADOW)
1378 case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DDKSHADOW));
1379 #else
1380 case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DHADOW));
1381 #endif
1382
1383 case CONTROL_TEXT_DISABLED:
1384 case SHADOW_HIGHLIGHT: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT));
1385
1386 case SHADOW_IN: return wxColour(GetSysColor(COLOR_BTNFACE));
1387
1388 case CONTROL_TEXT_DISABLED_SHADOW:
1389 case SHADOW_OUT: return wxColour(GetSysColor(COLOR_BTNSHADOW));
1390
1391 case TITLEBAR: return wxColour(GetSysColor(COLOR_INACTIVECAPTION));
1392 case TITLEBAR_ACTIVE: return wxColour(GetSysColor(COLOR_ACTIVECAPTION));
1393 case TITLEBAR_TEXT: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
1394 case TITLEBAR_ACTIVE_TEXT: return wxColour(GetSysColor(COLOR_CAPTIONTEXT));
1395
1396 case DESKTOP: return wxColour(0x808000);
1397 #else // !__WXMSW__
1398 // use the standard Windows colours elsewhere
1399 case WINDOW: return *wxWHITE;
1400
1401 case CONTROL_PRESSED:
1402 case CONTROL_CURRENT:
1403 case CONTROL: return wxColour(0xc0c0c0);
1404
1405 case CONTROL_TEXT: return *wxBLACK;
1406
1407 case SCROLLBAR: return wxColour(0xe0e0e0);
1408 case SCROLLBAR_PRESSED: return *wxBLACK;
1409
1410 case HIGHLIGHT: return wxColour(0x800000);
1411 case HIGHLIGHT_TEXT: return wxColour(0xffffff);
1412
1413 case SHADOW_DARK: return *wxBLACK;
1414
1415 case CONTROL_TEXT_DISABLED:return wxColour(0xe0e0e0);
1416 case SHADOW_HIGHLIGHT: return wxColour(0xffffff);
1417
1418 case SHADOW_IN: return wxColour(0xc0c0c0);
1419
1420 case CONTROL_TEXT_DISABLED_SHADOW:
1421 case SHADOW_OUT: return wxColour(0x7f7f7f);
1422
1423 case TITLEBAR: return wxColour(0xaeaaae);
1424 case TITLEBAR_ACTIVE: return wxColour(0x820300);
1425 case TITLEBAR_TEXT: return wxColour(0xc0c0c0);
1426 case TITLEBAR_ACTIVE_TEXT:return *wxWHITE;
1427
1428 case DESKTOP: return wxColour(0x808000);
1429 #endif // __WXMSW__
1430
1431 case GAUGE: return Get(HIGHLIGHT);
1432
1433 case MAX:
1434 default:
1435 wxFAIL_MSG(_T("invalid standard colour"));
1436 return *wxBLACK;
1437 }
1438 }
1439
1440 // ============================================================================
1441 // wxWin32Renderer
1442 // ============================================================================
1443
1444 // ----------------------------------------------------------------------------
1445 // construction
1446 // ----------------------------------------------------------------------------
1447
1448 wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme)
1449 {
1450 // init data
1451 m_scheme = scheme;
1452 m_sizeScrollbarArrow = wxSize(16, 16);
1453
1454 // init colours and pens
1455 m_penBlack = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_DARK), 0, wxSOLID);
1456
1457 m_colDarkGrey = wxSCHEME_COLOUR(scheme, SHADOW_OUT);
1458 m_penDarkGrey = wxPen(m_colDarkGrey, 0, wxSOLID);
1459
1460 m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN), 0, wxSOLID);
1461
1462 m_colHighlight = wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT);
1463 m_penHighlight = wxPen(m_colHighlight, 0, wxSOLID);
1464
1465 m_titlebarFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
1466 m_titlebarFont.SetWeight(wxFONTWEIGHT_BOLD);
1467
1468 // init the arrow bitmaps
1469 static const size_t ARROW_WIDTH = 7;
1470 static const size_t ARROW_LENGTH = 4;
1471
1472 wxMask *mask;
1473 wxMemoryDC dcNormal,
1474 dcDisabled,
1475 dcInverse;
1476 for ( size_t n = 0; n < Arrow_Max; n++ )
1477 {
1478 bool isVertical = n > Arrow_Right;
1479 int w, h;
1480 if ( isVertical )
1481 {
1482 w = ARROW_WIDTH;
1483 h = ARROW_LENGTH;
1484 }
1485 else
1486 {
1487 h = ARROW_WIDTH;
1488 w = ARROW_LENGTH;
1489 }
1490
1491 // disabled arrow is larger because of the shadow
1492 m_bmpArrows[Arrow_Normal][n].Create(w, h);
1493 m_bmpArrows[Arrow_Disabled][n].Create(w + 1, h + 1);
1494
1495 dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]);
1496 dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]);
1497
1498 dcNormal.SetBackground(*wxWHITE_BRUSH);
1499 dcDisabled.SetBackground(*wxWHITE_BRUSH);
1500 dcNormal.Clear();
1501 dcDisabled.Clear();
1502
1503 dcNormal.SetPen(m_penBlack);
1504 dcDisabled.SetPen(m_penDarkGrey);
1505
1506 // calculate the position of the point of the arrow
1507 wxCoord x1, y1;
1508 if ( isVertical )
1509 {
1510 x1 = (ARROW_WIDTH - 1)/2;
1511 y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1;
1512 }
1513 else // horizontal
1514 {
1515 x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1;
1516 y1 = (ARROW_WIDTH - 1)/2;
1517 }
1518
1519 wxCoord x2 = x1,
1520 y2 = y1;
1521
1522 if ( isVertical )
1523 x2++;
1524 else
1525 y2++;
1526
1527 for ( size_t i = 0; i < ARROW_LENGTH; i++ )
1528 {
1529 dcNormal.DrawLine(x1, y1, x2, y2);
1530 dcDisabled.DrawLine(x1, y1, x2, y2);
1531
1532 if ( isVertical )
1533 {
1534 x1--;
1535 x2++;
1536
1537 if ( n == Arrow_Up )
1538 {
1539 y1++;
1540 y2++;
1541 }
1542 else // down arrow
1543 {
1544 y1--;
1545 y2--;
1546 }
1547 }
1548 else // left or right arrow
1549 {
1550 y1--;
1551 y2++;
1552
1553 if ( n == Arrow_Left )
1554 {
1555 x1++;
1556 x2++;
1557 }
1558 else
1559 {
1560 x1--;
1561 x2--;
1562 }
1563 }
1564 }
1565
1566 // draw the shadow for the disabled one
1567 dcDisabled.SetPen(m_penHighlight);
1568 switch ( n )
1569 {
1570 case Arrow_Left:
1571 y1 += 2;
1572 dcDisabled.DrawLine(x1, y1, x2, y2);
1573 break;
1574
1575 case Arrow_Right:
1576 x1 = ARROW_LENGTH - 1;
1577 y1 = (ARROW_WIDTH - 1)/2 + 1;
1578 x2 = 0;
1579 y2 = ARROW_WIDTH;
1580 dcDisabled.DrawLine(x1, y1, x2, y2);
1581 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1582 break;
1583
1584 case Arrow_Up:
1585 x1 += 2;
1586 dcDisabled.DrawLine(x1, y1, x2, y2);
1587 break;
1588
1589 case Arrow_Down:
1590 x1 = ARROW_WIDTH - 1;
1591 y1 = 1;
1592 x2 = (ARROW_WIDTH - 1)/2;
1593 y2 = ARROW_LENGTH;
1594 dcDisabled.DrawLine(x1, y1, x2, y2);
1595 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1596 break;
1597
1598 }
1599
1600 // create the inversed bitmap but only for the right arrow as we only
1601 // use it for the menus
1602 if ( n == Arrow_Right )
1603 {
1604 m_bmpArrows[Arrow_Inversed][n].Create(w, h);
1605 dcInverse.SelectObject(m_bmpArrows[Arrow_Inversed][n]);
1606 dcInverse.Clear();
1607 dcInverse.Blit(0, 0, w, h,
1608 &dcNormal, 0, 0,
1609 wxXOR);
1610 dcInverse.SelectObject(wxNullBitmap);
1611
1612 mask = new wxMask(m_bmpArrows[Arrow_Inversed][n], *wxBLACK);
1613 m_bmpArrows[Arrow_Inversed][n].SetMask(mask);
1614
1615 m_bmpArrows[Arrow_InversedDisabled][n].Create(w, h);
1616 dcInverse.SelectObject(m_bmpArrows[Arrow_InversedDisabled][n]);
1617 dcInverse.Clear();
1618 dcInverse.Blit(0, 0, w, h,
1619 &dcDisabled, 0, 0,
1620 wxXOR);
1621 dcInverse.SelectObject(wxNullBitmap);
1622
1623 mask = new wxMask(m_bmpArrows[Arrow_InversedDisabled][n], *wxBLACK);
1624 m_bmpArrows[Arrow_InversedDisabled][n].SetMask(mask);
1625 }
1626
1627 dcNormal.SelectObject(wxNullBitmap);
1628 dcDisabled.SelectObject(wxNullBitmap);
1629
1630 mask = new wxMask(m_bmpArrows[Arrow_Normal][n], *wxWHITE);
1631 m_bmpArrows[Arrow_Normal][n].SetMask(mask);
1632 mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
1633 m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
1634
1635 m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
1636 }
1637
1638 // init the frame buttons bitmaps
1639 m_bmpFrameButtons[FrameButton_Close] = wxBitmap(frame_button_close_xpm);
1640 m_bmpFrameButtons[FrameButton_Minimize] = wxBitmap(frame_button_minimize_xpm);
1641 m_bmpFrameButtons[FrameButton_Maximize] = wxBitmap(frame_button_maximize_xpm);
1642 m_bmpFrameButtons[FrameButton_Restore] = wxBitmap(frame_button_restore_xpm);
1643 m_bmpFrameButtons[FrameButton_Help] = wxBitmap(frame_button_help_xpm);
1644 }
1645
1646 // ----------------------------------------------------------------------------
1647 // border stuff
1648 // ----------------------------------------------------------------------------
1649
1650 /*
1651 The raised border in Win32 looks like this:
1652
1653 IIIIIIIIIIIIIIIIIIIIIIB
1654 I GB
1655 I GB I = white (HILIGHT)
1656 I GB H = light grey (LIGHT)
1657 I GB G = dark grey (SHADOI)
1658 I GB B = black (DKSHADOI)
1659 I GB I = hIghlight (COLOR_3DHILIGHT)
1660 I GB
1661 IGGGGGGGGGGGGGGGGGGGGGB
1662 BBBBBBBBBBBBBBBBBBBBBBB
1663
1664 The sunken border looks like this:
1665
1666 GGGGGGGGGGGGGGGGGGGGGGI
1667 GBBBBBBBBBBBBBBBBBBBBHI
1668 GB HI
1669 GB HI
1670 GB HI
1671 GB HI
1672 GB HI
1673 GB HI
1674 GHHHHHHHHHHHHHHHHHHHHHI
1675 IIIIIIIIIIIIIIIIIIIIIII
1676
1677 The static border (used for the controls which don't get focus) is like
1678 this:
1679
1680 GGGGGGGGGGGGGGGGGGGGGGW
1681 G W
1682 G W
1683 G W
1684 G W
1685 G W
1686 G W
1687 G W
1688 WWWWWWWWWWWWWWWWWWWWWWW
1689
1690 The most complicated is the double border:
1691
1692 HHHHHHHHHHHHHHHHHHHHHHB
1693 HWWWWWWWWWWWWWWWWWWWWGB
1694 HWHHHHHHHHHHHHHHHHHHHGB
1695 HWH HGB
1696 HWH HGB
1697 HWH HGB
1698 HWH HGB
1699 HWHHHHHHHHHHHHHHHHHHHGB
1700 HGGGGGGGGGGGGGGGGGGGGGB
1701 BBBBBBBBBBBBBBBBBBBBBBB
1702
1703 And the simple border is, well, simple:
1704
1705 BBBBBBBBBBBBBBBBBBBBBBB
1706 B B
1707 B B
1708 B B
1709 B B
1710 B B
1711 B B
1712 B B
1713 B B
1714 BBBBBBBBBBBBBBBBBBBBBBB
1715 */
1716
1717 void wxWin32Renderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1718 {
1719 // draw
1720 dc.SetPen(pen);
1721 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1722 dc.DrawRectangle(*rect);
1723
1724 // adjust the rect
1725 rect->Inflate(-1);
1726 }
1727
1728 void wxWin32Renderer::DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1729 {
1730 // draw the bottom and right sides
1731 dc.SetPen(pen);
1732 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1733 rect->GetRight() + 1, rect->GetBottom());
1734 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1735 rect->GetRight(), rect->GetBottom());
1736
1737 // adjust the rect
1738 rect->width--;
1739 rect->height--;
1740 }
1741
1742 void wxWin32Renderer::DrawShadedRect(wxDC& dc, wxRect *rect,
1743 const wxPen& pen1, const wxPen& pen2)
1744 {
1745 // draw the rectangle
1746 dc.SetPen(pen1);
1747 dc.DrawLine(rect->GetLeft(), rect->GetTop(),
1748 rect->GetLeft(), rect->GetBottom());
1749 dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
1750 rect->GetRight(), rect->GetTop());
1751 dc.SetPen(pen2);
1752 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1753 rect->GetRight(), rect->GetBottom());
1754 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1755 rect->GetRight() + 1, rect->GetBottom());
1756
1757 // adjust the rect
1758 rect->Inflate(-1);
1759 }
1760
1761 void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxRect *rect)
1762 {
1763 DrawShadedRect(dc, rect, m_penHighlight, m_penBlack);
1764 DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
1765 }
1766
1767 void wxWin32Renderer::DrawSunkenBorder(wxDC& dc, wxRect *rect)
1768 {
1769 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
1770 DrawShadedRect(dc, rect, m_penBlack, m_penLightGrey);
1771 }
1772
1773 void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
1774 {
1775 if ( isPressed )
1776 {
1777 DrawRect(dc, rect, m_penDarkGrey);
1778
1779 // the arrow is usually drawn inside border of width 2 and is offset by
1780 // another pixel in both directions when it's pressed - as the border
1781 // in this case is more narrow as well, we have to adjust rect like
1782 // this:
1783 rect->Inflate(-1);
1784 rect->x++;
1785 rect->y++;
1786 }
1787 else
1788 {
1789 DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
1790 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
1791 }
1792 }
1793
1794 void wxWin32Renderer::DrawBorder(wxDC& dc,
1795 wxBorder border,
1796 const wxRect& rectTotal,
1797 int WXUNUSED(flags),
1798 wxRect *rectIn)
1799 {
1800 int i;
1801
1802 wxRect rect = rectTotal;
1803
1804 switch ( border )
1805 {
1806 case wxBORDER_SUNKEN:
1807 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1808 {
1809 DrawSunkenBorder(dc, &rect);
1810 }
1811 break;
1812
1813 case wxBORDER_STATIC:
1814 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1815 break;
1816
1817 case wxBORDER_RAISED:
1818 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1819 {
1820 DrawRaisedBorder(dc, &rect);
1821 }
1822 break;
1823
1824 case wxBORDER_DOUBLE:
1825 DrawArrowBorder(dc, &rect);
1826 DrawRect(dc, &rect, m_penLightGrey);
1827 break;
1828
1829 case wxBORDER_SIMPLE:
1830 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1831 {
1832 DrawRect(dc, &rect, m_penBlack);
1833 }
1834 break;
1835
1836 default:
1837 wxFAIL_MSG(_T("unknown border type"));
1838 // fall through
1839
1840 case wxBORDER_DEFAULT:
1841 case wxBORDER_NONE:
1842 break;
1843 }
1844
1845 if ( rectIn )
1846 *rectIn = rect;
1847 }
1848
1849 wxRect wxWin32Renderer::GetBorderDimensions(wxBorder border) const
1850 {
1851 wxCoord width;
1852 switch ( border )
1853 {
1854 case wxBORDER_RAISED:
1855 case wxBORDER_SUNKEN:
1856 width = BORDER_THICKNESS;
1857 break;
1858
1859 case wxBORDER_SIMPLE:
1860 case wxBORDER_STATIC:
1861 width = 1;
1862 break;
1863
1864 case wxBORDER_DOUBLE:
1865 width = 3;
1866 break;
1867
1868 default:
1869 {
1870 // char *crash = NULL;
1871 // *crash = 0;
1872 wxFAIL_MSG(_T("unknown border type"));
1873 // fall through
1874 }
1875
1876 case wxBORDER_DEFAULT:
1877 case wxBORDER_NONE:
1878 width = 0;
1879 break;
1880 }
1881
1882 wxRect rect;
1883 rect.x =
1884 rect.y =
1885 rect.width =
1886 rect.height = width;
1887
1888 return rect;
1889 }
1890
1891 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1892 {
1893 return TRUE;
1894 }
1895
1896 // ----------------------------------------------------------------------------
1897 // borders
1898 // ----------------------------------------------------------------------------
1899
1900 void wxWin32Renderer::DrawTextBorder(wxDC& dc,
1901 wxBorder border,
1902 const wxRect& rect,
1903 int flags,
1904 wxRect *rectIn)
1905 {
1906 // text controls are not special under windows
1907 DrawBorder(dc, border, rect, flags, rectIn);
1908 }
1909
1910 void wxWin32Renderer::DrawButtonBorder(wxDC& dc,
1911 const wxRect& rectTotal,
1912 int flags,
1913 wxRect *rectIn)
1914 {
1915 wxRect rect = rectTotal;
1916
1917 if ( flags & wxCONTROL_PRESSED )
1918 {
1919 // button pressed: draw a double border around it
1920 DrawRect(dc, &rect, m_penBlack);
1921 DrawRect(dc, &rect, m_penDarkGrey);
1922 }
1923 else
1924 {
1925 // button not pressed
1926
1927 if ( flags & (wxCONTROL_FOCUSED | wxCONTROL_ISDEFAULT) )
1928 {
1929 // button either default or focused (or both): add an extra border around it
1930 DrawRect(dc, &rect, m_penBlack);
1931 }
1932
1933 // now draw a normal button
1934 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
1935 DrawHalfRect(dc, &rect, m_penDarkGrey);
1936 }
1937
1938 if ( rectIn )
1939 {
1940 *rectIn = rect;
1941 }
1942 }
1943
1944 // ----------------------------------------------------------------------------
1945 // lines and frame
1946 // ----------------------------------------------------------------------------
1947
1948 void wxWin32Renderer::DrawHorizontalLine(wxDC& dc,
1949 wxCoord y, wxCoord x1, wxCoord x2)
1950 {
1951 dc.SetPen(m_penDarkGrey);
1952 dc.DrawLine(x1, y, x2 + 1, y);
1953 dc.SetPen(m_penHighlight);
1954 y++;
1955 dc.DrawLine(x1, y, x2 + 1, y);
1956 }
1957
1958 void wxWin32Renderer::DrawVerticalLine(wxDC& dc,
1959 wxCoord x, wxCoord y1, wxCoord y2)
1960 {
1961 dc.SetPen(m_penDarkGrey);
1962 dc.DrawLine(x, y1, x, y2 + 1);
1963 dc.SetPen(m_penHighlight);
1964 x++;
1965 dc.DrawLine(x, y1, x, y2 + 1);
1966 }
1967
1968 void wxWin32Renderer::DrawFrame(wxDC& dc,
1969 const wxString& label,
1970 const wxRect& rect,
1971 int flags,
1972 int alignment,
1973 int indexAccel)
1974 {
1975 wxCoord height = 0; // of the label
1976 wxRect rectFrame = rect;
1977 if ( !label.empty() )
1978 {
1979 // the text should touch the top border of the rect, so the frame
1980 // itself should be lower
1981 dc.GetTextExtent(label, NULL, &height);
1982 rectFrame.y += height / 2;
1983 rectFrame.height -= height / 2;
1984
1985 // we have to draw each part of the frame individually as we can't
1986 // erase the background beyond the label as it might contain some
1987 // pixmap already, so drawing everything and then overwriting part of
1988 // the frame with label doesn't work
1989
1990 // TODO: the +5 and space insertion should be customizable
1991
1992 wxRect rectText;
1993 rectText.x = rectFrame.x + 5;
1994 rectText.y = rect.y;
1995 rectText.width = rectFrame.width - 7; // +2 border width
1996 rectText.height = height;
1997
1998 wxString label2;
1999 label2 << _T(' ') << label << _T(' ');
2000 if ( indexAccel != -1 )
2001 {
2002 // adjust it as we prepended a space
2003 indexAccel++;
2004 }
2005
2006 wxRect rectLabel;
2007 DrawLabel(dc, label2, rectText, flags, alignment, indexAccel, &rectLabel);
2008
2009 StandardDrawFrame(dc, rectFrame, rectLabel);
2010 }
2011 else
2012 {
2013 // just draw the complete frame
2014 DrawShadedRect(dc, &rectFrame, m_penDarkGrey, m_penHighlight);
2015 DrawShadedRect(dc, &rectFrame, m_penHighlight, m_penDarkGrey);
2016 }
2017 }
2018
2019 // ----------------------------------------------------------------------------
2020 // label
2021 // ----------------------------------------------------------------------------
2022
2023 void wxWin32Renderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
2024 {
2025 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
2026 // pixels each while we really need dots here... PS_ALTERNATE might
2027 // work, but it is for NT 5 only
2028 #if 0
2029 DrawRect(dc, &rect, wxPen(*wxBLACK, 0, wxDOT));
2030 #else
2031 // draw the pixels manually: note that to behave in the same manner as
2032 // DrawRect(), we must exclude the bottom and right borders from the
2033 // rectangle
2034 wxCoord x1 = rect.GetLeft(),
2035 y1 = rect.GetTop(),
2036 x2 = rect.GetRight(),
2037 y2 = rect.GetBottom();
2038
2039 dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID));
2040
2041 // this seems to be closer than what Windows does than wxINVERT although
2042 // I'm still not sure if it's correct
2043 dc.SetLogicalFunction(wxAND_REVERSE);
2044
2045 wxCoord z;
2046 for ( z = x1 + 1; z < x2; z += 2 )
2047 dc.DrawPoint(z, rect.GetTop());
2048
2049 wxCoord shift = z == x2 ? 0 : 1;
2050 for ( z = y1 + shift; z < y2; z += 2 )
2051 dc.DrawPoint(x2, z);
2052
2053 shift = z == y2 ? 0 : 1;
2054 for ( z = x2 - shift; z > x1; z -= 2 )
2055 dc.DrawPoint(z, y2);
2056
2057 shift = z == x1 ? 0 : 1;
2058 for ( z = y2 - shift; z > y1; z -= 2 )
2059 dc.DrawPoint(x1, z);
2060
2061 dc.SetLogicalFunction(wxCOPY);
2062 #endif // 0/1
2063 }
2064
2065 void wxWin32Renderer::DrawLabelShadow(wxDC& dc,
2066 const wxString& label,
2067 const wxRect& rect,
2068 int alignment,
2069 int indexAccel)
2070 {
2071 // draw shadow of the text
2072 dc.SetTextForeground(m_colHighlight);
2073 wxRect rectShadow = rect;
2074 rectShadow.x++;
2075 rectShadow.y++;
2076 dc.DrawLabel(label, rectShadow, alignment, indexAccel);
2077
2078 // make the text grey
2079 dc.SetTextForeground(m_colDarkGrey);
2080 }
2081
2082 void wxWin32Renderer::DrawLabel(wxDC& dc,
2083 const wxString& label,
2084 const wxRect& rect,
2085 int flags,
2086 int alignment,
2087 int indexAccel,
2088 wxRect *rectBounds)
2089 {
2090 DoDrawLabel(dc, label, rect, flags, alignment, indexAccel, rectBounds);
2091 }
2092
2093 void wxWin32Renderer::DoDrawLabel(wxDC& dc,
2094 const wxString& label,
2095 const wxRect& rect,
2096 int flags,
2097 int alignment,
2098 int indexAccel,
2099 wxRect *rectBounds,
2100 const wxPoint& focusOffset)
2101 {
2102 // the underscores are not drawn for focused controls in wxMSW
2103 if ( flags & wxCONTROL_FOCUSED )
2104 {
2105 indexAccel = -1;
2106 }
2107
2108 if ( flags & wxCONTROL_DISABLED )
2109 {
2110 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2111 // currently only can happen for a menu item and it seems that Windows
2112 // doesn't draw the shadow in this case, so we don't do it neither
2113 if ( flags & wxCONTROL_SELECTED )
2114 {
2115 // just make the label text greyed out
2116 dc.SetTextForeground(m_colDarkGrey);
2117 }
2118 else // draw normal disabled label
2119 {
2120 DrawLabelShadow(dc, label, rect, alignment, indexAccel);
2121 }
2122 }
2123
2124 wxRect rectLabel;
2125 dc.DrawLabel(label, wxNullBitmap, rect, alignment, indexAccel, &rectLabel);
2126
2127 if ( flags & wxCONTROL_DISABLED )
2128 {
2129 // restore the fg colour
2130 dc.SetTextForeground(*wxBLACK);
2131 }
2132
2133 if ( flags & wxCONTROL_FOCUSED )
2134 {
2135 if ( focusOffset.x || focusOffset.y )
2136 {
2137 rectLabel.Inflate(focusOffset.x, focusOffset.y);
2138 }
2139
2140 DrawFocusRect(dc, rectLabel);
2141 }
2142
2143 if ( rectBounds )
2144 *rectBounds = rectLabel;
2145 }
2146
2147 void wxWin32Renderer::DrawButtonLabel(wxDC& dc,
2148 const wxString& label,
2149 const wxBitmap& image,
2150 const wxRect& rect,
2151 int flags,
2152 int alignment,
2153 int indexAccel,
2154 wxRect *rectBounds)
2155 {
2156 // the underscores are not drawn for focused controls in wxMSW
2157 if ( flags & wxCONTROL_PRESSED )
2158 {
2159 indexAccel = -1;
2160 }
2161
2162 wxRect rectLabel = rect;
2163 if ( !label.empty() )
2164 {
2165 // shift the label if a button is pressed
2166 if ( flags & wxCONTROL_PRESSED )
2167 {
2168 rectLabel.x++;
2169 rectLabel.y++;
2170 }
2171
2172 if ( flags & wxCONTROL_DISABLED )
2173 {
2174 DrawLabelShadow(dc, label, rectLabel, alignment, indexAccel);
2175 }
2176
2177 // leave enough space for the focus rectangle
2178 if ( flags & wxCONTROL_FOCUSED )
2179 {
2180 rectLabel.Inflate(-2);
2181 }
2182 }
2183
2184 dc.DrawLabel(label, image, rectLabel, alignment, indexAccel, rectBounds);
2185
2186 if ( !label.empty() && (flags & wxCONTROL_FOCUSED) )
2187 {
2188 if ( flags & wxCONTROL_PRESSED )
2189 {
2190 // the focus rectangle is never pressed, so undo the shift done
2191 // above
2192 rectLabel.x--;
2193 rectLabel.y--;
2194 rectLabel.width--;
2195 rectLabel.height--;
2196 }
2197
2198 DrawFocusRect(dc, rectLabel);
2199 }
2200 }
2201
2202 // ----------------------------------------------------------------------------
2203 // (check)listbox items
2204 // ----------------------------------------------------------------------------
2205
2206 void wxWin32Renderer::DrawItem(wxDC& dc,
2207 const wxString& label,
2208 const wxRect& rect,
2209 int flags)
2210 {
2211 wxDCTextColourChanger colChanger(dc);
2212
2213 if ( flags & wxCONTROL_SELECTED )
2214 {
2215 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2216
2217 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2218 dc.SetBrush(wxBrush(colBg, wxSOLID));
2219 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2220 dc.DrawRectangle(rect);
2221 }
2222
2223 wxRect rectText = rect;
2224 rectText.x += 2;
2225 rectText.width -= 2;
2226 dc.DrawLabel(label, wxNullBitmap, rectText);
2227
2228 if ( flags & wxCONTROL_FOCUSED )
2229 {
2230 DrawFocusRect(dc, rect);
2231 }
2232 }
2233
2234 void wxWin32Renderer::DrawCheckItem(wxDC& dc,
2235 const wxString& label,
2236 const wxBitmap& bitmap,
2237 const wxRect& rect,
2238 int flags)
2239 {
2240 wxBitmap bmp;
2241 if ( bitmap.Ok() )
2242 {
2243 bmp = bitmap;
2244 }
2245 else // use default bitmap
2246 {
2247 IndicatorStatus i = flags & wxCONTROL_CHECKED
2248 ? IndicatorStatus_Checked
2249 : IndicatorStatus_Unchecked;
2250
2251 if ( !m_bmpCheckBitmaps[i].Ok() )
2252 {
2253 m_bmpCheckBitmaps[i] = wxBitmap(xpmChecked[i]);
2254 }
2255
2256 bmp = m_bmpCheckBitmaps[i];
2257 }
2258
2259 dc.DrawBitmap(bmp, rect.x, rect.y + (rect.height - bmp.GetHeight()) / 2 - 1,
2260 TRUE /* use mask */);
2261
2262 wxRect rectLabel = rect;
2263 int bmpWidth = bmp.GetWidth();
2264 rectLabel.x += bmpWidth;
2265 rectLabel.width -= bmpWidth;
2266
2267 DrawItem(dc, label, rectLabel, flags);
2268 }
2269
2270 // ----------------------------------------------------------------------------
2271 // check/radio buttons
2272 // ----------------------------------------------------------------------------
2273
2274 wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags)
2275 {
2276 IndicatorState indState;
2277 if ( flags & wxCONTROL_SELECTED )
2278 indState = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
2279 : IndicatorState_Selected;
2280 else if ( flags & wxCONTROL_DISABLED )
2281 indState = IndicatorState_Disabled;
2282 else if ( flags & wxCONTROL_PRESSED )
2283 indState = IndicatorState_Pressed;
2284 else
2285 indState = IndicatorState_Normal;
2286
2287 IndicatorStatus indStatus = flags & wxCONTROL_CHECKED
2288 ? IndicatorStatus_Checked
2289 : IndicatorStatus_Unchecked;
2290
2291 wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus];
2292 if ( !bmp.Ok() )
2293 {
2294 const char **xpm = xpmIndicators[indType][indState][indStatus];
2295 if ( xpm )
2296 {
2297 // create and cache it
2298 bmp = wxBitmap(xpm);
2299 m_bmpIndicators[indType][indState][indStatus] = bmp;
2300 }
2301 }
2302
2303 return bmp;
2304 }
2305
2306 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc,
2307 const wxString& label,
2308 const wxBitmap& bitmap,
2309 const wxRect& rect,
2310 int flags,
2311 wxAlignment align,
2312 int indexAccel,
2313 wxCoord focusOffsetY)
2314 {
2315 // calculate the position of the bitmap and of the label
2316 wxCoord heightBmp = bitmap.GetHeight();
2317 wxCoord xBmp,
2318 yBmp = rect.y + (rect.height - heightBmp) / 2;
2319
2320 wxRect rectLabel;
2321 dc.GetMultiLineTextExtent(label, NULL, &rectLabel.height);
2322 rectLabel.y = rect.y + (rect.height - rectLabel.height) / 2;
2323
2324 // align label vertically with the bitmap - looks nicer like this
2325 rectLabel.y -= (rectLabel.height - heightBmp) % 2;
2326
2327 // calc horz position
2328 if ( align == wxALIGN_RIGHT )
2329 {
2330 xBmp = rect.GetRight() - bitmap.GetWidth();
2331 rectLabel.x = rect.x + 3;
2332 rectLabel.SetRight(xBmp);
2333 }
2334 else // normal (checkbox to the left of the text) case
2335 {
2336 xBmp = rect.x;
2337 rectLabel.x = xBmp + bitmap.GetWidth() + 5;
2338 rectLabel.SetRight(rect.GetRight());
2339 }
2340
2341 dc.DrawBitmap(bitmap, xBmp, yBmp, TRUE /* use mask */);
2342
2343 DoDrawLabel(
2344 dc, label, rectLabel,
2345 flags,
2346 wxALIGN_LEFT | wxALIGN_TOP,
2347 indexAccel,
2348 NULL, // we don't need bounding rect
2349 // use custom vert focus rect offset
2350 wxPoint(FOCUS_RECT_OFFSET_X, focusOffsetY)
2351 );
2352 }
2353
2354 void wxWin32Renderer::DrawRadioButton(wxDC& dc,
2355 const wxString& label,
2356 const wxBitmap& bitmap,
2357 const wxRect& rect,
2358 int flags,
2359 wxAlignment align,
2360 int indexAccel)
2361 {
2362 wxBitmap bmp;
2363 if ( bitmap.Ok() )
2364 bmp = bitmap;
2365 else
2366 bmp = GetRadioBitmap(flags);
2367
2368 DrawCheckOrRadioButton(dc, label,
2369 bmp,
2370 rect, flags, align, indexAccel,
2371 FOCUS_RECT_OFFSET_Y); // default focus rect offset
2372 }
2373
2374 void wxWin32Renderer::DrawCheckButton(wxDC& dc,
2375 const wxString& label,
2376 const wxBitmap& bitmap,
2377 const wxRect& rect,
2378 int flags,
2379 wxAlignment align,
2380 int indexAccel)
2381 {
2382 wxBitmap bmp;
2383 if ( bitmap.Ok() )
2384 bmp = bitmap;
2385 else
2386 bmp = GetCheckBitmap(flags);
2387
2388 DrawCheckOrRadioButton(dc, label,
2389 bmp,
2390 rect, flags, align, indexAccel,
2391 0); // no focus rect offset for checkboxes
2392 }
2393
2394 void wxWin32Renderer::DrawToolBarButton(wxDC& dc,
2395 const wxString& label,
2396 const wxBitmap& bitmap,
2397 const wxRect& rectOrig,
2398 int flags)
2399 {
2400 if ( !label.empty() || bitmap.Ok() )
2401 {
2402 wxRect rect = rectOrig;
2403 rect.Deflate(BORDER_THICKNESS);
2404
2405 if ( flags & wxCONTROL_PRESSED )
2406 {
2407 DrawBorder(dc, wxBORDER_SUNKEN, rect, flags);
2408 }
2409 else if ( flags & wxCONTROL_CURRENT )
2410 {
2411 DrawBorder(dc, wxBORDER_RAISED, rect, flags);
2412 }
2413
2414 dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
2415 }
2416 else // a separator
2417 {
2418 // leave a small gap aroudn the line, also account for the toolbar
2419 // border itself
2420 DrawVerticalLine(dc, rectOrig.x + rectOrig.width/2,
2421 rectOrig.y + 2*BORDER_THICKNESS,
2422 rectOrig.GetBottom() - BORDER_THICKNESS);
2423 }
2424 }
2425
2426 // ----------------------------------------------------------------------------
2427 // text control
2428 // ----------------------------------------------------------------------------
2429
2430 void wxWin32Renderer::DrawTextLine(wxDC& dc,
2431 const wxString& text,
2432 const wxRect& rect,
2433 int selStart,
2434 int selEnd,
2435 int flags)
2436 {
2437 // nothing special to do here
2438 StandardDrawTextLine(dc, text, rect, selStart, selEnd, flags);
2439 }
2440
2441 void wxWin32Renderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
2442 {
2443 // we don't draw them
2444 }
2445
2446 // ----------------------------------------------------------------------------
2447 // notebook
2448 // ----------------------------------------------------------------------------
2449
2450 void wxWin32Renderer::DrawTab(wxDC& dc,
2451 const wxRect& rectOrig,
2452 wxDirection dir,
2453 const wxString& label,
2454 const wxBitmap& bitmap,
2455 int flags,
2456 int indexAccel)
2457 {
2458 wxRect rect = rectOrig;
2459
2460 // the current tab is drawn indented (to the top for default case) and
2461 // bigger than the other ones
2462 const wxSize indent = GetTabIndent();
2463 if ( flags & wxCONTROL_SELECTED )
2464 {
2465 switch ( dir )
2466 {
2467 default:
2468 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2469 // fall through
2470
2471 case wxTOP:
2472 rect.Inflate(indent.x, 0);
2473 rect.y -= indent.y;
2474 rect.height += indent.y;
2475 break;
2476
2477 case wxBOTTOM:
2478 rect.Inflate(indent.x, 0);
2479 rect.height += indent.y;
2480 break;
2481
2482 case wxLEFT:
2483 case wxRIGHT:
2484 wxFAIL_MSG(_T("TODO"));
2485 break;
2486 }
2487 }
2488
2489 // draw the text, image and the focus around them (if necessary)
2490 wxRect rectLabel = rect;
2491 rectLabel.Deflate(1, 1);
2492 DrawButtonLabel(dc, label, bitmap, rectLabel,
2493 flags, wxALIGN_CENTRE, indexAccel);
2494
2495 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2496 static const wxCoord CUTOFF = 2; // radius of the rounded corner
2497 wxCoord x = rect.x,
2498 y = rect.y,
2499 x2 = rect.GetRight(),
2500 y2 = rect.GetBottom();
2501
2502 // FIXME: all this code will break if the tab indent or the border width,
2503 // it is tied to the fact that both of them are equal to 2
2504 switch ( dir )
2505 {
2506 default:
2507 case wxTOP:
2508 dc.SetPen(m_penHighlight);
2509 dc.DrawLine(x, y2, x, y + CUTOFF);
2510 dc.DrawLine(x, y + CUTOFF, x + CUTOFF, y);
2511 dc.DrawLine(x + CUTOFF, y, x2 - CUTOFF + 1, y);
2512
2513 dc.SetPen(m_penBlack);
2514 dc.DrawLine(x2, y2, x2, y + CUTOFF);
2515 dc.DrawLine(x2, y + CUTOFF, x2 - CUTOFF, y);
2516
2517 dc.SetPen(m_penDarkGrey);
2518 dc.DrawLine(x2 - 1, y2, x2 - 1, y + CUTOFF - 1);
2519
2520 if ( flags & wxCONTROL_SELECTED )
2521 {
2522 dc.SetPen(m_penLightGrey);
2523
2524 // overwrite the part of the border below this tab
2525 dc.DrawLine(x + 1, y2 + 1, x2 - 1, y2 + 1);
2526
2527 // and the shadow of the tab to the left of us
2528 dc.DrawLine(x + 1, y + CUTOFF + 1, x + 1, y2 + 1);
2529 }
2530 break;
2531
2532 case wxBOTTOM:
2533 dc.SetPen(m_penHighlight);
2534 // we need to continue one pixel further to overwrite the corner of
2535 // the border for the selected tab
2536 dc.DrawLine(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0),
2537 x, y2 - CUTOFF);
2538 dc.DrawLine(x, y2 - CUTOFF, x + CUTOFF, y2);
2539
2540 dc.SetPen(m_penBlack);
2541 dc.DrawLine(x + CUTOFF, y2, x2 - CUTOFF + 1, y2);
2542 dc.DrawLine(x2, y, x2, y2 - CUTOFF);
2543 dc.DrawLine(x2, y2 - CUTOFF, x2 - CUTOFF, y2);
2544
2545 dc.SetPen(m_penDarkGrey);
2546 dc.DrawLine(x + CUTOFF, y2 - 1, x2 - CUTOFF + 1, y2 - 1);
2547 dc.DrawLine(x2 - 1, y, x2 - 1, y2 - CUTOFF + 1);
2548
2549 if ( flags & wxCONTROL_SELECTED )
2550 {
2551 dc.SetPen(m_penLightGrey);
2552
2553 // overwrite the part of the (double!) border above this tab
2554 dc.DrawLine(x + 1, y - 1, x2 - 1, y - 1);
2555 dc.DrawLine(x + 1, y - 2, x2 - 1, y - 2);
2556
2557 // and the shadow of the tab to the left of us
2558 dc.DrawLine(x + 1, y2 - CUTOFF, x + 1, y - 1);
2559 }
2560 break;
2561
2562 case wxLEFT:
2563 case wxRIGHT:
2564 wxFAIL_MSG(_T("TODO"));
2565 }
2566 }
2567
2568 // ----------------------------------------------------------------------------
2569 // slider
2570 // ----------------------------------------------------------------------------
2571
2572 wxSize wxWin32Renderer::GetSliderThumbSize(const wxRect& rect,
2573 wxOrientation orient) const
2574 {
2575 wxSize size;
2576
2577 wxRect rectShaft = GetSliderShaftRect(rect, orient);
2578 if ( orient == wxHORIZONTAL )
2579 {
2580 size.y = rect.height - 6;
2581 size.x = wxMin(size.y / 2, rectShaft.width);
2582 }
2583 else // vertical
2584 {
2585 size.x = rect.width - 6;
2586 size.y = wxMin(size.x / 2, rectShaft.height);
2587 }
2588
2589 return size;
2590 }
2591
2592 wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
2593 wxOrientation orient) const
2594 {
2595 static const wxCoord SLIDER_MARGIN = 6;
2596
2597 wxRect rect = rectOrig;
2598
2599 if ( orient == wxHORIZONTAL )
2600 {
2601 // make the rect of minimal width and centre it
2602 rect.height = 2*BORDER_THICKNESS;
2603 rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
2604 if ( rect.y < 0 )
2605 rect.y = 0;
2606
2607 // leave margins on the sides
2608 rect.Deflate(SLIDER_MARGIN, 0);
2609 }
2610 else // vertical
2611 {
2612 // same as above but in other direction
2613 rect.width = 2*BORDER_THICKNESS;
2614 rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
2615 if ( rect.x < 0 )
2616 rect.x = 0;
2617
2618 rect.Deflate(0, SLIDER_MARGIN);
2619 }
2620
2621 return rect;
2622 }
2623
2624 void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
2625 const wxRect& rectOrig,
2626 wxOrientation orient,
2627 int flags,
2628 wxRect *rectShaft)
2629 {
2630 if ( flags & wxCONTROL_FOCUSED )
2631 {
2632 DrawFocusRect(dc, rectOrig);
2633 }
2634
2635 wxRect rect = GetSliderShaftRect(rectOrig, orient);
2636
2637 if ( rectShaft )
2638 *rectShaft = rect;
2639
2640 DrawSunkenBorder(dc, &rect);
2641 }
2642
2643 void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
2644 const wxRect& rect,
2645 wxOrientation orient,
2646 int flags)
2647 {
2648 /*
2649 we are drawing a shape of this form
2650
2651 HHHHHHB <--- y
2652 H DB
2653 H DB
2654 H DB where H is hightlight colour
2655 H DB D dark grey
2656 H DB B black
2657 H DB
2658 H DB <--- y3
2659 H DB
2660 HDB
2661 B <--- y2
2662
2663 ^ ^ ^
2664 | | |
2665 x x3 x2
2666
2667 The interior of this shape is filled with the hatched brush if the thumb
2668 is pressed.
2669 */
2670
2671 DrawBackground(dc, wxNullColour, rect, flags);
2672
2673 bool transpose = orient == wxVERTICAL;
2674
2675 wxCoord x, y, x2, y2;
2676 if ( transpose )
2677 {
2678 x = rect.y;
2679 y = rect.x;
2680 x2 = rect.GetBottom();
2681 y2 = rect.GetRight();
2682 }
2683 else
2684 {
2685 x = rect.x;
2686 y = rect.y;
2687 x2 = rect.GetRight();
2688 y2 = rect.GetBottom();
2689 }
2690
2691 // the size of the pointed part of the thumb
2692 wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
2693
2694 wxCoord x3 = x + sizeArrow,
2695 y3 = y2 - sizeArrow;
2696
2697 dc.SetPen(m_penHighlight);
2698 DrawLine(dc, x, y, x2, y, transpose);
2699 DrawLine(dc, x, y + 1, x, y2 - sizeArrow, transpose);
2700 DrawLine(dc, x, y3, x3, y2, transpose);
2701
2702 dc.SetPen(m_penBlack);
2703 DrawLine(dc, x3, y2, x2, y3, transpose);
2704 DrawLine(dc, x2, y3, x2, y - 1, transpose);
2705
2706 dc.SetPen(m_penDarkGrey);
2707 DrawLine(dc, x3, y2 - 1, x2 - 1, y3, transpose);
2708 DrawLine(dc, x2 - 1, y3, x2 - 1, y, transpose);
2709
2710 if ( flags & wxCONTROL_PRESSED )
2711 {
2712 // TODO: MSW fills the entire area inside, not just the rect
2713 wxRect rectInt = rect;
2714 if ( transpose )
2715 rectInt.SetRight(y3);
2716 else
2717 rectInt.SetBottom(y3);
2718 rectInt.Deflate(2);
2719
2720 #if !defined(__WXMGL__)
2721 static const char *stipple_xpm[] = {
2722 /* columns rows colors chars-per-pixel */
2723 "2 2 2 1",
2724 " c None",
2725 "w c white",
2726 /* pixels */
2727 "w ",
2728 " w",
2729 };
2730 #else
2731 // VS: MGL can only do 8x8 stipple brushes
2732 static const char *stipple_xpm[] = {
2733 /* columns rows colors chars-per-pixel */
2734 "8 8 2 1",
2735 " c None",
2736 "w c white",
2737 /* pixels */
2738 "w w w w ",
2739 " w w w w",
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 };
2747 #endif
2748 dc.SetBrush(wxBrush(stipple_xpm));
2749
2750 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
2751 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
2752 dc.SetPen(*wxTRANSPARENT_PEN);
2753 dc.DrawRectangle(rectInt);
2754 }
2755 }
2756
2757 void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
2758 const wxRect& rect,
2759 const wxSize& sizeThumb,
2760 wxOrientation orient,
2761 int start,
2762 int end,
2763 int step,
2764 int flags)
2765 {
2766 if ( end == start )
2767 {
2768 // empty slider?
2769 return;
2770 }
2771
2772 // the variable names correspond to horizontal case, but they can be used
2773 // for both orientations
2774 wxCoord x1, x2, y1, y2, len, widthThumb;
2775 if ( orient == wxHORIZONTAL )
2776 {
2777 x1 = rect.GetLeft();
2778 x2 = rect.GetRight();
2779
2780 // draw from bottom to top to leave one pixel space between the ticks
2781 // and the slider as Windows do
2782 y1 = rect.GetBottom();
2783 y2 = rect.GetTop();
2784
2785 len = rect.width;
2786
2787 widthThumb = sizeThumb.x;
2788 }
2789 else // vertical
2790 {
2791 x1 = rect.GetTop();
2792 x2 = rect.GetBottom();
2793
2794 y1 = rect.GetRight();
2795 y2 = rect.GetLeft();
2796
2797 len = rect.height;
2798
2799 widthThumb = sizeThumb.y;
2800 }
2801
2802 // the first tick should be positioned in such way that a thumb drawn in
2803 // the first position points down directly to it
2804 x1 += widthThumb / 2;
2805 x2 -= widthThumb / 2;
2806
2807 // this also means that we have slightly less space for the ticks in
2808 // between the first and the last
2809 len -= widthThumb;
2810
2811 dc.SetPen(m_penBlack);
2812
2813 int range = end - start;
2814 for ( int n = 0; n < range; n += step )
2815 {
2816 wxCoord x = x1 + (len*n) / range;
2817
2818 DrawLine(dc, x, y1, x, y2, orient == wxVERTICAL);
2819 }
2820
2821 // always draw the line at the end position
2822 DrawLine(dc, x2, y1, x2, y2, orient == wxVERTICAL);
2823 }
2824
2825 // ----------------------------------------------------------------------------
2826 // menu and menubar
2827 // ----------------------------------------------------------------------------
2828
2829 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2830 class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo
2831 {
2832 public:
2833 virtual wxSize GetSize() const { return m_size; }
2834
2835 wxCoord GetLabelOffset() const { return m_ofsLabel; }
2836 wxCoord GetAccelOffset() const { return m_ofsAccel; }
2837
2838 wxCoord GetItemHeight() const { return m_heightItem; }
2839
2840 private:
2841 // the total size of the menu
2842 wxSize m_size;
2843
2844 // the offset of the start of the menu item label
2845 wxCoord m_ofsLabel;
2846
2847 // the offset of the start of the accel label
2848 wxCoord m_ofsAccel;
2849
2850 // the height of a normal (not separator) item
2851 wxCoord m_heightItem;
2852
2853 friend wxMenuGeometryInfo *
2854 wxWin32Renderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
2855 };
2856
2857 // FIXME: all constants are hardcoded but shouldn't be
2858 static const wxCoord MENU_LEFT_MARGIN = 9;
2859 static const wxCoord MENU_RIGHT_MARGIN = 18;
2860 static const wxCoord MENU_VERT_MARGIN = 3;
2861
2862 // the margin around bitmap/check marks (on each side)
2863 static const wxCoord MENU_BMP_MARGIN = 2;
2864
2865 // the margin between the labels and accel strings
2866 static const wxCoord MENU_ACCEL_MARGIN = 8;
2867
2868 // the separator height in pixels: in fact, strangely enough, the real height
2869 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2870 // account here
2871 static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
2872
2873 // the size of the standard checkmark bitmap
2874 static const wxCoord MENU_CHECK_SIZE = 9;
2875
2876 void wxWin32Renderer::DrawMenuBarItem(wxDC& dc,
2877 const wxRect& rectOrig,
2878 const wxString& label,
2879 int flags,
2880 int indexAccel)
2881 {
2882 wxRect rect = rectOrig;
2883 rect.height--;
2884
2885 wxDCTextColourChanger colChanger(dc);
2886
2887 if ( flags & wxCONTROL_SELECTED )
2888 {
2889 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2890
2891 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2892 dc.SetBrush(wxBrush(colBg, wxSOLID));
2893 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2894 dc.DrawRectangle(rect);
2895 }
2896
2897 // don't draw the focus rect around menu bar items
2898 DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
2899 wxALIGN_CENTRE, indexAccel);
2900 }
2901
2902 void wxWin32Renderer::DrawMenuItem(wxDC& dc,
2903 wxCoord y,
2904 const wxMenuGeometryInfo& gi,
2905 const wxString& label,
2906 const wxString& accel,
2907 const wxBitmap& bitmap,
2908 int flags,
2909 int indexAccel)
2910 {
2911 const wxWin32MenuGeometryInfo& geometryInfo =
2912 (const wxWin32MenuGeometryInfo&)gi;
2913
2914 wxRect rect;
2915 rect.x = 0;
2916 rect.y = y;
2917 rect.width = geometryInfo.GetSize().x;
2918 rect.height = geometryInfo.GetItemHeight();
2919
2920 // draw the selected item specially
2921 wxDCTextColourChanger colChanger(dc);
2922 if ( flags & wxCONTROL_SELECTED )
2923 {
2924 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2925
2926 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2927 dc.SetBrush(wxBrush(colBg, wxSOLID));
2928 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2929 dc.DrawRectangle(rect);
2930 }
2931
2932 // draw the bitmap: use the bitmap provided or the standard checkmark for
2933 // the checkable items
2934 wxBitmap bmp = bitmap;
2935 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKED) )
2936 {
2937 bmp = GetIndicator(IndicatorType_Menu, flags);
2938 }
2939
2940 if ( bmp.Ok() )
2941 {
2942 rect.SetRight(geometryInfo.GetLabelOffset());
2943 wxControlRenderer::DrawBitmap(dc, bmp, rect);
2944 }
2945
2946 // draw the label
2947 rect.x = geometryInfo.GetLabelOffset();
2948 rect.SetRight(geometryInfo.GetAccelOffset());
2949
2950 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
2951
2952 // draw the accel string
2953 rect.x = geometryInfo.GetAccelOffset();
2954 rect.SetRight(geometryInfo.GetSize().x);
2955
2956 // NB: no accel index here
2957 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
2958
2959 // draw the submenu indicator
2960 if ( flags & wxCONTROL_ISSUBMENU )
2961 {
2962 rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
2963 rect.width = MENU_RIGHT_MARGIN;
2964
2965 wxArrowStyle arrowStyle;
2966 if ( flags & wxCONTROL_DISABLED )
2967 arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InversedDisabled
2968 : Arrow_Disabled;
2969 else if ( flags & wxCONTROL_SELECTED )
2970 arrowStyle = Arrow_Inversed;
2971 else
2972 arrowStyle = Arrow_Normal;
2973
2974 DrawArrow(dc, rect, Arrow_Right, arrowStyle);
2975 }
2976 }
2977
2978 void wxWin32Renderer::DrawMenuSeparator(wxDC& dc,
2979 wxCoord y,
2980 const wxMenuGeometryInfo& geomInfo)
2981 {
2982 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
2983 }
2984
2985 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& sizeText) const
2986 {
2987 wxSize size = sizeText;
2988
2989 // FIXME: menubar height is configurable under Windows
2990 size.x += 12;
2991 size.y += 6;
2992
2993 return size;
2994 }
2995
2996 wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win,
2997 const wxMenu& menu) const
2998 {
2999 // prepare the dc: for now we draw all the items with the system font
3000 wxClientDC dc(win);
3001 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
3002
3003 // the height of a normal item
3004 wxCoord heightText = dc.GetCharHeight();
3005
3006 // the total height
3007 wxCoord height = 0;
3008
3009 // the max length of label and accel strings: the menu width is the sum of
3010 // them, even if they're for different items (as the accels should be
3011 // aligned)
3012 //
3013 // the max length of the bitmap is never 0 as Windows always leaves enough
3014 // space for a check mark indicator
3015 wxCoord widthLabelMax = 0,
3016 widthAccelMax = 0,
3017 widthBmpMax = MENU_LEFT_MARGIN;
3018
3019 for ( wxMenuItemList::Node *node = menu.GetMenuItems().GetFirst();
3020 node;
3021 node = node->GetNext() )
3022 {
3023 // height of this item
3024 wxCoord h;
3025
3026 wxMenuItem *item = node->GetData();
3027 if ( item->IsSeparator() )
3028 {
3029 h = MENU_SEPARATOR_HEIGHT;
3030 }
3031 else // not separator
3032 {
3033 h = heightText;
3034
3035 wxCoord widthLabel;
3036 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
3037 if ( widthLabel > widthLabelMax )
3038 {
3039 widthLabelMax = widthLabel;
3040 }
3041
3042 wxCoord widthAccel;
3043 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
3044 if ( widthAccel > widthAccelMax )
3045 {
3046 widthAccelMax = widthAccel;
3047 }
3048
3049 const wxBitmap& bmp = item->GetBitmap();
3050 if ( bmp.Ok() )
3051 {
3052 wxCoord widthBmp = bmp.GetWidth();
3053 if ( widthBmp > widthBmpMax )
3054 widthBmpMax = widthBmp;
3055 }
3056 //else if ( item->IsCheckable() ): no need to check for this as
3057 // MENU_LEFT_MARGIN is big enough to show the check mark
3058 }
3059
3060 h += 2*MENU_VERT_MARGIN;
3061
3062 // remember the item position and height
3063 item->SetGeometry(height, h);
3064
3065 height += h;
3066 }
3067
3068 // bundle the metrics into a struct and return it
3069 wxWin32MenuGeometryInfo *gi = new wxWin32MenuGeometryInfo;
3070
3071 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
3072 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
3073 if ( widthAccelMax > 0 )
3074 {
3075 // if we actually have any accesl, add a margin
3076 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
3077 }
3078
3079 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
3080
3081 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
3082 gi->m_size.y = height;
3083
3084 return gi;
3085 }
3086
3087 // ----------------------------------------------------------------------------
3088 // status bar
3089 // ----------------------------------------------------------------------------
3090
3091 static const wxCoord STATBAR_BORDER_X = 2;
3092 static const wxCoord STATBAR_BORDER_Y = 2;
3093
3094 wxSize wxWin32Renderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const
3095 {
3096 if ( borderBetweenFields )
3097 *borderBetweenFields = 2;
3098
3099 return wxSize(STATBAR_BORDER_X, STATBAR_BORDER_Y);
3100 }
3101
3102 void wxWin32Renderer::DrawStatusField(wxDC& dc,
3103 const wxRect& rect,
3104 const wxString& label,
3105 int flags)
3106 {
3107 wxRect rectIn;
3108
3109 if ( flags & wxCONTROL_ISDEFAULT )
3110 {
3111 // draw the size grip: it is a normal rect except that in the lower
3112 // right corner we have several bands which may be used for dragging
3113 // the status bar corner
3114 //
3115 // each band consists of 4 stripes: m_penHighlight, double
3116 // m_penDarkGrey and transparent one
3117 wxCoord x2 = rect.GetRight(),
3118 y2 = rect.GetBottom();
3119
3120 // draw the upper left part of the rect normally
3121 dc.SetPen(m_penDarkGrey);
3122 dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2);
3123 dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop());
3124
3125 // draw the grey stripes of the grip
3126 size_t n;
3127 wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1;
3128 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
3129 {
3130 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
3131 dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1);
3132 }
3133
3134 // draw the white stripes
3135 dc.SetPen(m_penHighlight);
3136 ofs = WIDTH_STATUSBAR_GRIP_BAND + 1;
3137 for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
3138 {
3139 dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
3140 }
3141
3142 // draw the remaining rect boundaries
3143 ofs -= WIDTH_STATUSBAR_GRIP_BAND;
3144 dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1);
3145 dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2);
3146
3147 rectIn = rect;
3148 rectIn.Deflate(1);
3149
3150 rectIn.width -= STATUSBAR_GRIP_SIZE;
3151 }
3152 else // normal pane
3153 {
3154 DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
3155 }
3156
3157 rectIn.Deflate(STATBAR_BORDER_X, STATBAR_BORDER_Y);
3158
3159 wxDCClipper clipper(dc, rectIn);
3160 DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3161 }
3162
3163 // ----------------------------------------------------------------------------
3164 // combobox
3165 // ----------------------------------------------------------------------------
3166
3167 void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal,
3168 wxBitmap *bmpFocus,
3169 wxBitmap *bmpPressed,
3170 wxBitmap *bmpDisabled)
3171 {
3172 static const wxCoord widthCombo = 16;
3173 static const wxCoord heightCombo = 17;
3174
3175 wxMemoryDC dcMem;
3176
3177 if ( bmpNormal )
3178 {
3179 bmpNormal->Create(widthCombo, heightCombo);
3180 dcMem.SelectObject(*bmpNormal);
3181 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3182 Arrow_Down, Arrow_Normal);
3183 }
3184
3185 if ( bmpPressed )
3186 {
3187 bmpPressed->Create(widthCombo, heightCombo);
3188 dcMem.SelectObject(*bmpPressed);
3189 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3190 Arrow_Down, Arrow_Pressed);
3191 }
3192
3193 if ( bmpDisabled )
3194 {
3195 bmpDisabled->Create(widthCombo, heightCombo);
3196 dcMem.SelectObject(*bmpDisabled);
3197 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
3198 Arrow_Down, Arrow_Disabled);
3199 }
3200 }
3201
3202 // ----------------------------------------------------------------------------
3203 // background
3204 // ----------------------------------------------------------------------------
3205
3206 void wxWin32Renderer::DoDrawBackground(wxDC& dc,
3207 const wxColour& col,
3208 const wxRect& rect,
3209 wxWindow *window )
3210 {
3211 wxBrush brush(col, wxSOLID);
3212 dc.SetBrush(brush);
3213 dc.SetPen(*wxTRANSPARENT_PEN);
3214 dc.DrawRectangle(rect);
3215 }
3216
3217 void wxWin32Renderer::DrawBackground(wxDC& dc,
3218 const wxColour& col,
3219 const wxRect& rect,
3220 int flags,
3221 wxWindow *window )
3222 {
3223 // just fill it with the given or default bg colour
3224 wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL);
3225 DoDrawBackground(dc, colBg, rect, window );
3226 }
3227
3228 // ----------------------------------------------------------------------------
3229 // scrollbar
3230 // ----------------------------------------------------------------------------
3231
3232 void wxWin32Renderer::DrawArrow(wxDC& dc,
3233 wxDirection dir,
3234 const wxRect& rect,
3235 int flags)
3236 {
3237 // get the bitmap for this arrow
3238 wxArrowDirection arrowDir;
3239 switch ( dir )
3240 {
3241 case wxLEFT: arrowDir = Arrow_Left; break;
3242 case wxRIGHT: arrowDir = Arrow_Right; break;
3243 case wxUP: arrowDir = Arrow_Up; break;
3244 case wxDOWN: arrowDir = Arrow_Down; break;
3245
3246 default:
3247 wxFAIL_MSG(_T("unknown arrow direction"));
3248 return;
3249 }
3250
3251 wxArrowStyle arrowStyle;
3252 if ( flags & wxCONTROL_PRESSED )
3253 {
3254 // can't be pressed and disabled
3255 arrowStyle = Arrow_Pressed;
3256 }
3257 else
3258 {
3259 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
3260 }
3261
3262 DrawArrowButton(dc, rect, arrowDir, arrowStyle);
3263 }
3264
3265 void wxWin32Renderer::DrawArrow(wxDC& dc,
3266 const wxRect& rect,
3267 wxArrowDirection arrowDir,
3268 wxArrowStyle arrowStyle)
3269 {
3270 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
3271
3272 // under Windows the arrows always have the same size so just centre it in
3273 // the provided rectangle
3274 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
3275 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
3276
3277 // Windows does it like this...
3278 if ( arrowDir == Arrow_Left )
3279 x--;
3280
3281 // draw it
3282 dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
3283 }
3284
3285 void wxWin32Renderer::DrawArrowButton(wxDC& dc,
3286 const wxRect& rectAll,
3287 wxArrowDirection arrowDir,
3288 wxArrowStyle arrowStyle)
3289 {
3290 wxRect rect = rectAll;
3291 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3292 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
3293 DrawArrow(dc, rect, arrowDir, arrowStyle);
3294 }
3295
3296 void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
3297 wxOrientation orient,
3298 const wxRect& rect,
3299 int flags)
3300 {
3301 // we don't use the flags, the thumb never changes appearance
3302 wxRect rectThumb = rect;
3303 DrawArrowBorder(dc, &rectThumb);
3304 DrawBackground(dc, wxNullColour, rectThumb);
3305 }
3306
3307 void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
3308 wxOrientation orient,
3309 const wxRect& rectBar,
3310 int flags)
3311 {
3312 wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
3313 ? wxColourScheme::SCROLLBAR_PRESSED
3314 : wxColourScheme::SCROLLBAR;
3315 DoDrawBackground(dc, m_scheme->Get(col), rectBar);
3316 }
3317
3318 void wxWin32Renderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
3319 {
3320 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
3321 }
3322
3323 wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar,
3324 wxScrollBar::Element elem,
3325 int thumbPos) const
3326 {
3327 return StandardGetScrollbarRect(scrollbar, elem,
3328 thumbPos, m_sizeScrollbarArrow);
3329 }
3330
3331 wxCoord wxWin32Renderer::GetScrollbarSize(const wxScrollBar *scrollbar)
3332 {
3333 return StandardScrollBarSize(scrollbar, m_sizeScrollbarArrow);
3334 }
3335
3336 wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
3337 const wxPoint& pt) const
3338 {
3339 return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow);
3340 }
3341
3342 wxCoord wxWin32Renderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
3343 int thumbPos)
3344 {
3345 return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow);
3346 }
3347
3348 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar,
3349 wxCoord coord)
3350 {
3351 return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow);
3352 }
3353
3354 // ----------------------------------------------------------------------------
3355 // top level windows
3356 // ----------------------------------------------------------------------------
3357
3358 int wxWin32Renderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
3359 {
3360 wxRect client = GetFrameClientArea(rect, flags);
3361
3362 if ( client.Inside(pt) )
3363 return wxHT_TOPLEVEL_CLIENT_AREA;
3364
3365 if ( flags & wxTOPLEVEL_TITLEBAR )
3366 {
3367 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3368
3369 if ( flags & wxTOPLEVEL_ICON )
3370 {
3371 if ( wxRect(client.GetPosition(), GetFrameIconSize()).Inside(pt) )
3372 return wxHT_TOPLEVEL_ICON;
3373 }
3374
3375 wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
3376 client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
3377 FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
3378
3379 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3380 {
3381 if ( btnRect.Inside(pt) )
3382 return wxHT_TOPLEVEL_BUTTON_CLOSE;
3383 btnRect.x -= FRAME_BUTTON_WIDTH + 2;
3384 }
3385 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3386 {
3387 if ( btnRect.Inside(pt) )
3388 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
3389 btnRect.x -= FRAME_BUTTON_WIDTH;
3390 }
3391 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3392 {
3393 if ( btnRect.Inside(pt) )
3394 return wxHT_TOPLEVEL_BUTTON_RESTORE;
3395 btnRect.x -= FRAME_BUTTON_WIDTH;
3396 }
3397 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3398 {
3399 if ( btnRect.Inside(pt) )
3400 return wxHT_TOPLEVEL_BUTTON_ICONIZE;
3401 btnRect.x -= FRAME_BUTTON_WIDTH;
3402 }
3403 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3404 {
3405 if ( btnRect.Inside(pt) )
3406 return wxHT_TOPLEVEL_BUTTON_HELP;
3407 btnRect.x -= FRAME_BUTTON_WIDTH;
3408 }
3409
3410 if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
3411 return wxHT_TOPLEVEL_TITLEBAR;
3412 }
3413
3414 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3415 {
3416 // we are certainly at one of borders, lets decide which one:
3417
3418 int border = 0;
3419 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3420 if ( pt.x < client.x )
3421 border |= wxHT_TOPLEVEL_BORDER_W;
3422 else if ( pt.x >= client.width + client.x )
3423 border |= wxHT_TOPLEVEL_BORDER_E;
3424 if ( pt.y < client.y )
3425 border |= wxHT_TOPLEVEL_BORDER_N;
3426 else if ( pt.y >= client.height + client.y )
3427 border |= wxHT_TOPLEVEL_BORDER_S;
3428 return border;
3429 }
3430
3431 return wxHT_NOWHERE;
3432 }
3433
3434 void wxWin32Renderer::DrawFrameTitleBar(wxDC& dc,
3435 const wxRect& rect,
3436 const wxString& title,
3437 const wxIcon& icon,
3438 int flags,
3439 int specialButton,
3440 int specialButtonFlags)
3441 {
3442 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3443 {
3444 DrawFrameBorder(dc, rect, flags);
3445 }
3446 if ( flags & wxTOPLEVEL_TITLEBAR )
3447 {
3448 DrawFrameBackground(dc, rect, flags);
3449 if ( flags & wxTOPLEVEL_ICON )
3450 DrawFrameIcon(dc, rect, icon, flags);
3451 DrawFrameTitle(dc, rect, title, flags);
3452
3453 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3454 wxCoord x,y;
3455 x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
3456 y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
3457
3458 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3459 {
3460 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
3461 (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
3462 specialButtonFlags : 0);
3463 x -= FRAME_BUTTON_WIDTH + 2;
3464 }
3465 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3466 {
3467 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
3468 (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
3469 specialButtonFlags : 0);
3470 x -= FRAME_BUTTON_WIDTH;
3471 }
3472 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3473 {
3474 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
3475 (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
3476 specialButtonFlags : 0);
3477 x -= FRAME_BUTTON_WIDTH;
3478 }
3479 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3480 {
3481 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
3482 (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
3483 specialButtonFlags : 0);
3484 x -= FRAME_BUTTON_WIDTH;
3485 }
3486 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3487 {
3488 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
3489 (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
3490 specialButtonFlags : 0);
3491 x -= FRAME_BUTTON_WIDTH;
3492 }
3493 }
3494 }
3495
3496 void wxWin32Renderer::DrawFrameBorder(wxDC& dc,
3497 const wxRect& rect,
3498 int flags)
3499 {
3500 if ( !(flags & wxTOPLEVEL_BORDER) ) return;
3501
3502 wxRect r(rect);
3503
3504 DrawShadedRect(dc, &r, m_penLightGrey, m_penBlack);
3505 DrawShadedRect(dc, &r, m_penHighlight, m_penDarkGrey);
3506 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3507 if ( flags & wxTOPLEVEL_RESIZEABLE )
3508 DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
3509 }
3510
3511 void wxWin32Renderer::DrawFrameBackground(wxDC& dc,
3512 const wxRect& rect,
3513 int flags)
3514 {
3515 if ( !(flags & wxTOPLEVEL_TITLEBAR) ) return;
3516
3517 wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
3518 wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE) :
3519 wxSCHEME_COLOUR(m_scheme, TITLEBAR);
3520
3521 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3522 r.height = FRAME_TITLEBAR_HEIGHT;
3523
3524 DrawBackground(dc, col, r);
3525 }
3526
3527 void wxWin32Renderer::DrawFrameTitle(wxDC& dc,
3528 const wxRect& rect,
3529 const wxString& title,
3530 int flags)
3531 {
3532 wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
3533 wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE_TEXT) :
3534 wxSCHEME_COLOUR(m_scheme, TITLEBAR_TEXT);
3535
3536 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3537 r.height = FRAME_TITLEBAR_HEIGHT;
3538 if ( flags & wxTOPLEVEL_ICON )
3539 {
3540 r.x += FRAME_TITLEBAR_HEIGHT;
3541 r.width -= FRAME_TITLEBAR_HEIGHT + 2;
3542 }
3543 else
3544 {
3545 r.x += 1;
3546 r.width -= 3;
3547 }
3548
3549 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3550 r.width -= FRAME_BUTTON_WIDTH + 2;
3551 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3552 r.width -= FRAME_BUTTON_WIDTH;
3553 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3554 r.width -= FRAME_BUTTON_WIDTH;
3555 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3556 r.width -= FRAME_BUTTON_WIDTH;
3557 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3558 r.width -= FRAME_BUTTON_WIDTH;
3559
3560 dc.SetFont(m_titlebarFont);
3561 dc.SetTextForeground(col);
3562
3563 wxCoord textW;
3564 dc.GetTextExtent(title, &textW, NULL);
3565 if ( textW > r.width )
3566 {
3567 // text is too big, let's shorten it and add "..." after it:
3568 size_t len = title.length();
3569 wxCoord WSoFar, letterW;
3570
3571 dc.GetTextExtent(wxT("..."), &WSoFar, NULL);
3572 if ( WSoFar > r.width )
3573 {
3574 // not enough space to draw anything
3575 return;
3576 }
3577
3578 wxString s;
3579 s.Alloc(len);
3580 for (size_t i = 0; i < len; i++)
3581 {
3582 dc.GetTextExtent(title[i], &letterW, NULL);
3583 if ( letterW + WSoFar > r.width )
3584 break;
3585 WSoFar += letterW;
3586 s << title[i];
3587 }
3588 s << wxT("...");
3589 dc.DrawLabel(s, wxNullBitmap, r,
3590 wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3591 }
3592 else
3593 dc.DrawLabel(title, wxNullBitmap, r,
3594 wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
3595 }
3596
3597 void wxWin32Renderer::DrawFrameIcon(wxDC& dc,
3598 const wxRect& rect,
3599 const wxIcon& icon,
3600 int flags)
3601 {
3602 if ( icon.Ok() )
3603 {
3604 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
3605 dc.DrawIcon(icon, r.x, r.y);
3606 }
3607 }
3608
3609 void wxWin32Renderer::DrawFrameButton(wxDC& dc,
3610 wxCoord x, wxCoord y,
3611 int button,
3612 int flags)
3613 {
3614 wxRect r(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
3615
3616 size_t idx = 0;
3617 switch (button)
3618 {
3619 case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
3620 case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
3621 case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
3622 case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
3623 case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
3624 default:
3625 wxFAIL_MSG(wxT("incorrect button specification"));
3626 }
3627
3628 if ( flags & wxCONTROL_PRESSED )
3629 {
3630 DrawShadedRect(dc, &r, m_penBlack, m_penHighlight);
3631 DrawShadedRect(dc, &r, m_penDarkGrey, m_penLightGrey);
3632 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
3633 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x+1, r.y+1, TRUE);
3634 }
3635 else
3636 {
3637 DrawShadedRect(dc, &r, m_penHighlight, m_penBlack);
3638 DrawShadedRect(dc, &r, m_penLightGrey, m_penDarkGrey);
3639 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
3640 dc.DrawBitmap(m_bmpFrameButtons[idx], r.x, r.y, TRUE);
3641 }
3642 }
3643
3644
3645 wxRect wxWin32Renderer::GetFrameClientArea(const wxRect& rect,
3646 int flags) const
3647 {
3648 wxRect r(rect);
3649
3650 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3651 {
3652 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3653 RESIZEABLE_FRAME_BORDER_THICKNESS :
3654 FRAME_BORDER_THICKNESS;
3655 r.Inflate(-border);
3656 }
3657 if ( flags & wxTOPLEVEL_TITLEBAR )
3658 {
3659 r.y += FRAME_TITLEBAR_HEIGHT;
3660 r.height -= FRAME_TITLEBAR_HEIGHT;
3661 }
3662
3663 return r;
3664 }
3665
3666 wxSize wxWin32Renderer::GetFrameTotalSize(const wxSize& clientSize,
3667 int flags) const
3668 {
3669 wxSize s(clientSize);
3670
3671 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3672 {
3673 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3674 RESIZEABLE_FRAME_BORDER_THICKNESS :
3675 FRAME_BORDER_THICKNESS;
3676 s.x += 2*border;
3677 s.y += 2*border;
3678 }
3679 if ( flags & wxTOPLEVEL_TITLEBAR )
3680 s.y += FRAME_TITLEBAR_HEIGHT;
3681
3682 return s;
3683 }
3684
3685 wxSize wxWin32Renderer::GetFrameMinSize(int flags) const
3686 {
3687 wxSize s(0, 0);
3688
3689 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
3690 {
3691 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
3692 RESIZEABLE_FRAME_BORDER_THICKNESS :
3693 FRAME_BORDER_THICKNESS;
3694 s.x += 2*border;
3695 s.y += 2*border;
3696 }
3697
3698 if ( flags & wxTOPLEVEL_TITLEBAR )
3699 {
3700 s.y += FRAME_TITLEBAR_HEIGHT;
3701
3702 if ( flags & wxTOPLEVEL_ICON )
3703 s.x += FRAME_TITLEBAR_HEIGHT + 2;
3704 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
3705 s.x += FRAME_BUTTON_WIDTH + 2;
3706 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
3707 s.x += FRAME_BUTTON_WIDTH;
3708 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
3709 s.x += FRAME_BUTTON_WIDTH;
3710 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
3711 s.x += FRAME_BUTTON_WIDTH;
3712 if ( flags & wxTOPLEVEL_BUTTON_HELP )
3713 s.x += FRAME_BUTTON_WIDTH;
3714 }
3715
3716 return s;
3717 }
3718
3719 wxSize wxWin32Renderer::GetFrameIconSize() const
3720 {
3721 return wxSize(16, 16);
3722 }
3723
3724
3725 // ----------------------------------------------------------------------------
3726 // standard icons
3727 // ----------------------------------------------------------------------------
3728
3729 static char *error_xpm[]={
3730 "32 32 5 1",
3731 ". c None",
3732 "# c #800000",
3733 "b c #808080",
3734 "a c #ff0000",
3735 "c c #ffffff",
3736 "...........########.............",
3737 "........###aaaaaaaa###..........",
3738 ".......#aaaaaaaaaaaaaa#.........",
3739 ".....##aaaaaaaaaaaaaaaa##.......",
3740 "....#aaaaaaaaaaaaaaaaaaaa#......",
3741 "...#aaaaaaaaaaaaaaaaaaaaaa#.....",
3742 "...#aaaaaaaaaaaaaaaaaaaaaa#b....",
3743 "..#aaaaaacaaaaaaaaaacaaaaaa#b...",
3744 ".#aaaaaacccaaaaaaaacccaaaaaa#...",
3745 ".#aaaaacccccaaaaaacccccaaaaa#b..",
3746 ".#aaaaaacccccaaaacccccaaaaaa#bb.",
3747 "#aaaaaaaacccccaacccccaaaaaaaa#b.",
3748 "#aaaaaaaaaccccccccccaaaaaaaaa#b.",
3749 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3750 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3751 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3752 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3753 "#aaaaaaaaaccccccccccaaaaaaaaa#bb",
3754 "#aaaaaaaacccccaacccccaaaaaaaa#bb",
3755 ".#aaaaaacccccaaaacccccaaaaaa#bbb",
3756 ".#aaaaacccccaaaaaacccccaaaaa#bbb",
3757 ".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
3758 "..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
3759 "...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
3760 "...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
3761 "....#aaaaaaaaaaaaaaaaaaaa#bbb...",
3762 ".....##aaaaaaaaaaaaaaaa##bbbb...",
3763 "......b#aaaaaaaaaaaaaa#bbbbb....",
3764 ".......b###aaaaaaaa###bbbbb.....",
3765 ".........bb########bbbbbb.......",
3766 "..........bbbbbbbbbbbbbb........",
3767 ".............bbbbbbbb..........."};
3768
3769 static char *info_xpm[]={
3770 "32 32 6 1",
3771 ". c None",
3772 "d c #000000",
3773 "c c #0000ff",
3774 "# c #808080",
3775 "a c #c0c0c0",
3776 "b c #ffffff",
3777 "...........########.............",
3778 "........###abbbbbba###..........",
3779 "......##abbbbbbbbbbbba##........",
3780 ".....#abbbbbbbbbbbbbbbba#.......",
3781 "....#bbbbbbbaccccabbbbbbbd......",
3782 "...#bbbbbbbbccccccbbbbbbbbd.....",
3783 "..#bbbbbbbbbccccccbbbbbbbbbd....",
3784 ".#abbbbbbbbbaccccabbbbbbbbbad...",
3785 ".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
3786 "#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
3787 "#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
3788 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3789 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3790 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3791 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3792 "#abbbbbbbbbbbcccccbbbbbbbbbbad##",
3793 ".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
3794 ".#abbbbbbbbbbcccccbbbbbbbbbad###",
3795 "..#bbbbbbbbcccccccccbbbbbbbd###.",
3796 "...dbbbbbbbbbbbbbbbbbbbbbbd####.",
3797 "....dbbbbbbbbbbbbbbbbbbbbd####..",
3798 ".....dabbbbbbbbbbbbbbbbad####...",
3799 "......ddabbbbbbbbbbbbadd####....",
3800 ".......#dddabbbbbbaddd#####.....",
3801 "........###dddabbbd#######......",
3802 "..........####dbbbd#####........",
3803 ".............#dbbbd##...........",
3804 "...............dbbd##...........",
3805 "................dbd##...........",
3806 ".................dd##...........",
3807 "..................###...........",
3808 "...................##..........."};
3809
3810 static char *question_xpm[]={
3811 "32 32 6 1",
3812 ". c None",
3813 "c c #000000",
3814 "d c #0000ff",
3815 "# c #808080",
3816 "a c #c0c0c0",
3817 "b c #ffffff",
3818 "...........########.............",
3819 "........###abbbbbba###..........",
3820 "......##abbbbbbbbbbbba##........",
3821 ".....#abbbbbbbbbbbbbbbba#.......",
3822 "....#bbbbbbbbbbbbbbbbbbbbc......",
3823 "...#bbbbbbbaddddddabbbbbbbc.....",
3824 "..#bbbbbbbadabbddddabbbbbbbc....",
3825 ".#abbbbbbbddbbbbddddbbbbbbbac...",
3826 ".#bbbbbbbbddddbbddddbbbbbbbbc#..",
3827 "#abbbbbbbbddddbaddddbbbbbbbbac#.",
3828 "#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
3829 "#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
3830 "#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
3831 "#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
3832 "#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
3833 "#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
3834 ".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
3835 ".#abbbbbbbbbbddddbbbbbbbbbbac###",
3836 "..#bbbbbbbbbbddddbbbbbbbbbbc###.",
3837 "...cbbbbbbbbbaddabbbbbbbbbc####.",
3838 "....cbbbbbbbbbbbbbbbbbbbbc####..",
3839 ".....cabbbbbbbbbbbbbbbbac####...",
3840 "......ccabbbbbbbbbbbbacc####....",
3841 ".......#cccabbbbbbaccc#####.....",
3842 "........###cccabbbc#######......",
3843 "..........####cbbbc#####........",
3844 ".............#cbbbc##...........",
3845 "...............cbbc##...........",
3846 "................cbc##...........",
3847 ".................cc##...........",
3848 "..................###...........",
3849 "...................##..........."};
3850
3851 static char *warning_xpm[]={
3852 "32 32 6 1",
3853 ". c None",
3854 "c c #000000",
3855 "# c #808000",
3856 "d c #808080",
3857 "b c #c0c0c0",
3858 "a c #ffff00",
3859 ".............###................",
3860 "............#aabc...............",
3861 "...........#aaaabcd.............",
3862 "...........#aaaaacdd............",
3863 "..........#aaaaaabcdd...........",
3864 "..........#aaaaaaacdd...........",
3865 ".........#aaaaaaaabcdd..........",
3866 ".........#aaaaaaaaacdd..........",
3867 "........#aaaaaaaaaabcdd.........",
3868 "........#aaabcccbaaacdd.........",
3869 ".......#aaaacccccaaabcdd........",
3870 ".......#aaaacccccaaaacdd........",
3871 "......#aaaaacccccaaaabcdd.......",
3872 "......#aaaaacccccaaaaacdd.......",
3873 ".....#aaaaaacccccaaaaabcdd......",
3874 ".....#aaaaaa#ccc#aaaaaacdd......",
3875 "....#aaaaaaabcccbaaaaaabcdd.....",
3876 "....#aaaaaaaacccaaaaaaaacdd.....",
3877 "...#aaaaaaaaa#c#aaaaaaaabcdd....",
3878 "...#aaaaaaaaabcbaaaaaaaaacdd....",
3879 "..#aaaaaaaaaaacaaaaaaaaaabcdd...",
3880 "..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
3881 ".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
3882 ".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
3883 "#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
3884 "#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
3885 "#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
3886 "#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
3887 ".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
3888 "..#ccccccccccccccccccccccccddddd",
3889 "....ddddddddddddddddddddddddddd.",
3890 ".....ddddddddddddddddddddddddd.."};
3891
3892 wxBitmap wxWin32ArtProvider::CreateBitmap(const wxArtID& id,
3893 const wxArtClient& WXUNUSED(client),
3894 const wxSize& WXUNUSED(size))
3895 {
3896 if ( id == wxART_INFORMATION )
3897 return wxBitmap(info_xpm);
3898 if ( id == wxART_ERROR )
3899 return wxBitmap(error_xpm);
3900 if ( id == wxART_WARNING )
3901 return wxBitmap(warning_xpm);
3902 if ( id == wxART_QUESTION )
3903 return wxBitmap(question_xpm);
3904 return wxNullBitmap;
3905 }
3906
3907
3908 // ----------------------------------------------------------------------------
3909 // text control geometry
3910 // ----------------------------------------------------------------------------
3911
3912 static inline int GetTextBorderWidth()
3913 {
3914 return 1;
3915 }
3916
3917 wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
3918 const wxRect& rect) const
3919 {
3920 wxRect rectTotal = rect;
3921
3922 wxCoord widthBorder = GetTextBorderWidth();
3923 rectTotal.Inflate(widthBorder);
3924
3925 // this is what Windows does
3926 rectTotal.height++;
3927
3928 return rectTotal;
3929 }
3930
3931 wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
3932 const wxRect& rect,
3933 wxCoord *extraSpaceBeyond) const
3934 {
3935 wxRect rectText = rect;
3936
3937 // undo GetTextTotalArea()
3938 if ( rectText.height > 0 )
3939 rectText.height--;
3940
3941 wxCoord widthBorder = GetTextBorderWidth();
3942 rectText.Inflate(-widthBorder);
3943
3944 if ( extraSpaceBeyond )
3945 *extraSpaceBeyond = 0;
3946
3947 return rectText;
3948 }
3949
3950 // ----------------------------------------------------------------------------
3951 // size adjustments
3952 // ----------------------------------------------------------------------------
3953
3954 void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
3955 {
3956 #if wxUSE_SCROLLBAR
3957 if ( wxDynamicCast(window, wxScrollBar) )
3958 {
3959 // we only set the width of vert scrollbars and height of the
3960 // horizontal ones
3961 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
3962 size->y = m_sizeScrollbarArrow.y;
3963 else
3964 size->x = m_sizeScrollbarArrow.x;
3965
3966 // skip border width adjustments, they don't make sense for us
3967 return;
3968 }
3969 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3970
3971 #if wxUSE_BUTTON
3972 if ( wxDynamicCast(window, wxButton) )
3973 {
3974 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
3975 {
3976 // TODO: don't harcode all this
3977 size->x += 3*window->GetCharWidth();
3978
3979 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
3980 if ( size->y < heightBtn - 8 )
3981 size->y = heightBtn;
3982 else
3983 size->y += 9;
3984 }
3985
3986 // no border width adjustments for buttons
3987 return;
3988 }
3989 #endif // wxUSE_BUTTON
3990
3991 // take into account the border width
3992 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
3993 size->x += rectBorder.x + rectBorder.width;
3994 size->y += rectBorder.y + rectBorder.height;
3995 }
3996
3997 // ============================================================================
3998 // wxInputHandler
3999 // ============================================================================
4000
4001 // ----------------------------------------------------------------------------
4002 // wxWin32InputHandler
4003 // ----------------------------------------------------------------------------
4004
4005 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer)
4006 {
4007 m_renderer = renderer;
4008 }
4009
4010 bool wxWin32InputHandler::HandleKey(wxInputConsumer *control,
4011 const wxKeyEvent& event,
4012 bool pressed)
4013 {
4014 return FALSE;
4015 }
4016
4017 bool wxWin32InputHandler::HandleMouse(wxInputConsumer *control,
4018 const wxMouseEvent& event)
4019 {
4020 // clicking on the control gives it focus
4021 if ( event.ButtonDown() )
4022 {
4023 wxWindow *win = control->GetInputWindow();
4024
4025 if (( wxWindow::FindFocus() != control->GetInputWindow() ) &&
4026 ( win->AcceptsFocus() ) )
4027 {
4028 win->SetFocus();
4029
4030 return TRUE;
4031 }
4032 }
4033
4034 return FALSE;
4035 }
4036
4037 // ----------------------------------------------------------------------------
4038 // wxWin32ScrollBarInputHandler
4039 // ----------------------------------------------------------------------------
4040
4041 wxWin32ScrollBarInputHandler::
4042 wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
4043 wxInputHandler *handler)
4044 : wxStdScrollBarInputHandler(renderer, handler)
4045 {
4046 m_scrollPaused = FALSE;
4047 m_interval = 0;
4048 }
4049
4050 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
4051 const wxControlAction& action)
4052 {
4053 // stop if went beyond the position of the original click (this can only
4054 // happen when we scroll by pages)
4055 bool stop = FALSE;
4056 if ( action == wxACTION_SCROLL_PAGE_DOWN )
4057 {
4058 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
4059 != wxHT_SCROLLBAR_BAR_2;
4060 }
4061 else if ( action == wxACTION_SCROLL_PAGE_UP )
4062 {
4063 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
4064 != wxHT_SCROLLBAR_BAR_1;
4065 }
4066
4067 if ( stop )
4068 {
4069 StopScrolling(scrollbar);
4070
4071 scrollbar->Refresh();
4072
4073 return FALSE;
4074 }
4075
4076 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
4077 }
4078
4079 bool wxWin32ScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
4080 const wxMouseEvent& event)
4081 {
4082 // remember the current state
4083 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
4084
4085 // do process the message
4086 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
4087
4088 // analyse the changes
4089 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
4090 {
4091 // we just started dragging the thumb, remember its initial position to
4092 // be able to restore it if the drag is cancelled later
4093 m_eventStartDrag = event;
4094 }
4095
4096 return rc;
4097 }
4098
4099 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
4100 const wxMouseEvent& event)
4101 {
4102 // we don't highlight scrollbar elements, so there is no need to process
4103 // mouse move events normally - only do it while mouse is captured (i.e.
4104 // when we're dragging the thumb or pressing on something)
4105 if ( !m_winCapture )
4106 return FALSE;
4107
4108 if ( event.Entering() )
4109 {
4110 // we're not interested in this at all
4111 return FALSE;
4112 }
4113
4114 wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
4115 wxHitTest ht;
4116 if ( m_scrollPaused )
4117 {
4118 // check if the mouse returned to its original location
4119
4120 if ( event.Leaving() )
4121 {
4122 // it surely didn't
4123 return FALSE;
4124 }
4125
4126 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
4127 if ( ht == m_htLast )
4128 {
4129 // yes it did, resume scrolling
4130 m_scrollPaused = FALSE;
4131 if ( m_timerScroll )
4132 {
4133 // we were scrolling by line/page, restart timer
4134 m_timerScroll->Start(m_interval);
4135
4136 Press(scrollbar, TRUE);
4137 }
4138 else // we were dragging the thumb
4139 {
4140 // restore its last location
4141 HandleThumbMove(scrollbar, m_eventLastDrag);
4142 }
4143
4144 return TRUE;
4145 }
4146 }
4147 else // normal case, scrolling hasn't been paused
4148 {
4149 // if we're scrolling the scrollbar because the arrow or the shaft was
4150 // pressed, check that the mouse stays on the same scrollbar element
4151
4152 #if 0
4153 // Always let thumb jump back if we leave the scrollbar
4154 if ( event.Moving() )
4155 {
4156 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
4157 }
4158 else // event.Leaving()
4159 {
4160 ht = wxHT_NOWHERE;
4161 }
4162 #else
4163 // Jump back only if we get far away from it
4164 wxPoint pos = event.GetPosition();
4165 if (scrollbar->HasFlag( wxVERTICAL ))
4166 {
4167 if (pos.x > -40 && pos.x < scrollbar->GetSize().x+40)
4168 pos.x = 5;
4169 }
4170 else
4171 {
4172 if (pos.y > -40 && pos.y < scrollbar->GetSize().y+40)
4173 pos.y = 5;
4174 }
4175 ht = m_renderer->HitTestScrollbar(scrollbar, pos );
4176 #endif
4177
4178 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4179 // is still ok - we only want to catch the case when the mouse leaves
4180 // the scrollbar here
4181 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
4182 {
4183 ht = wxHT_SCROLLBAR_THUMB;
4184 }
4185
4186 if ( ht != m_htLast )
4187 {
4188 // what were we doing? 2 possibilities: either an arrow/shaft was
4189 // pressed in which case we have a timer and so we just stop it or
4190 // we were dragging the thumb
4191 if ( m_timerScroll )
4192 {
4193 // pause scrolling
4194 m_interval = m_timerScroll->GetInterval();
4195 m_timerScroll->Stop();
4196 m_scrollPaused = TRUE;
4197
4198 // unpress the arrow
4199 Press(scrollbar, FALSE);
4200 }
4201 else // we were dragging the thumb
4202 {
4203 // remember the current thumb position to be able to restore it
4204 // if the mouse returns to it later
4205 m_eventLastDrag = event;
4206
4207 // and restore the original position (before dragging) of the
4208 // thumb for now
4209 HandleThumbMove(scrollbar, m_eventStartDrag);
4210 }
4211
4212 return TRUE;
4213 }
4214 }
4215
4216 return wxStdScrollBarInputHandler::HandleMouseMove(control, event);
4217 }
4218
4219 // ----------------------------------------------------------------------------
4220 // wxWin32CheckboxInputHandler
4221 // ----------------------------------------------------------------------------
4222
4223 bool wxWin32CheckboxInputHandler::HandleKey(wxInputConsumer *control,
4224 const wxKeyEvent& event,
4225 bool pressed)
4226 {
4227 if ( pressed )
4228 {
4229 wxControlAction action;
4230 int keycode = event.GetKeyCode();
4231 switch ( keycode )
4232 {
4233 case WXK_SPACE:
4234 action = wxACTION_CHECKBOX_TOGGLE;
4235 break;
4236
4237 case WXK_SUBTRACT:
4238 case WXK_NUMPAD_SUBTRACT:
4239 action = wxACTION_CHECKBOX_CHECK;
4240 break;
4241
4242 case WXK_ADD:
4243 case WXK_NUMPAD_ADD:
4244 case WXK_NUMPAD_EQUAL:
4245 action = wxACTION_CHECKBOX_CLEAR;
4246 break;
4247 }
4248
4249 if ( !!action )
4250 {
4251 control->PerformAction(action);
4252
4253 return TRUE;
4254 }
4255 }
4256
4257 return FALSE;
4258 }
4259
4260 // ----------------------------------------------------------------------------
4261 // wxWin32TextCtrlInputHandler
4262 // ----------------------------------------------------------------------------
4263
4264 bool wxWin32TextCtrlInputHandler::HandleKey(wxInputConsumer *control,
4265 const wxKeyEvent& event,
4266 bool pressed)
4267 {
4268 // handle only MSW-specific text bindings here, the others are handled in
4269 // the base class
4270 if ( pressed )
4271 {
4272 int keycode = event.GetKeyCode();
4273
4274 wxControlAction action;
4275 if ( keycode == WXK_DELETE && event.ShiftDown() )
4276 {
4277 action = wxACTION_TEXT_CUT;
4278 }
4279 else if ( keycode == WXK_INSERT )
4280 {
4281 if ( event.ControlDown() )
4282 action = wxACTION_TEXT_COPY;
4283 else if ( event.ShiftDown() )
4284 action = wxACTION_TEXT_PASTE;
4285 }
4286
4287 if ( action != wxACTION_NONE )
4288 {
4289 control->PerformAction(action);
4290
4291 return TRUE;
4292 }
4293 }
4294
4295 return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed);
4296 }
4297
4298 // ----------------------------------------------------------------------------
4299 // wxWin32StatusBarInputHandler
4300 // ----------------------------------------------------------------------------
4301
4302 wxWin32StatusBarInputHandler::
4303 wxWin32StatusBarInputHandler(wxInputHandler *handler)
4304 : wxStdInputHandler(handler)
4305 {
4306 m_isOnGrip = FALSE;
4307 }
4308
4309 bool wxWin32StatusBarInputHandler::IsOnGrip(wxWindow *statbar,
4310 const wxPoint& pt) const
4311 {
4312 if ( statbar->HasFlag(wxST_SIZEGRIP) &&
4313 statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
4314 {
4315 wxTopLevelWindow *
4316 parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow);
4317
4318 wxCHECK_MSG( parentTLW, FALSE,
4319 _T("the status bar should be a child of a TLW") );
4320
4321 // a maximized window can't be resized anyhow
4322 if ( !parentTLW->IsMaximized() )
4323 {
4324 // VZ: I think that the standard Windows behaviour is to only
4325 // show the resizing cursor when the mouse is on top of the
4326 // grip itself but apparently different Windows versions behave
4327 // differently (?) and it seems a better UI to allow resizing
4328 // the status bar even when the mouse is above the grip
4329 wxSize sizeSbar = statbar->GetSize();
4330
4331 int diff = sizeSbar.x - pt.x;
4332 return diff >= 0 && diff < (wxCoord)STATUSBAR_GRIP_SIZE;
4333 }
4334 }
4335
4336 return FALSE;
4337 }
4338
4339 bool wxWin32StatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
4340 const wxMouseEvent& event)
4341 {
4342 if ( event.Button(1) )
4343 {
4344 if ( event.ButtonDown(1) )
4345 {
4346 wxWindow *statbar = consumer->GetInputWindow();
4347
4348 if ( IsOnGrip(statbar, event.GetPosition()) )
4349 {
4350 wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
4351 wxTopLevelWindow);
4352 if ( tlw )
4353 {
4354 tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
4355 wxHT_TOPLEVEL_BORDER_SE);
4356
4357 statbar->SetCursor(m_cursorOld);
4358
4359 return TRUE;
4360 }
4361 }
4362 }
4363 }
4364
4365 return wxStdInputHandler::HandleMouse(consumer, event);
4366 }
4367
4368 bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
4369 const wxMouseEvent& event)
4370 {
4371 wxWindow *statbar = consumer->GetInputWindow();
4372
4373 bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
4374 if ( isOnGrip != m_isOnGrip )
4375 {
4376 m_isOnGrip = isOnGrip;
4377 if ( isOnGrip )
4378 {
4379 m_cursorOld = statbar->GetCursor();
4380 statbar->SetCursor(wxCURSOR_SIZENWSE);
4381 }
4382 else
4383 {
4384 statbar->SetCursor(m_cursorOld);
4385 }
4386 }
4387
4388 return wxStdInputHandler::HandleMouseMove(consumer, event);
4389 }
4390
4391 // ----------------------------------------------------------------------------
4392 // wxWin32FrameInputHandler
4393 // ----------------------------------------------------------------------------
4394
4395 class wxWin32SystemMenuEvtHandler : public wxEvtHandler
4396 {
4397 public:
4398 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
4399
4400 void Attach(wxInputConsumer *consumer);
4401 void Detach();
4402
4403 private:
4404 DECLARE_EVENT_TABLE()
4405 void OnSystemMenu(wxCommandEvent &event);
4406 void OnCloseFrame(wxCommandEvent &event);
4407 void OnClose(wxCloseEvent &event);
4408
4409 wxWin32FrameInputHandler *m_inputHnd;
4410 wxTopLevelWindow *m_wnd;
4411 wxAcceleratorTable m_oldAccelTable;
4412 };
4413
4414 wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler(
4415 wxWin32FrameInputHandler *handler)
4416 {
4417 m_inputHnd = handler;
4418 m_wnd = NULL;
4419 }
4420
4421 void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
4422 {
4423 wxASSERT_MSG( m_wnd == NULL, _T("can't attach the handler twice!") );
4424
4425 m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
4426 m_wnd->PushEventHandler(this);
4427
4428 // VS: This code relies on using generic implementation of
4429 // wxAcceleratorTable in wxUniv!
4430 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
4431 m_oldAccelTable = table;
4432 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
4433 table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
4434 m_wnd->SetAcceleratorTable(table);
4435 }
4436
4437 void wxWin32SystemMenuEvtHandler::Detach()
4438 {
4439 if ( m_wnd )
4440 {
4441 m_wnd->SetAcceleratorTable(m_oldAccelTable);
4442 m_wnd->RemoveEventHandler(this);
4443 m_wnd = NULL;
4444 }
4445 }
4446
4447 BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
4448 EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
4449 EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
4450 EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
4451 END_EVENT_TABLE()
4452
4453 void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
4454 {
4455 int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) &&
4456 !m_wnd->IsMaximized()) ?
4457 RESIZEABLE_FRAME_BORDER_THICKNESS :
4458 FRAME_BORDER_THICKNESS;
4459 wxPoint pt = m_wnd->GetClientAreaOrigin();
4460 pt.x = -pt.x + border;
4461 pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT;
4462
4463 wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
4464 m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
4465 m_inputHnd->PopupSystemMenu(m_wnd, pt);
4466 m_wnd->SetAcceleratorTable(table);
4467 }
4468
4469 void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
4470 {
4471 m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
4472 wxTOPLEVEL_BUTTON_CLOSE);
4473 }
4474
4475 void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
4476 {
4477 m_wnd = NULL;
4478 event.Skip();
4479 }
4480
4481
4482 wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
4483 : wxStdFrameInputHandler(handler)
4484 {
4485 m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
4486 }
4487
4488 wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
4489 {
4490 if ( m_menuHandler )
4491 {
4492 m_menuHandler->Detach();
4493 delete m_menuHandler;
4494 }
4495 }
4496
4497 bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
4498 const wxMouseEvent& event)
4499 {
4500 if ( event.LeftDClick() || event.LeftDown() || event.RightDown() )
4501 {
4502 wxTopLevelWindow *tlw =
4503 wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
4504
4505 long hit = tlw->HitTest(event.GetPosition());
4506
4507 if ( event.LeftDClick() && hit == wxHT_TOPLEVEL_TITLEBAR )
4508 {
4509 tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
4510 tlw->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4511 : wxTOPLEVEL_BUTTON_MAXIMIZE);
4512 return TRUE;
4513 }
4514 else if ( tlw->GetWindowStyle() & wxSYSTEM_MENU )
4515 {
4516 if ( (event.LeftDown() && hit == wxHT_TOPLEVEL_ICON) ||
4517 (event.RightDown() &&
4518 (hit == wxHT_TOPLEVEL_TITLEBAR ||
4519 hit == wxHT_TOPLEVEL_ICON)) )
4520 {
4521 PopupSystemMenu(tlw, event.GetPosition());
4522 return TRUE;
4523 }
4524 }
4525 }
4526
4527 return wxStdFrameInputHandler::HandleMouse(consumer, event);
4528 }
4529
4530 void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window,
4531 const wxPoint& pos) const
4532 {
4533 wxMenu *menu = new wxMenu;
4534
4535 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
4536 menu->Append(wxID_RESTORE_FRAME , _("&Restore"));
4537 menu->Append(wxID_MOVE_FRAME , _("&Move"));
4538 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
4539 menu->Append(wxID_RESIZE_FRAME , _("&Size"));
4540 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME) )
4541 menu->Append(wxID_ICONIZE_FRAME , _("Mi&nimize"));
4542 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
4543 menu->Append(wxID_MAXIMIZE_FRAME , _("Ma&ximize"));
4544 menu->AppendSeparator();
4545 menu->Append(wxID_CLOSE_FRAME, _("Close\tAlt-F4"));
4546
4547 if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
4548 {
4549 if ( window->IsMaximized() )
4550 {
4551 menu->Enable(wxID_MAXIMIZE_FRAME, FALSE);
4552 menu->Enable(wxID_MOVE_FRAME, FALSE);
4553 if ( window->GetWindowStyle() & wxRESIZE_BORDER )
4554 menu->Enable(wxID_RESIZE_FRAME, FALSE);
4555 }
4556 else
4557 menu->Enable(wxID_RESTORE_FRAME, FALSE);
4558 }
4559
4560 window->PopupMenu(menu, pos);
4561 delete menu;
4562 }
4563
4564 bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
4565 bool activated)
4566 {
4567 if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
4568 {
4569 // always detach if active frame changed:
4570 m_menuHandler->Detach();
4571
4572 if ( activated )
4573 {
4574 m_menuHandler->Attach(consumer);
4575 }
4576 }
4577
4578 return wxStdFrameInputHandler::HandleActivation(consumer, activated);
4579 }