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