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