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