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