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