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