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