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