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