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