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