]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/win32.cpp
wxMac: wxUniversal integration steps
[wxWidgets.git] / src / univ / themes / win32.cpp
CommitLineData
1e6feb95
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: univ/themes/win32.cpp
3// Purpose: wxUniversal theme implementing Win32-like LNF
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 06.08.00
7// RCS-ID: $Id$
442b35b5 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
1e6feb95
VZ
9// Licence: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/timer.h"
29 #include "wx/intl.h"
30 #include "wx/dc.h"
31 #include "wx/window.h"
32
33 #include "wx/dcmemory.h"
34
35 #include "wx/button.h"
36 #include "wx/listbox.h"
37 #include "wx/checklst.h"
8cb172b4 38 #include "wx/combobox.h"
1e6feb95
VZ
39 #include "wx/scrolbar.h"
40 #include "wx/slider.h"
41 #include "wx/textctrl.h"
42#endif // WX_PRECOMP
43
44#include "wx/notebook.h"
45#include "wx/spinbutt.h"
8cb172b4 46#include "wx/settings.h"
8a46f9b1 47#include "wx/menu.h"
1e6feb95
VZ
48
49#include "wx/univ/scrtimer.h"
50
51#include "wx/univ/renderer.h"
52#include "wx/univ/inphand.h"
53#include "wx/univ/colschem.h"
54#include "wx/univ/theme.h"
55
56// ----------------------------------------------------------------------------
57// constants
58// ----------------------------------------------------------------------------
59
60static const int BORDER_THICKNESS = 2;
61
62// the offset between the label and focus rect around it
63static const int FOCUS_RECT_OFFSET_X = 1;
64static const int FOCUS_RECT_OFFSET_Y = 1;
65
66enum IndicatorType
67{
68 IndicatorType_Check,
69 IndicatorType_Radio,
70 IndicatorType_Menu,
71 IndicatorType_Max
72};
73
74enum IndicatorState
75{
76 IndicatorState_Normal,
77 IndicatorState_Pressed, // this one is for check/radioboxes
78 IndicatorState_Selected = IndicatorState_Pressed, // for menus
79 IndicatorState_Disabled,
80 IndicatorState_SelectedDisabled, // only for the menus
81 IndicatorState_Max
82};
83
84enum IndicatorStatus
85{
86 IndicatorStatus_Checked,
87 IndicatorStatus_Unchecked,
88 IndicatorStatus_Max
89};
90
91// ----------------------------------------------------------------------------
92// wxWin32Renderer: draw the GUI elements in Win32 style
93// ----------------------------------------------------------------------------
94
95class wxWin32Renderer : public wxRenderer
96{
97public:
98 // constants
99 enum wxArrowDirection
100 {
101 Arrow_Left,
102 Arrow_Right,
103 Arrow_Up,
104 Arrow_Down,
105 Arrow_Max
106 };
107
108 enum wxArrowStyle
109 {
110 Arrow_Normal,
111 Arrow_Disabled,
112 Arrow_Pressed,
113 Arrow_Inversed,
114 Arrow_InversedDisabled,
115 Arrow_StateMax
116 };
117
118 // ctor
119 wxWin32Renderer(const wxColourScheme *scheme);
120
121 // implement the base class pure virtuals
122 virtual void DrawBackground(wxDC& dc,
123 const wxColour& col,
124 const wxRect& rect,
125 int flags = 0);
126 virtual void DrawLabel(wxDC& dc,
127 const wxString& label,
128 const wxRect& rect,
129 int flags = 0,
130 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
131 int indexAccel = -1,
132 wxRect *rectBounds = NULL);
133 virtual void DrawButtonLabel(wxDC& dc,
134 const wxString& label,
135 const wxBitmap& image,
136 const wxRect& rect,
137 int flags = 0,
138 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
139 int indexAccel = -1,
140 wxRect *rectBounds = NULL);
141 virtual void DrawBorder(wxDC& dc,
142 wxBorder border,
143 const wxRect& rect,
144 int flags = 0,
145 wxRect *rectIn = (wxRect *)NULL);
146 virtual void DrawHorizontalLine(wxDC& dc,
147 wxCoord y, wxCoord x1, wxCoord x2);
148 virtual void DrawVerticalLine(wxDC& dc,
149 wxCoord x, wxCoord y1, wxCoord y2);
150 virtual void DrawFrame(wxDC& dc,
151 const wxString& label,
152 const wxRect& rect,
153 int flags = 0,
154 int alignment = wxALIGN_LEFT,
155 int indexAccel = -1);
156 virtual void DrawTextBorder(wxDC& dc,
157 wxBorder border,
158 const wxRect& rect,
159 int flags = 0,
160 wxRect *rectIn = (wxRect *)NULL);
161 virtual void DrawButtonBorder(wxDC& dc,
162 const wxRect& rect,
163 int flags = 0,
164 wxRect *rectIn = (wxRect *)NULL);
165 virtual void DrawArrow(wxDC& dc,
166 wxDirection dir,
167 const wxRect& rect,
168 int flags = 0);
169 virtual void DrawScrollbarArrow(wxDC& dc,
170 wxDirection dir,
171 const wxRect& rect,
172 int flags = 0)
173 { DrawArrow(dc, dir, rect, flags); }
174 virtual void DrawScrollbarThumb(wxDC& dc,
175 wxOrientation orient,
176 const wxRect& rect,
177 int flags = 0);
178 virtual void DrawScrollbarShaft(wxDC& dc,
179 wxOrientation orient,
180 const wxRect& rect,
181 int flags = 0);
182 virtual void DrawScrollCorner(wxDC& dc,
183 const wxRect& rect);
184 virtual void DrawItem(wxDC& dc,
185 const wxString& label,
186 const wxRect& rect,
187 int flags = 0);
188 virtual void DrawCheckItem(wxDC& dc,
189 const wxString& label,
190 const wxBitmap& bitmap,
191 const wxRect& rect,
192 int flags = 0);
193 virtual void DrawCheckButton(wxDC& dc,
194 const wxString& label,
195 const wxBitmap& bitmap,
196 const wxRect& rect,
197 int flags = 0,
198 wxAlignment align = wxALIGN_LEFT,
199 int indexAccel = -1);
200 virtual void DrawRadioButton(wxDC& dc,
201 const wxString& label,
202 const wxBitmap& bitmap,
203 const wxRect& rect,
204 int flags = 0,
205 wxAlignment align = wxALIGN_LEFT,
206 int indexAccel = -1);
207 virtual void DrawTextLine(wxDC& dc,
208 const wxString& text,
209 const wxRect& rect,
210 int selStart = -1,
211 int selEnd = -1,
212 int flags = 0);
213 virtual void DrawLineWrapMark(wxDC& dc, const wxRect& rect);
214 virtual void DrawTab(wxDC& dc,
215 const wxRect& rect,
216 wxDirection dir,
217 const wxString& label,
218 const wxBitmap& bitmap = wxNullBitmap,
219 int flags = 0,
220 int indexAccel = -1);
221
222 virtual void DrawSliderShaft(wxDC& dc,
223 const wxRect& rect,
224 wxOrientation orient,
225 int flags = 0,
226 wxRect *rectShaft = NULL);
227 virtual void DrawSliderThumb(wxDC& dc,
228 const wxRect& rect,
229 wxOrientation orient,
230 int flags = 0);
231 virtual void DrawSliderTicks(wxDC& dc,
232 const wxRect& rect,
233 const wxSize& sizeThumb,
234 wxOrientation orient,
235 int start,
236 int end,
237 int step = 1,
238 int flags = 0);
e766c8a9 239#if wxUSE_MENUS
1e6feb95
VZ
240
241 virtual void DrawMenuBarItem(wxDC& dc,
242 const wxRect& rect,
243 const wxString& label,
244 int flags = 0,
245 int indexAccel = -1);
246 virtual void DrawMenuItem(wxDC& dc,
247 wxCoord y,
248 const wxMenuGeometryInfo& geometryInfo,
249 const wxString& label,
250 const wxString& accel,
251 const wxBitmap& bitmap = wxNullBitmap,
252 int flags = 0,
253 int indexAccel = -1);
254 virtual void DrawMenuSeparator(wxDC& dc,
255 wxCoord y,
256 const wxMenuGeometryInfo& geomInfo);
e766c8a9 257#endif
1e6feb95
VZ
258 virtual void GetComboBitmaps(wxBitmap *bmpNormal,
259 wxBitmap *bmpPressed,
260 wxBitmap *bmpDisabled);
261
262 virtual void AdjustSize(wxSize *size, const wxWindow *window);
263 virtual wxRect GetBorderDimensions(wxBorder border) const;
264 virtual bool AreScrollbarsInsideBorder() const;
265
266 virtual wxSize GetScrollbarArrowSize() const
267 { return m_sizeScrollbarArrow; }
268 virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
269 wxScrollBar::Element elem,
270 int thumbPos = -1) const;
271 virtual wxCoord GetScrollbarSize(const wxScrollBar *scrollbar);
272 virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
273 const wxPoint& pt) const;
274 virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
275 int thumbPos = -1);
276 virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
277 virtual wxCoord GetListboxItemHeight(wxCoord fontHeight)
278 { return fontHeight + 2; }
279 virtual wxSize GetCheckBitmapSize() const
280 { return wxSize(13, 13); }
281 virtual wxSize GetRadioBitmapSize() const
282 { return wxSize(12, 12); }
283 virtual wxCoord GetCheckItemMargin() const
284 { return 0; }
285
286 virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
287 const wxRect& rect);
288 virtual wxRect GetTextClientArea(const wxTextCtrl *text,
289 const wxRect& rect,
290 wxCoord *extraSpaceBeyond);
291
292 virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
293 virtual wxSize GetTabPadding() const { return wxSize(6, 5); }
294
295 virtual wxCoord GetSliderDim() const { return 20; }
296 virtual wxCoord GetSliderTickLen() const { return 4; }
297 virtual wxRect GetSliderShaftRect(const wxRect& rect,
298 wxOrientation orient) const;
299 virtual wxSize GetSliderThumbSize(const wxRect& rect,
300 wxOrientation orient) const;
301 virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
302
e766c8a9 303#if wxUSE_MENUS
1e6feb95
VZ
304 virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const;
305 virtual wxMenuGeometryInfo *GetMenuGeometry(wxWindow *win,
306 const wxMenu& menu) const;
e766c8a9 307#endif
1e6feb95
VZ
308protected:
309 // helper of DrawLabel() and DrawCheckOrRadioButton()
310 void DoDrawLabel(wxDC& dc,
311 const wxString& label,
312 const wxRect& rect,
313 int flags = 0,
314 int alignment = wxALIGN_LEFT | wxALIGN_TOP,
315 int indexAccel = -1,
316 wxRect *rectBounds = NULL,
317 const wxPoint& focusOffset
318 = wxPoint(FOCUS_RECT_OFFSET_X, FOCUS_RECT_OFFSET_Y));
319
320 // common part of DrawLabel() and DrawItem()
321 void DrawFocusRect(wxDC& dc, const wxRect& rect);
322
323 // DrawLabel() and DrawButtonLabel() helper
324 void DrawLabelShadow(wxDC& dc,
325 const wxString& label,
326 const wxRect& rect,
327 int alignment,
328 int indexAccel);
329
330 // DrawButtonBorder() helper
331 void DoDrawBackground(wxDC& dc,
332 const wxColour& col,
333 const wxRect& rect);
334
335 // DrawBorder() helpers: all of them shift and clip the DC after drawing
336 // the border
337
338 // just draw a rectangle with the given pen
339 void DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen);
340
341 // draw the lower left part of rectangle
342 void DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen);
343
344 // draw the rectange using the first brush for the left and top sides and
345 // the second one for the bottom and right ones
346 void DrawShadedRect(wxDC& dc, wxRect *rect,
347 const wxPen& pen1, const wxPen& pen2);
348
349 // draw the normal 3D border
350 void DrawRaisedBorder(wxDC& dc, wxRect *rect);
351
352 // draw the sunken 3D border
353 void DrawSunkenBorder(wxDC& dc, wxRect *rect);
354
355 // draw the border used for scrollbar arrows
356 void DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed = FALSE);
357
358 // public DrawArrow()s helper
359 void DrawArrow(wxDC& dc, const wxRect& rect,
360 wxArrowDirection arrowDir, wxArrowStyle arrowStyle);
361
362 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
363 void DrawArrowButton(wxDC& dc, const wxRect& rect,
364 wxArrowDirection arrowDir,
365 wxArrowStyle arrowStyle);
366
367 // DrawCheckButton/DrawRadioButton helper
368 void DrawCheckOrRadioButton(wxDC& dc,
369 const wxString& label,
370 const wxBitmap& bitmap,
371 const wxRect& rect,
372 int flags,
373 wxAlignment align,
374 int indexAccel,
375 wxCoord focusOffsetY);
376
377 // draw a normal or transposed line (useful for using the same code fo both
378 // horizontal and vertical widgets)
379 void DrawLine(wxDC& dc,
380 wxCoord x1, wxCoord y1,
381 wxCoord x2, wxCoord y2,
382 bool transpose = FALSE)
383 {
384 if ( transpose )
385 dc.DrawLine(y1, x1, y2, x2);
386 else
387 dc.DrawLine(x1, y1, x2, y2);
388 }
389
390 // get the standard check/radio button bitmap
391 wxBitmap GetIndicator(IndicatorType indType, int flags);
392 wxBitmap GetCheckBitmap(int flags)
393 { return GetIndicator(IndicatorType_Check, flags); }
394 wxBitmap GetRadioBitmap(int flags)
395 { return GetIndicator(IndicatorType_Radio, flags); }
396
397private:
398 const wxColourScheme *m_scheme;
399
400 // the sizing parameters (TODO make them changeable)
401 wxSize m_sizeScrollbarArrow;
402
403 // GDI objects we use for drawing
404 wxColour m_colDarkGrey,
405 m_colHighlight;
406
407 wxPen m_penBlack,
408 m_penDarkGrey,
409 m_penLightGrey,
410 m_penHighlight;
411
412 // first row is for the normal state, second - for the disabled
413 wxBitmap m_bmpArrows[Arrow_StateMax][Arrow_Max];
414};
415
416// ----------------------------------------------------------------------------
417// wxWin32InputHandler and derived classes: process the keyboard and mouse
418// messages according to Windows standards
419// ----------------------------------------------------------------------------
420
421class wxWin32InputHandler : public wxInputHandler
422{
423public:
424 wxWin32InputHandler(wxWin32Renderer *renderer);
425
426 virtual bool HandleKey(wxControl *control,
427 const wxKeyEvent& event,
428 bool pressed);
429 virtual bool HandleMouse(wxControl *control,
430 const wxMouseEvent& event);
431
432protected:
433 wxWin32Renderer *m_renderer;
434};
435
436class wxWin32ScrollBarInputHandler : public wxStdScrollBarInputHandler
437{
438public:
439 wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
440 wxInputHandler *handler);
441
442 virtual bool HandleMouse(wxControl *control, const wxMouseEvent& event);
443 virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event);
444
445 virtual bool OnScrollTimer(wxScrollBar *scrollbar,
446 const wxControlAction& action);
447
448protected:
449 virtual bool IsAllowedButton(int button) { return button == 1; }
450
451 virtual void Highlight(wxScrollBar *scrollbar, bool doIt)
452 {
453 // we don't highlight anything
454 }
455
456 // the first and last event which caused the thumb to move
457 wxMouseEvent m_eventStartDrag,
458 m_eventLastDrag;
459
460 // have we paused the scrolling because the mouse moved?
461 bool m_scrollPaused;
462
463 // we remember the interval of the timer to be able to restart it
464 int m_interval;
465};
466
467class wxWin32CheckboxInputHandler : public wxStdCheckboxInputHandler
468{
469public:
470 wxWin32CheckboxInputHandler(wxInputHandler *handler)
471 : wxStdCheckboxInputHandler(handler) { }
472
473 virtual bool HandleKey(wxControl *control,
474 const wxKeyEvent& event,
475 bool pressed);
476};
477
478class wxWin32TextCtrlInputHandler : public wxStdTextCtrlInputHandler
479{
480public:
481 wxWin32TextCtrlInputHandler(wxInputHandler *handler)
482 : wxStdTextCtrlInputHandler(handler) { }
483
484 virtual bool HandleKey(wxControl *control,
485 const wxKeyEvent& event,
486 bool pressed);
487};
488
489// ----------------------------------------------------------------------------
490// wxWin32ColourScheme: uses (default) Win32 colours
491// ----------------------------------------------------------------------------
492
493class wxWin32ColourScheme : public wxColourScheme
494{
495public:
496 virtual wxColour Get(StdColour col) const;
497 virtual wxColour GetBackground(wxWindow *win) const;
498};
499
500// ----------------------------------------------------------------------------
501// wxWin32Theme
502// ----------------------------------------------------------------------------
503
504WX_DEFINE_ARRAY(wxInputHandler *, wxArrayHandlers);
505
506class wxWin32Theme : public wxTheme
507{
508public:
509 wxWin32Theme();
510 virtual ~wxWin32Theme();
511
512 virtual wxRenderer *GetRenderer() { return m_renderer; }
513 virtual wxInputHandler *GetInputHandler(const wxString& control);
514 virtual wxColourScheme *GetColourScheme();
515
516private:
517 // get the default input handler
518 wxInputHandler *GetDefaultInputHandler();
519
520 wxWin32Renderer *m_renderer;
521
522 // the names of the already created handlers and the handlers themselves
523 // (these arrays are synchronized)
524 wxSortedArrayString m_handlerNames;
525 wxArrayHandlers m_handlers;
526
527 wxWin32InputHandler *m_handlerDefault;
528
529 wxWin32ColourScheme *m_scheme;
530
531 WX_DECLARE_THEME(win32)
532};
533
534// ----------------------------------------------------------------------------
535// standard bitmaps
536// ----------------------------------------------------------------------------
537
538// menu bitmaps
539
540static const char *checked_menu_xpm[] = {
541/* columns rows colors chars-per-pixel */
542"9 9 2 1",
543"w c None",
544"b c black",
545/* pixels */
546"wwwwwwwww",
547"wwwwwwwbw",
548"wwwwwwbbw",
549"wbwwwbbbw",
550"wbbwbbbww",
551"wbbbbbwww",
552"wwbbbwwww",
553"wwwbwwwww",
554"wwwwwwwww"
555};
556
557static const char *selected_checked_menu_xpm[] = {
558/* columns rows colors chars-per-pixel */
559"9 9 2 1",
560"w c None",
561"b c white",
562/* pixels */
563"wwwwwwwww",
564"wwwwwwwbw",
565"wwwwwwbbw",
566"wbwwwbbbw",
567"wbbwbbbww",
568"wbbbbbwww",
569"wwbbbwwww",
570"wwwbwwwww",
571"wwwwwwwww"
572};
573
574static const char *disabled_checked_menu_xpm[] = {
575/* columns rows colors chars-per-pixel */
576"9 9 3 1",
577"w c None",
578"b c #7f7f7f",
579"W c #e0e0e0",
580/* pixels */
581"wwwwwwwww",
582"wwwwwwwbw",
583"wwwwwwbbW",
584"wbwwwbbbW",
585"wbbwbbbWW",
586"wbbbbbWWw",
587"wwbbbWWww",
588"wwwbWWwww",
589"wwwwWwwww"
590};
591
592static const char *selected_disabled_checked_menu_xpm[] = {
593/* columns rows colors chars-per-pixel */
594"9 9 2 1",
595"w c None",
596"b c #7f7f7f",
597/* pixels */
598"wwwwwwwww",
599"wwwwwwwbw",
600"wwwwwwbbw",
601"wbwwwbbbw",
602"wbbwbbbww",
603"wbbbbbwww",
604"wwbbbwwww",
605"wwwbwwwww",
606"wwwwwwwww"
607};
608
609// checkbox and radiobox bitmaps below
610
611static const char *checked_xpm[] = {
612/* columns rows colors chars-per-pixel */
613"13 13 5 1",
614"w c white",
615"b c black",
616"d c #7f7f7f",
617"g c #c0c0c0",
618"h c #e0e0e0",
619/* pixels */
620"ddddddddddddh",
621"dbbbbbbbbbbgh",
622"dbwwwwwwwwwgh",
623"dbwwwwwwwbwgh",
624"dbwwwwwwbbwgh",
625"dbwbwwwbbbwgh",
626"dbwbbwbbbwwgh",
627"dbwbbbbbwwwgh",
628"dbwwbbbwwwwgh",
629"dbwwwbwwwwwgh",
630"dbwwwwwwwwwgh",
631"dgggggggggggh",
632"hhhhhhhhhhhhh"
633};
634
635static const char *pressed_checked_xpm[] = {
636/* columns rows colors chars-per-pixel */
637"13 13 4 1",
638"b c black",
639"d c #7f7f7f",
640"g c #c0c0c0",
641"h c #e0e0e0",
642/* pixels */
643"ddddddddddddh",
644"dbbbbbbbbbbgh",
645"dbggggggggggh",
646"dbgggggggbggh",
647"dbggggggbbggh",
648"dbgbgggbbbggh",
649"dbgbbgbbbgggh",
650"dbgbbbbbggggh",
651"dbggbbbgggggh",
652"dbgggbggggggh",
653"dbggggggggggh",
654"dgggggggggggh",
655"hhhhhhhhhhhhh"
656};
657
658static const char *pressed_disabled_checked_xpm[] = {
659/* columns rows colors chars-per-pixel */
660"13 13 4 1",
661"b c black",
662"d c #7f7f7f",
663"g c #c0c0c0",
664"h c #e0e0e0",
665/* pixels */
666"ddddddddddddh",
667"dbbbbbbbbbbgh",
668"dbggggggggggh",
669"dbgggggggdggh",
670"dbggggggddggh",
671"dbgdgggdddggh",
672"dbgddgdddgggh",
673"dbgdddddggggh",
674"dbggdddgggggh",
675"dbgggdggggggh",
676"dbggggggggggh",
677"dgggggggggggh",
678"hhhhhhhhhhhhh"
679};
680
681static const char *checked_item_xpm[] = {
682/* columns rows colors chars-per-pixel */
683"13 13 3 1",
684"w c white",
685"b c black",
686"d c #808080",
687/* pixels */
688"wwwwwwwwwwwww",
689"wdddddddddddw",
690"wdwwwwwwwwwdw",
691"wdwwwwwwwbwdw",
692"wdwwwwwwbbwdw",
693"wdwbwwwbbbwdw",
694"wdwbbwbbbwwdw",
695"wdwbbbbbwwwdw",
696"wdwwbbbwwwwdw",
697"wdwwwbwwwwwdw",
698"wdwwwwwwwwwdw",
699"wdddddddddddw",
700"wwwwwwwwwwwww"
701};
702
703static const char *unchecked_xpm[] = {
704/* columns rows colors chars-per-pixel */
705"13 13 5 1",
706"w c white",
707"b c black",
708"d c #7f7f7f",
709"g c #c0c0c0",
710"h c #e0e0e0",
711/* pixels */
712"ddddddddddddh",
713"dbbbbbbbbbbgh",
714"dbwwwwwwwwwgh",
715"dbwwwwwwwwwgh",
716"dbwwwwwwwwwgh",
717"dbwwwwwwwwwgh",
718"dbwwwwwwwwwgh",
719"dbwwwwwwwwwgh",
720"dbwwwwwwwwwgh",
721"dbwwwwwwwwwgh",
722"dbwwwwwwwwwgh",
723"dgggggggggggh",
724"hhhhhhhhhhhhh"
725};
726
727static const char *pressed_unchecked_xpm[] = {
728/* columns rows colors chars-per-pixel */
729"13 13 4 1",
730"b c black",
731"d c #7f7f7f",
732"g c #c0c0c0",
733"h c #e0e0e0",
734/* pixels */
735"ddddddddddddh",
736"dbbbbbbbbbbgh",
737"dbggggggggggh",
738"dbggggggggggh",
739"dbggggggggggh",
740"dbggggggggggh",
741"dbggggggggggh",
742"dbggggggggggh",
743"dbggggggggggh",
744"dbggggggggggh",
745"dbggggggggggh",
746"dbggggggggggh",
747"hhhhhhhhhhhhh"
748};
749
750static const char *unchecked_item_xpm[] = {
751/* columns rows colors chars-per-pixel */
752"13 13 2 1",
753"w c white",
754"d c #808080",
755/* pixels */
756"wwwwwwwwwwwww",
757"wdddddddddddw",
758"wdwwwwwwwwwdw",
759"wdwwwwwwwwwdw",
760"wdwwwwwwwwwdw",
761"wdwwwwwwwwwdw",
762"wdwwwwwwwwwdw",
763"wdwwwwwwwwwdw",
764"wdwwwwwwwwwdw",
765"wdwwwwwwwwwdw",
766"wdwwwwwwwwwdw",
767"wdddddddddddw",
768"wwwwwwwwwwwww"
769};
770
771static const char *checked_radio_xpm[] = {
772/* columns rows colors chars-per-pixel */
773"12 12 6 1",
774" c None",
775"w c white",
776"b c black",
777"d c #7f7f7f",
778"g c #c0c0c0",
779"h c #e0e0e0",
780/* pixels */
781" dddd ",
782" ddbbbbdd ",
783" dbbwwwwbbh ",
784" dbwwwwwwgh ",
785"dbwwwbbwwwgh",
786"dbwwbbbbwwgh",
787"dbwwbbbbwwgh",
788"dbwwwbbwwwgh",
789" dbwwwwwwgh ",
790" dggwwwwggh ",
791" hhgggghh ",
792" hhhh "
793};
794
795static const char *pressed_checked_radio_xpm[] = {
796/* columns rows colors chars-per-pixel */
797"12 12 6 1",
798" c None",
799"w c white",
800"b c black",
801"d c #7f7f7f",
802"g c #c0c0c0",
803"h c #e0e0e0",
804/* pixels */
805" dddd ",
806" ddbbbbdd ",
807" dbbggggbbh ",
808" dbgggggggh ",
809"dbgggbbggggh",
810"dbggbbbbgggh",
811"dbggbbbbgggh",
812"dbgggbbggggh",
813" dbgggggggh ",
814" dggggggggh ",
815" hhgggghh ",
816" hhhh "
817};
818
819static const char *pressed_disabled_checked_radio_xpm[] = {
820/* columns rows colors chars-per-pixel */
821"12 12 6 1",
822" c None",
823"w c white",
824"b c black",
825"d c #7f7f7f",
826"g c #c0c0c0",
827"h c #e0e0e0",
828/* pixels */
829" dddd ",
830" ddbbbbdd ",
831" dbbggggbbh ",
832" dbgggggggh ",
833"dbgggddggggh",
834"dbggddddgggh",
835"dbggddddgggh",
836"dbgggddggggh",
837" dbgggggggh ",
838" dggggggggh ",
839" hhgggghh ",
840" hhhh ",
841};
842
843static const char *unchecked_radio_xpm[] = {
844/* columns rows colors chars-per-pixel */
845"12 12 6 1",
846" c None",
847"w c white",
848"b c black",
849"d c #7f7f7f",
850"g c #c0c0c0",
851"h c #e0e0e0",
852/* pixels */
853" dddd ",
854" ddbbbbdd ",
855" dbbwwwwbbh ",
856" dbwwwwwwgh ",
857"dbwwwwwwwwgh",
858"dbwwwwwwwwgh",
859"dbwwwwwwwwgh",
860"dbwwwwwwwwgh",
861" dbwwwwwwgh ",
862" dggwwwwggh ",
863" hhgggghh ",
864" hhhh "
865};
866
867static const char *pressed_unchecked_radio_xpm[] = {
868/* columns rows colors chars-per-pixel */
869"12 12 6 1",
870" c None",
871"w c white",
872"b c black",
873"d c #7f7f7f",
874"g c #c0c0c0",
875"h c #e0e0e0",
876/* pixels */
877" dddd ",
878" ddbbbbdd ",
879" dbbggggbbh ",
880" dbgggggggh ",
881"dbgggggggggh",
882"dbgggggggggh",
883"dbgggggggggh",
884"dbgggggggggh",
885" dbgggggggh ",
886" dggggggggh ",
887" hhgggghh ",
888" hhhh "
889};
890
891static const char **
892 bmpIndicators[IndicatorType_Max][IndicatorState_Max][IndicatorStatus_Max] =
893{
894 // checkboxes first
895 {
896 // normal state
897 { checked_xpm, unchecked_xpm },
898
899 // pressed state
900 { pressed_checked_xpm, pressed_unchecked_xpm },
901
902 // disabled state
903 { pressed_disabled_checked_xpm, pressed_unchecked_xpm },
904 },
905
906 // radio
907 {
908 // normal state
909 { checked_radio_xpm, unchecked_radio_xpm },
910
911 // pressed state
912 { pressed_checked_radio_xpm, pressed_unchecked_radio_xpm },
913
914 // disabled state
915 { pressed_disabled_checked_radio_xpm, pressed_unchecked_radio_xpm },
916 },
917
918 // menu
919 {
920 // normal state
921 { checked_menu_xpm, NULL },
922
923 // selected state
924 { selected_checked_menu_xpm, NULL },
925
926 // disabled state
927 { disabled_checked_menu_xpm, NULL },
928
929 // disabled selected state
930 { selected_disabled_checked_menu_xpm, NULL },
931 }
932};
933
934// ============================================================================
935// implementation
936// ============================================================================
937
938WX_IMPLEMENT_THEME(wxWin32Theme, win32, wxTRANSLATE("Win32 theme"));
939
940// ----------------------------------------------------------------------------
941// wxWin32Theme
942// ----------------------------------------------------------------------------
943
944wxWin32Theme::wxWin32Theme()
945{
946 m_scheme = new wxWin32ColourScheme;
947 m_renderer = new wxWin32Renderer(m_scheme);
948 m_handlerDefault = NULL;
949}
950
951wxWin32Theme::~wxWin32Theme()
952{
953 size_t count = m_handlers.GetCount();
954 for ( size_t n = 0; n < count; n++ )
955 {
956 if ( m_handlers[n] != m_handlerDefault )
957 delete m_handlers[n];
958 }
959
960 delete m_handlerDefault;
961
962 delete m_renderer;
963 delete m_scheme;
964}
965
966wxInputHandler *wxWin32Theme::GetDefaultInputHandler()
967{
968 if ( !m_handlerDefault )
969 {
970 m_handlerDefault = new wxWin32InputHandler(m_renderer);
971 }
972
973 return m_handlerDefault;
974}
975
976wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control)
977{
978 wxInputHandler *handler;
979 int n = m_handlerNames.Index(control);
980 if ( n == wxNOT_FOUND )
981 {
982 // create a new handler
983 if ( control == wxINP_HANDLER_SCROLLBAR )
984 handler = new wxWin32ScrollBarInputHandler(m_renderer,
985 GetDefaultInputHandler());
986#if wxUSE_BUTTON
987 else if ( control == wxINP_HANDLER_BUTTON )
988 handler = new wxStdButtonInputHandler(GetDefaultInputHandler());
989#endif // wxUSE_BUTTON
990#if wxUSE_CHECKBOX
991 else if ( control == wxINP_HANDLER_CHECKBOX )
992 handler = new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
993#endif // wxUSE_CHECKBOX
994#if wxUSE_COMBOBOX
995 else if ( control == wxINP_HANDLER_COMBOBOX )
996 handler = new wxStdComboBoxInputHandler(GetDefaultInputHandler());
997#endif // wxUSE_COMBOBOX
998#if wxUSE_LISTBOX
999 else if ( control == wxINP_HANDLER_LISTBOX )
1000 handler = new wxStdListboxInputHandler(GetDefaultInputHandler());
1001#endif // wxUSE_LISTBOX
1002#if wxUSE_CHECKLISTBOX
1003 else if ( control == wxINP_HANDLER_CHECKLISTBOX )
1004 handler = new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1005#endif // wxUSE_CHECKLISTBOX
1006#if wxUSE_TEXTCTRL
1007 else if ( control == wxINP_HANDLER_TEXTCTRL )
1008 handler = new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1009#endif // wxUSE_TEXTCTRL
1010#if wxUSE_SLIDER
1011 else if ( control == wxINP_HANDLER_SLIDER )
1012 handler = new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1013#endif // wxUSE_SLIDER
1014#if wxUSE_SPINBTN
1015 else if ( control == wxINP_HANDLER_SPINBTN )
1016 handler = new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1017#endif // wxUSE_SPINBTN
1018#if wxUSE_NOTEBOOK
1019 else if ( control == wxINP_HANDLER_NOTEBOOK )
1020 handler = new wxStdNotebookInputHandler(GetDefaultInputHandler());
1021#endif // wxUSE_NOTEBOOK
1022 else
1023 handler = GetDefaultInputHandler();
1024
1025 n = m_handlerNames.Add(control);
1026 m_handlers.Insert(handler, n);
1027 }
1028 else // we already have it
1029 {
1030 handler = m_handlers[n];
1031 }
1032
1033 return handler;
1034}
1035
1036wxColourScheme *wxWin32Theme::GetColourScheme()
1037{
1038 return m_scheme;
1039}
1040
1041// ============================================================================
1042// wxWin32ColourScheme
1043// ============================================================================
1044
1045wxColour wxWin32ColourScheme::GetBackground(wxWindow *win) const
1046{
1047 wxColour col;
1048 if ( win->UseBgCol() )
1049 {
1050 // use the user specified colour
1051 col = win->GetBackgroundColour();
1052 }
1053
1054 if ( win->IsContainerWindow() )
1055 {
1056 wxTextCtrl *text = wxDynamicCast(win, wxTextCtrl);
1057 if ( text )
1058 {
1059 if ( !text->IsEnabled() ) // not IsEditable()
1060 col = Get(CONTROL);
1061 //else: execute code below
1062 }
1063
1064 if ( !col.Ok() )
1065 {
1066 // doesn't depend on the state
1067 col = Get(WINDOW);
1068 }
1069 }
1070 else
1071 {
1072 int flags = win->GetStateFlags();
1073
1074 // the colour set by the user should be used for the normal state
1075 // and for the states for which we don't have any specific colours
1076 if ( !col.Ok() || (flags != 0) )
1077 {
1078 if ( wxDynamicCast(win, wxScrollBar) )
1079 col = Get(flags & wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
1080 : SCROLLBAR);
1081 else
1082 col = Get(CONTROL);
1083 }
1084 }
1085
1086 return col;
1087}
1088
1089wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const
1090{
1091 switch ( col )
1092 {
1093 case WINDOW: return *wxWHITE;
1094
1095 case CONTROL_PRESSED:
1096 case CONTROL_CURRENT:
1097 case CONTROL: return wxColour(0xc0c0c0);
1098
1099 case CONTROL_TEXT: return *wxBLACK;
1100
1101 case SCROLLBAR: return wxColour(0xe0e0e0);
1102 case SCROLLBAR_PRESSED: return *wxBLACK;
1103
1104 case HIGHLIGHT: return wxColour(0x800000);
1105 case HIGHLIGHT_TEXT: return wxColour(0xffffff);
1106
1107 case SHADOW_DARK: return *wxBLACK;
1108
1109 case CONTROL_TEXT_DISABLED:
1110 case SHADOW_HIGHLIGHT: return wxColour(0xe0e0e0);
1111
1112 case SHADOW_IN: return wxColour(0xc0c0c0);
1113
1114 case CONTROL_TEXT_DISABLED_SHADOW:
1115 case SHADOW_OUT: return wxColour(0x7f7f7f);
1116
1117 case MAX:
1118 default:
1119 wxFAIL_MSG(_T("invalid standard colour"));
1120 return *wxBLACK;
1121 }
1122}
1123
1124// ============================================================================
1125// wxWin32Renderer
1126// ============================================================================
1127
1128// ----------------------------------------------------------------------------
1129// construction
1130// ----------------------------------------------------------------------------
1131
1132wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme)
1133{
1134 // init data
1135 m_scheme = scheme;
1136 m_sizeScrollbarArrow = wxSize(16, 16);
1137
1138 // init colours and pens
1139 m_penBlack = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_DARK), 0, wxSOLID);
1140
1141 m_colDarkGrey = wxSCHEME_COLOUR(scheme, SHADOW_OUT);
1142 m_penDarkGrey = wxPen(m_colDarkGrey, 0, wxSOLID);
1143
1144 m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN), 0, wxSOLID);
1145
1146 m_colHighlight = wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT);
1147 m_penHighlight = wxPen(m_colHighlight, 0, wxSOLID);
1148
1149 // init the arrow bitmaps
1150 static const size_t ARROW_WIDTH = 7;
1151 static const size_t ARROW_LENGTH = 4;
1152
1153 wxMask *mask;
1154 wxMemoryDC dcNormal,
1155 dcDisabled,
1156 dcInverse;
1157 for ( size_t n = 0; n < Arrow_Max; n++ )
1158 {
1159 bool isVertical = n > Arrow_Right;
1160 int w, h;
1161 if ( isVertical )
1162 {
1163 w = ARROW_WIDTH;
1164 h = ARROW_LENGTH;
1165 }
1166 else
1167 {
1168 h = ARROW_WIDTH;
1169 w = ARROW_LENGTH;
1170 }
1171
1172 // disabled arrow is larger because of the shadow
1173 m_bmpArrows[Arrow_Normal][n].Create(w, h);
1174 m_bmpArrows[Arrow_Disabled][n].Create(w + 1, h + 1);
1175
1176 dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]);
1177 dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]);
1178
1179 dcNormal.SetBackground(*wxWHITE_BRUSH);
1180 dcDisabled.SetBackground(*wxWHITE_BRUSH);
1181 dcNormal.Clear();
1182 dcDisabled.Clear();
1183
1184 dcNormal.SetPen(m_penBlack);
1185 dcDisabled.SetPen(m_penDarkGrey);
1186
1187 // calculate the position of the point of the arrow
1188 wxCoord x1, y1;
1189 if ( isVertical )
1190 {
1191 x1 = (ARROW_WIDTH - 1)/2;
1192 y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1;
1193 }
1194 else // horizontal
1195 {
1196 x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1;
1197 y1 = (ARROW_WIDTH - 1)/2;
1198 }
1199
1200 wxCoord x2 = x1,
1201 y2 = y1;
1202
1203 if ( isVertical )
1204 x2++;
1205 else
1206 y2++;
1207
1208 for ( size_t i = 0; i < ARROW_LENGTH; i++ )
1209 {
1210 dcNormal.DrawLine(x1, y1, x2, y2);
1211 dcDisabled.DrawLine(x1, y1, x2, y2);
1212
1213 if ( isVertical )
1214 {
1215 x1--;
1216 x2++;
1217
1218 if ( n == Arrow_Up )
1219 {
1220 y1++;
1221 y2++;
1222 }
1223 else // down arrow
1224 {
1225 y1--;
1226 y2--;
1227 }
1228 }
1229 else // left or right arrow
1230 {
1231 y1--;
1232 y2++;
1233
1234 if ( n == Arrow_Left )
1235 {
1236 x1++;
1237 x2++;
1238 }
1239 else
1240 {
1241 x1--;
1242 x2--;
1243 }
1244 }
1245 }
1246
1247 // draw the shadow for the disabled one
1248 dcDisabled.SetPen(m_penHighlight);
1249 switch ( n )
1250 {
1251 case Arrow_Left:
1252 y1 += 2;
1253 dcDisabled.DrawLine(x1, y1, x2, y2);
1254 break;
1255
1256 case Arrow_Right:
1257 x1 = ARROW_LENGTH - 1;
1258 y1 = (ARROW_WIDTH - 1)/2 + 1;
1259 x2 = 0;
1260 y2 = ARROW_WIDTH;
1261 dcDisabled.DrawLine(x1, y1, x2, y2);
1262 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1263 break;
1264
1265 case Arrow_Up:
1266 x1 += 2;
1267 dcDisabled.DrawLine(x1, y1, x2, y2);
1268 break;
1269
1270 case Arrow_Down:
1271 x1 = ARROW_WIDTH - 1;
1272 y1 = 1;
1273 x2 = (ARROW_WIDTH - 1)/2;
1274 y2 = ARROW_LENGTH;
1275 dcDisabled.DrawLine(x1, y1, x2, y2);
1276 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
1277 break;
1278
1279 }
1280
1281 // create the inversed bitmap but only for the right arrow as we only
1282 // use it for the menus
1283 if ( n == Arrow_Right )
1284 {
1285 m_bmpArrows[Arrow_Inversed][n].Create(w, h);
1286 dcInverse.SelectObject(m_bmpArrows[Arrow_Inversed][n]);
1287 dcInverse.Clear();
1288 dcInverse.Blit(0, 0, w, h,
1289 &dcNormal, 0, 0,
1290 wxXOR);
1291 dcInverse.SelectObject(wxNullBitmap);
1292
1293 mask = new wxMask(m_bmpArrows[Arrow_Inversed][n], *wxBLACK);
1294 m_bmpArrows[Arrow_Inversed][n].SetMask(mask);
1295
1296 m_bmpArrows[Arrow_InversedDisabled][n].Create(w, h);
1297 dcInverse.SelectObject(m_bmpArrows[Arrow_InversedDisabled][n]);
1298 dcInverse.Clear();
1299 dcInverse.Blit(0, 0, w, h,
1300 &dcDisabled, 0, 0,
1301 wxXOR);
1302 dcInverse.SelectObject(wxNullBitmap);
1303
1304 mask = new wxMask(m_bmpArrows[Arrow_InversedDisabled][n], *wxBLACK);
1305 m_bmpArrows[Arrow_InversedDisabled][n].SetMask(mask);
1306 }
1307
1308 dcNormal.SelectObject(wxNullBitmap);
1309 dcDisabled.SelectObject(wxNullBitmap);
1310
1311 mask = new wxMask(m_bmpArrows[Arrow_Normal][n], *wxWHITE);
1312 m_bmpArrows[Arrow_Normal][n].SetMask(mask);
1313 mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
1314 m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
1315
1316 m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
1317 }
1318}
1319
1320// ----------------------------------------------------------------------------
1321// border stuff
1322// ----------------------------------------------------------------------------
1323
1324/*
1325 The raised border in Win32 looks like this:
1326
1327 IIIIIIIIIIIIIIIIIIIIIIB
1328 I GB
1329 I GB I = white (HILIGHT)
1330 I GB H = light grey (LIGHT)
1331 I GB G = dark grey (SHADOI)
1332 I GB B = black (DKSHADOI)
1333 I GB I = hIghlight (COLOR_3DHILIGHT)
1334 I GB
1335 IGGGGGGGGGGGGGGGGGGGGGB
1336 BBBBBBBBBBBBBBBBBBBBBBB
1337
1338 The sunken border looks like this:
1339
1340 GGGGGGGGGGGGGGGGGGGGGGI
1341 GBBBBBBBBBBBBBBBBBBBBHI
1342 GB HI
1343 GB HI
1344 GB HI
1345 GB HI
1346 GB HI
1347 GB HI
1348 GHHHHHHHHHHHHHHHHHHHHHI
1349 IIIIIIIIIIIIIIIIIIIIIII
1350
1351 The static border (used for the controls which don't get focus) is like
1352 this:
1353
1354 GGGGGGGGGGGGGGGGGGGGGGW
1355 G W
1356 G W
1357 G W
1358 G W
1359 G W
1360 G W
1361 G W
1362 WWWWWWWWWWWWWWWWWWWWWWW
1363
1364 The most complicated is the double border:
1365
1366 HHHHHHHHHHHHHHHHHHHHHHB
1367 HWWWWWWWWWWWWWWWWWWWWGB
1368 HWHHHHHHHHHHHHHHHHHHHGB
1369 HWH HGB
1370 HWH HGB
1371 HWH HGB
1372 HWH HGB
1373 HWHHHHHHHHHHHHHHHHHHHGB
1374 HGGGGGGGGGGGGGGGGGGGGGB
1375 BBBBBBBBBBBBBBBBBBBBBBB
1376
1377 And the simple border is, well, simple:
1378
1379 BBBBBBBBBBBBBBBBBBBBBBB
1380 B B
1381 B B
1382 B B
1383 B B
1384 B B
1385 B B
1386 B B
1387 B B
1388 BBBBBBBBBBBBBBBBBBBBBBB
1389*/
1390
1391void wxWin32Renderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1392{
1393 // draw
1394 dc.SetPen(pen);
1395 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1396 dc.DrawRectangle(*rect);
1397
1398 // adjust the rect
1399 rect->Inflate(-1);
1400}
1401
1402void wxWin32Renderer::DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen)
1403{
1404 // draw the bottom and right sides
1405 dc.SetPen(pen);
1406 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1407 rect->GetRight() + 1, rect->GetBottom());
1408 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1409 rect->GetRight(), rect->GetBottom());
1410
1411 // adjust the rect
1412 rect->width--;
1413 rect->height--;
1414}
1415
1416void wxWin32Renderer::DrawShadedRect(wxDC& dc, wxRect *rect,
1417 const wxPen& pen1, const wxPen& pen2)
1418{
1419 // draw the rectangle
1420 dc.SetPen(pen1);
1421 dc.DrawLine(rect->GetLeft(), rect->GetTop(),
1422 rect->GetLeft(), rect->GetBottom());
1423 dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
1424 rect->GetRight(), rect->GetTop());
1425 dc.SetPen(pen2);
1426 dc.DrawLine(rect->GetRight(), rect->GetTop(),
1427 rect->GetRight(), rect->GetBottom());
1428 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
1429 rect->GetRight() + 1, rect->GetBottom());
1430
1431 // adjust the rect
1432 rect->Inflate(-1);
1433}
1434
1435void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxRect *rect)
1436{
1437 DrawShadedRect(dc, rect, m_penHighlight, m_penBlack);
1438 DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
1439}
1440
1441void wxWin32Renderer::DrawSunkenBorder(wxDC& dc, wxRect *rect)
1442{
1443 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
1444 DrawShadedRect(dc, rect, m_penBlack, m_penLightGrey);
1445}
1446
1447void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
1448{
1449 if ( isPressed )
1450 {
1451 DrawRect(dc, rect, m_penDarkGrey);
1452
1453 // the arrow is usually drawn inside border of width 2 and is offset by
1454 // another pixel in both directions when it's pressed - as the border
1455 // in this case is more narrow as well, we have to adjust rect like
1456 // this:
1457 rect->Inflate(-1);
1458 rect->x++;
1459 rect->y++;
1460 }
1461 else
1462 {
1463 DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
1464 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
1465 }
1466}
1467
1468void wxWin32Renderer::DrawBorder(wxDC& dc,
1469 wxBorder border,
1470 const wxRect& rectTotal,
1471 int WXUNUSED(flags),
1472 wxRect *rectIn)
1473{
1474 int i;
1475
1476 wxRect rect = rectTotal;
1477
1478 switch ( border )
1479 {
1480 case wxBORDER_SUNKEN:
1481 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1482 {
1483 DrawSunkenBorder(dc, &rect);
1484 }
1485 break;
1486
1487 case wxBORDER_STATIC:
1488 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1489 break;
1490
1491 case wxBORDER_RAISED:
1492 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1493 {
1494 DrawRaisedBorder(dc, &rect);
1495 }
1496 break;
1497
1498 case wxBORDER_DOUBLE:
1499 DrawArrowBorder(dc, &rect);
1500 DrawRect(dc, &rect, m_penLightGrey);
1501 break;
1502
1503 case wxBORDER_SIMPLE:
1504 for ( i = 0; i < BORDER_THICKNESS / 2; i++ )
1505 {
1506 DrawRect(dc, &rect, m_penBlack);
1507 }
1508 break;
1509
1510 default:
1511 wxFAIL_MSG(_T("unknown border type"));
1512 // fall through
1513
1514 case wxBORDER_DEFAULT:
1515 case wxBORDER_NONE:
1516 break;
1517 }
1518
1519 if ( rectIn )
1520 *rectIn = rect;
1521}
1522
1523wxRect wxWin32Renderer::GetBorderDimensions(wxBorder border) const
1524{
1525 wxCoord width;
1526 switch ( border )
1527 {
1528 case wxBORDER_RAISED:
1529 case wxBORDER_SUNKEN:
1530 width = BORDER_THICKNESS;
1531 break;
1532
1533 case wxBORDER_SIMPLE:
1534 case wxBORDER_STATIC:
1535 width = 1;
1536 break;
1537
1538 case wxBORDER_DOUBLE:
1539 width = 3;
1540 break;
1541
1542 default:
1543 wxFAIL_MSG(_T("unknown border type"));
1544 // fall through
1545
1546 case wxBORDER_DEFAULT:
1547 case wxBORDER_NONE:
1548 width = 0;
1549 break;
1550 }
1551
1552 wxRect rect;
1553 rect.x =
1554 rect.y =
1555 rect.width =
1556 rect.height = width;
1557
1558 return rect;
1559}
1560
1561bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1562{
1563 return TRUE;
1564}
1565
1566// ----------------------------------------------------------------------------
1567// borders
1568// ----------------------------------------------------------------------------
1569
1570void wxWin32Renderer::DrawTextBorder(wxDC& dc,
1571 wxBorder border,
1572 const wxRect& rect,
1573 int flags,
1574 wxRect *rectIn)
1575{
1576 // text controls are not special under windows
1577 DrawBorder(dc, border, rect, flags, rectIn);
1578}
1579
1580void wxWin32Renderer::DrawButtonBorder(wxDC& dc,
1581 const wxRect& rectTotal,
1582 int flags,
1583 wxRect *rectIn)
1584{
1585 wxRect rect = rectTotal;
1586
1587 if ( flags & wxCONTROL_PRESSED )
1588 {
1589 // button pressed: draw a double border around it
1590 DrawRect(dc, &rect, m_penBlack);
1591 DrawRect(dc, &rect, m_penDarkGrey);
1592 }
1593 else
1594 {
1595 // button not pressed
1596
1597 if ( flags & (wxCONTROL_FOCUSED | wxCONTROL_ISDEFAULT) )
1598 {
1599 // button either default or focused (or both): add an extra border around it
1600 DrawRect(dc, &rect, m_penBlack);
1601 }
1602
1603 // now draw a normal button
1604 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
1605 DrawHalfRect(dc, &rect, m_penDarkGrey);
1606 }
1607
1608 if ( rectIn )
1609 {
1610 *rectIn = rect;
1611 }
1612}
1613
1614// ----------------------------------------------------------------------------
1615// lines and frame
1616// ----------------------------------------------------------------------------
1617
1618void wxWin32Renderer::DrawHorizontalLine(wxDC& dc,
1619 wxCoord y, wxCoord x1, wxCoord x2)
1620{
1621 dc.SetPen(m_penDarkGrey);
1622 dc.DrawLine(x1, y, x2 + 1, y);
1623 dc.SetPen(m_penHighlight);
1624 y++;
1625 dc.DrawLine(x1, y, x2 + 1, y);
1626}
1627
1628void wxWin32Renderer::DrawVerticalLine(wxDC& dc,
1629 wxCoord x, wxCoord y1, wxCoord y2)
1630{
1631 dc.SetPen(m_penDarkGrey);
1632 dc.DrawLine(x, y1, x, y2 + 1);
1633 dc.SetPen(m_penHighlight);
1634 x++;
1635 dc.DrawLine(x, y1, x, y2 + 1);
1636}
1637
1638void wxWin32Renderer::DrawFrame(wxDC& dc,
1639 const wxString& label,
1640 const wxRect& rect,
1641 int flags,
1642 int alignment,
1643 int indexAccel)
1644{
1645 wxCoord height = 0; // of the label
1646 wxRect rectFrame = rect;
1647 if ( !label.empty() )
1648 {
1649 // the text should touch the top border of the rect, so the frame
1650 // itself should be lower
1651 dc.GetTextExtent(label, NULL, &height);
1652 rectFrame.y += height / 2;
1653 rectFrame.height -= height / 2;
1654
1655 // we have to draw each part of the frame individually as we can't
1656 // erase the background beyond the label as it might contain some
1657 // pixmap already, so drawing everything and then overwriting part of
1658 // the frame with label doesn't work
1659
1660 // TODO: the +5 and space insertion should be customizable
1661
1662 wxRect rectText;
1663 rectText.x = rectFrame.x + 5;
1664 rectText.y = rect.y;
1665 rectText.width = rectFrame.width - 7; // +2 border width
1666 rectText.height = height;
1667
1668 wxString label2;
1669 label2 << _T(' ') << label << _T(' ');
1670 if ( indexAccel != -1 )
1671 {
1672 // adjust it as we prepended a space
1673 indexAccel++;
1674 }
1675
1676 wxRect rectLabel;
1677 DrawLabel(dc, label2, rectText, flags, alignment, indexAccel, &rectLabel);
1678
1679 StandardDrawFrame(dc, rectFrame, rectLabel);
1680 }
1681 else
1682 {
1683 // just draw the complete frame
1684 DrawShadedRect(dc, &rectFrame, m_penDarkGrey, m_penHighlight);
1685 DrawShadedRect(dc, &rectFrame, m_penHighlight, m_penDarkGrey);
1686 }
1687}
1688
1689// ----------------------------------------------------------------------------
1690// label
1691// ----------------------------------------------------------------------------
1692
1693void wxWin32Renderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
1694{
1695 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1696 // pixels each while we really need dots here... PS_ALTERNATE might
1697 // work, but it is for NT 5 only
1698#if 0
1699 DrawRect(dc, &rect, wxPen(*wxBLACK, 0, wxDOT));
1700#else
1701 // draw the pixels manually: note that to behave in the same manner as
1702 // DrawRect(), we must exclude the bottom and right borders from the
1703 // rectangle
1704 wxCoord x1 = rect.GetLeft(),
1705 y1 = rect.GetTop(),
1706 x2 = rect.GetRight(),
1707 y2 = rect.GetBottom();
1708
1709 dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID));
1710
1711 // this seems to be closer than what Windows does than wxINVERT although
1712 // I'm still not sure if it's correct
1713 dc.SetLogicalFunction(wxAND_REVERSE);
1714
1715 wxCoord z;
1716 for ( z = x1 + 1; z < x2; z += 2 )
1717 dc.DrawPoint(z, rect.GetTop());
1718
1719 wxCoord shift = z == x2 ? 0 : 1;
1720 for ( z = y1 + shift; z < y2; z += 2 )
1721 dc.DrawPoint(x2, z);
1722
1723 shift = z == y2 ? 0 : 1;
1724 for ( z = x2 - shift; z > x1; z -= 2 )
1725 dc.DrawPoint(z, y2);
1726
1727 shift = z == x1 ? 0 : 1;
1728 for ( z = y2 - shift; z > y1; z -= 2 )
1729 dc.DrawPoint(x1, z);
1730
1731 dc.SetLogicalFunction(wxCOPY);
1732#endif // 0/1
1733}
1734
1735void wxWin32Renderer::DrawLabelShadow(wxDC& dc,
1736 const wxString& label,
1737 const wxRect& rect,
1738 int alignment,
1739 int indexAccel)
1740{
1741 // draw shadow of the text
1742 dc.SetTextForeground(m_colHighlight);
1743 wxRect rectShadow = rect;
1744 rectShadow.x++;
1745 rectShadow.y++;
1746 dc.DrawLabel(label, rectShadow, alignment, indexAccel);
1747
1748 // make the text grey
1749 dc.SetTextForeground(m_colDarkGrey);
1750}
1751
1752void wxWin32Renderer::DrawLabel(wxDC& dc,
1753 const wxString& label,
1754 const wxRect& rect,
1755 int flags,
1756 int alignment,
1757 int indexAccel,
1758 wxRect *rectBounds)
1759{
1760 DoDrawLabel(dc, label, rect, flags, alignment, indexAccel, rectBounds);
1761}
1762
1763void wxWin32Renderer::DoDrawLabel(wxDC& dc,
1764 const wxString& label,
1765 const wxRect& rect,
1766 int flags,
1767 int alignment,
1768 int indexAccel,
1769 wxRect *rectBounds,
1770 const wxPoint& focusOffset)
1771{
1772 // the underscores are not drawn for focused controls in wxMSW
1773 if ( flags & wxCONTROL_FOCUSED )
1774 {
1775 indexAccel = -1;
1776 }
1777
1778 if ( flags & wxCONTROL_DISABLED )
1779 {
1780 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1781 // currently only can happen for a menu item and it seems that Windows
1782 // doesn't draw the shadow in this case, so we don't do it neither
1783 if ( flags & wxCONTROL_SELECTED )
1784 {
1785 // just make the label text greyed out
1786 dc.SetTextForeground(m_colDarkGrey);
1787 }
1788 else // draw normal disabled label
1789 {
1790 DrawLabelShadow(dc, label, rect, alignment, indexAccel);
1791 }
1792 }
1793
1794 wxRect rectLabel;
1795 dc.DrawLabel(label, wxNullBitmap, rect, alignment, indexAccel, &rectLabel);
1796
1797 if ( flags & wxCONTROL_DISABLED )
1798 {
1799 // restore the fg colour
1800 dc.SetTextForeground(*wxBLACK);
1801 }
1802
1803 if ( flags & wxCONTROL_FOCUSED )
1804 {
1805 if ( focusOffset.x || focusOffset.y )
1806 {
1e6feb95
VZ
1807 rectLabel.Inflate(focusOffset.x, focusOffset.y);
1808 }
1809
1810 DrawFocusRect(dc, rectLabel);
1811 }
1812
1813 if ( rectBounds )
1814 *rectBounds = rectLabel;
1815}
1816
1817void wxWin32Renderer::DrawButtonLabel(wxDC& dc,
1818 const wxString& label,
1819 const wxBitmap& image,
1820 const wxRect& rect,
1821 int flags,
1822 int alignment,
1823 int indexAccel,
1824 wxRect *rectBounds)
1825{
1826 // the underscores are not drawn for focused controls in wxMSW
1827 if ( flags & wxCONTROL_PRESSED )
1828 {
1829 indexAccel = -1;
1830 }
1831
1832 wxRect rectLabel = rect;
1833 if ( !label.empty() )
1834 {
1835 // shift the label if a button is pressed
1836 if ( flags & wxCONTROL_PRESSED )
1837 {
1838 rectLabel.x++;
1839 rectLabel.y++;
1840 }
1841
1842 if ( flags & wxCONTROL_DISABLED )
1843 {
1844 DrawLabelShadow(dc, label, rectLabel, alignment, indexAccel);
1845 }
1846
1847 // leave enough space for the focus rectangle
1848 if ( flags & wxCONTROL_FOCUSED )
1849 {
1850 rectLabel.Inflate(-2);
1851 }
1852 }
1853
1854 dc.DrawLabel(label, image, rectLabel, alignment, indexAccel, rectBounds);
1855
1856 if ( !label.empty() && (flags & wxCONTROL_FOCUSED) )
1857 {
1858 if ( flags & wxCONTROL_PRESSED )
1859 {
1860 // the focus rectangle is never pressed, so undo the shift done
1861 // above
1862 rectLabel.x--;
1863 rectLabel.y--;
1864 rectLabel.width--;
1865 rectLabel.height--;
1866 }
1867
1868 DrawFocusRect(dc, rectLabel);
1869 }
1870}
1871
1872// ----------------------------------------------------------------------------
1873// (check)listbox items
1874// ----------------------------------------------------------------------------
1875
1876void wxWin32Renderer::DrawItem(wxDC& dc,
1877 const wxString& label,
1878 const wxRect& rect,
1879 int flags)
1880{
1881 wxDCTextColourChanger colChanger(dc);
1882
1883 if ( flags & wxCONTROL_SELECTED )
1884 {
1885 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
1886
1887 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
1888 dc.SetBrush(wxBrush(colBg, wxSOLID));
1889 dc.SetPen(wxPen(colBg, 0, wxSOLID));
1890 dc.DrawRectangle(rect);
1891 }
1892
1893 wxRect rectText = rect;
1894 rectText.x += 2;
1895 rectText.width -= 2;
1896 dc.DrawLabel(label, wxNullBitmap, rectText);
1897
1898 if ( flags & wxCONTROL_FOCUSED )
1899 {
1900 DrawFocusRect(dc, rect);
1901 }
1902}
1903
1904void wxWin32Renderer::DrawCheckItem(wxDC& dc,
1905 const wxString& label,
1906 const wxBitmap& bitmap,
1907 const wxRect& rect,
1908 int flags)
1909{
1910 wxBitmap bmp;
1911 if ( bitmap.Ok() )
1912 {
1913 bmp = bitmap;
1914 }
1915 else // use default bitmap
1916 {
1917 bmp = wxBitmap(flags & wxCONTROL_CHECKED ? checked_item_xpm
1918 : unchecked_item_xpm);
1919 }
1920
1921 dc.DrawBitmap(bmp, rect.x, rect.y + (rect.height - bmp.GetHeight()) / 2 - 1,
1922 TRUE /* use mask */);
1923
1924 wxRect rectLabel = rect;
1925 int bmpWidth = bmp.GetWidth();
1926 rectLabel.x += bmpWidth;
1927 rectLabel.width -= bmpWidth;
1928
1929 DrawItem(dc, label, rectLabel, flags);
1930}
1931
1932// ----------------------------------------------------------------------------
1933// check/radio buttons
1934// ----------------------------------------------------------------------------
1935
1936wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags)
1937{
1938 IndicatorState indState;
1939 if ( flags & wxCONTROL_SELECTED )
1940 indState = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
1941 : IndicatorState_Selected;
1942 else if ( flags & wxCONTROL_DISABLED )
1943 indState = IndicatorState_Disabled;
1944 else if ( flags & wxCONTROL_PRESSED )
1945 indState = IndicatorState_Pressed;
1946 else
1947 indState = IndicatorState_Normal;
1948
1949 IndicatorStatus indStatus = flags & wxCONTROL_CHECKED
1950 ? IndicatorStatus_Checked
1951 : IndicatorStatus_Unchecked;
1952
1953 const char **xpm = bmpIndicators[indType][indState][indStatus];
1954 return xpm ? wxBitmap(xpm) : wxNullBitmap;
1955}
1956
1957void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc,
1958 const wxString& label,
1959 const wxBitmap& bitmap,
1960 const wxRect& rect,
1961 int flags,
1962 wxAlignment align,
1963 int indexAccel,
1964 wxCoord focusOffsetY)
1965{
1966 // calculate the position of the bitmap and of the label
1967 wxCoord heightBmp = bitmap.GetHeight();
1968 wxCoord xBmp,
1969 yBmp = rect.y + (rect.height - heightBmp) / 2;
1970
1971 wxRect rectLabel;
1972 dc.GetMultiLineTextExtent(label, NULL, &rectLabel.height);
1973 rectLabel.y = rect.y + (rect.height - rectLabel.height) / 2;
1974
1975 // align label vertically with the bitmap - looks nicer like this
1976 rectLabel.y -= (rectLabel.height - heightBmp) % 2;
1977
1978 // calc horz position
1979 if ( align == wxALIGN_RIGHT )
1980 {
1981 xBmp = rect.GetRight() - bitmap.GetWidth();
1982 rectLabel.x = rect.x + 3;
1983 rectLabel.SetRight(xBmp);
1984 }
1985 else // normal (checkbox to the left of the text) case
1986 {
1987 xBmp = rect.x;
1988 rectLabel.x = xBmp + bitmap.GetWidth() + 5;
1989 rectLabel.SetRight(rect.GetRight());
1990 }
1991
1992 dc.DrawBitmap(bitmap, xBmp, yBmp, TRUE /* use mask */);
1993
1994 DoDrawLabel(
1995 dc, label, rectLabel,
1996 flags,
1997 wxALIGN_LEFT | wxALIGN_TOP,
1998 indexAccel,
1999 NULL, // we don't need bounding rect
2000 // use custom vert focus rect offset
2001 wxPoint(FOCUS_RECT_OFFSET_X, focusOffsetY)
2002 );
2003}
2004
2005void wxWin32Renderer::DrawRadioButton(wxDC& dc,
2006 const wxString& label,
2007 const wxBitmap& bitmap,
2008 const wxRect& rect,
2009 int flags,
2010 wxAlignment align,
2011 int indexAccel)
2012{
2013 DrawCheckOrRadioButton(dc, label,
2014 bitmap.Ok() ? bitmap : GetRadioBitmap(flags),
2015 rect, flags, align, indexAccel,
2016 FOCUS_RECT_OFFSET_Y); // default focus rect offset
2017}
2018
2019void wxWin32Renderer::DrawCheckButton(wxDC& dc,
2020 const wxString& label,
2021 const wxBitmap& bitmap,
2022 const wxRect& rect,
2023 int flags,
2024 wxAlignment align,
2025 int indexAccel)
2026{
2027 DrawCheckOrRadioButton(dc, label,
2028 bitmap.Ok() ? bitmap : GetCheckBitmap(flags),
2029 rect, flags, align, indexAccel,
2030 0); // no focus rect offset for checkboxes
2031}
2032
2033// ----------------------------------------------------------------------------
2034// text control
2035// ----------------------------------------------------------------------------
2036
2037void wxWin32Renderer::DrawTextLine(wxDC& dc,
2038 const wxString& text,
2039 const wxRect& rect,
2040 int selStart,
2041 int selEnd,
2042 int flags)
2043{
2044 // nothing special to do here
2045 StandardDrawTextLine(dc, text, rect, selStart, selEnd, flags);
2046}
2047
2048void wxWin32Renderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
2049{
2050 // we don't draw them
2051}
2052
2053// ----------------------------------------------------------------------------
2054// notebook
2055// ----------------------------------------------------------------------------
2056
2057void wxWin32Renderer::DrawTab(wxDC& dc,
2058 const wxRect& rectOrig,
2059 wxDirection dir,
2060 const wxString& label,
2061 const wxBitmap& bitmap,
2062 int flags,
2063 int indexAccel)
2064{
2065 wxRect rect = rectOrig;
2066
2067 // the current tab is drawn indented (to the top for default case) and
2068 // bigger than the other ones
2069 const wxSize indent = GetTabIndent();
2070 if ( flags & wxCONTROL_SELECTED )
2071 {
2072 switch ( dir )
2073 {
2074 default:
2075 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2076 // fall through
2077
2078 case wxTOP:
2079 rect.Inflate(indent.x, 0);
2080 rect.y -= indent.y;
2081 rect.height += indent.y;
2082 break;
2083
2084 case wxBOTTOM:
2085 rect.Inflate(indent.x, 0);
2086 rect.height += indent.y;
2087 break;
2088
2089 case wxLEFT:
2090 case wxRIGHT:
2091 wxFAIL_MSG(_T("TODO"));
2092 break;
2093 }
2094 }
2095
2096 // draw the text, image and the focus around them (if necessary)
2097 wxRect rectLabel = rect;
2098 rectLabel.Deflate(1, 1);
2099 DrawButtonLabel(dc, label, bitmap, rectLabel,
2100 flags, wxALIGN_CENTRE, indexAccel);
2101
2102 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2103 static const wxCoord CUTOFF = 2; // radius of the rounded corner
2104 wxCoord x = rect.x,
2105 y = rect.y,
2106 x2 = rect.GetRight(),
2107 y2 = rect.GetBottom();
2108
2109 // FIXME: all this code will break if the tab indent or the border width,
2110 // it is tied to the fact that both of them are equal to 2
2111 switch ( dir )
2112 {
2113 default:
2114 case wxTOP:
2115 dc.SetPen(m_penHighlight);
2116 dc.DrawLine(x, y2, x, y + CUTOFF);
2117 dc.DrawLine(x, y + CUTOFF, x + CUTOFF, y);
2118 dc.DrawLine(x + CUTOFF, y, x2 - CUTOFF + 1, y);
2119
2120 dc.SetPen(m_penBlack);
2121 dc.DrawLine(x2, y2, x2, y + CUTOFF);
2122 dc.DrawLine(x2, y + CUTOFF, x2 - CUTOFF, y);
2123
2124 dc.SetPen(m_penDarkGrey);
2125 dc.DrawLine(x2 - 1, y2, x2 - 1, y + CUTOFF - 1);
2126
2127 if ( flags & wxCONTROL_SELECTED )
2128 {
2129 dc.SetPen(m_penLightGrey);
2130
2131 // overwrite the part of the border below this tab
2132 dc.DrawLine(x + 1, y2 + 1, x2 - 1, y2 + 1);
2133
2134 // and the shadow of the tab to the left of us
2135 dc.DrawLine(x + 1, y + CUTOFF + 1, x + 1, y2 + 1);
2136 }
2137 break;
2138
2139 case wxBOTTOM:
2140 dc.SetPen(m_penHighlight);
2141 // we need to continue one pixel further to overwrite the corner of
2142 // the border for the selected tab
2143 dc.DrawLine(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0),
2144 x, y2 - CUTOFF);
2145 dc.DrawLine(x, y2 - CUTOFF, x + CUTOFF, y2);
2146
2147 dc.SetPen(m_penBlack);
2148 dc.DrawLine(x + CUTOFF, y2, x2 - CUTOFF + 1, y2);
2149 dc.DrawLine(x2, y, x2, y2 - CUTOFF);
2150 dc.DrawLine(x2, y2 - CUTOFF, x2 - CUTOFF, y2);
2151
2152 dc.SetPen(m_penDarkGrey);
2153 dc.DrawLine(x + CUTOFF, y2 - 1, x2 - CUTOFF + 1, y2 - 1);
2154 dc.DrawLine(x2 - 1, y, x2 - 1, y2 - CUTOFF + 1);
2155
2156 if ( flags & wxCONTROL_SELECTED )
2157 {
2158 dc.SetPen(m_penLightGrey);
2159
2160 // overwrite the part of the (double!) border above this tab
2161 dc.DrawLine(x + 1, y - 1, x2 - 1, y - 1);
2162 dc.DrawLine(x + 1, y - 2, x2 - 1, y - 2);
2163
2164 // and the shadow of the tab to the left of us
2165 dc.DrawLine(x + 1, y2 - CUTOFF, x + 1, y - 1);
2166 }
2167 break;
2168
2169 case wxLEFT:
2170 case wxRIGHT:
2171 wxFAIL_MSG(_T("TODO"));
2172 }
2173}
2174
2175// ----------------------------------------------------------------------------
2176// slider
2177// ----------------------------------------------------------------------------
2178
2179wxSize wxWin32Renderer::GetSliderThumbSize(const wxRect& rect,
2180 wxOrientation orient) const
2181{
2182 wxSize size;
2183
2184 wxRect rectShaft = GetSliderShaftRect(rect, orient);
2185 if ( orient == wxHORIZONTAL )
2186 {
2187 size.y = rect.height - 6;
2188 size.x = wxMin(size.y / 2, rectShaft.width);
2189 }
2190 else // vertical
2191 {
2192 size.x = rect.width - 6;
2193 size.y = wxMin(size.x / 2, rectShaft.height);
2194 }
2195
2196 return size;
2197}
2198
2199wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
2200 wxOrientation orient) const
2201{
2202 static const wxCoord SLIDER_MARGIN = 6;
2203
2204 wxRect rect = rectOrig;
2205
2206 if ( orient == wxHORIZONTAL )
2207 {
2208 // make the rect of minimal width and centre it
2209 rect.height = 2*BORDER_THICKNESS;
2210 rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
2211 if ( rect.y < 0 )
2212 rect.y = 0;
2213
2214 // leave margins on the sides
2215 rect.Deflate(SLIDER_MARGIN, 0);
2216 }
2217 else // vertical
2218 {
2219 // same as above but in other direction
2220 rect.width = 2*BORDER_THICKNESS;
2221 rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
2222 if ( rect.x < 0 )
2223 rect.x = 0;
2224
2225 rect.Deflate(0, SLIDER_MARGIN);
2226 }
2227
2228 return rect;
2229}
2230
2231void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
2232 const wxRect& rectOrig,
2233 wxOrientation orient,
2234 int flags,
2235 wxRect *rectShaft)
2236{
2237 if ( flags & wxCONTROL_FOCUSED )
2238 {
2239 DrawFocusRect(dc, rectOrig);
2240 }
2241
2242 wxRect rect = GetSliderShaftRect(rectOrig, orient);
2243
2244 if ( rectShaft )
2245 *rectShaft = rect;
2246
2247 DrawSunkenBorder(dc, &rect);
2248}
2249
2250void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
2251 const wxRect& rect,
2252 wxOrientation orient,
2253 int flags)
2254{
2255 /*
2256 we are drawing a shape of this form
2257
2258 HHHHHHB <--- y
2259 H DB
2260 H DB
2261 H DB where H is hightlight colour
2262 H DB D dark grey
2263 H DB B black
2264 H DB
2265 H DB <--- y3
2266 H DB
2267 HDB
2268 B <--- y2
2269
2270 ^ ^ ^
2271 | | |
2272 x x3 x2
2273
2274 The interior of this shape is filled with the hatched brush if the thumb
2275 is pressed.
2276 */
2277
2278 DrawBackground(dc, wxNullColour, rect, flags);
2279
2280 bool transpose = orient == wxVERTICAL;
2281
2282 wxCoord x, y, x2, y2;
2283 if ( transpose )
2284 {
2285 x = rect.y;
2286 y = rect.x;
2287 x2 = rect.GetBottom();
2288 y2 = rect.GetRight();
2289 }
2290 else
2291 {
2292 x = rect.x;
2293 y = rect.y;
2294 x2 = rect.GetRight();
2295 y2 = rect.GetBottom();
2296 }
2297
2298 // the size of the pointed part of the thumb
2299 wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
2300
2301 wxCoord x3 = x + sizeArrow,
2302 y3 = y2 - sizeArrow;
2303
2304 dc.SetPen(m_penHighlight);
2305 DrawLine(dc, x, y, x2, y, transpose);
2306 DrawLine(dc, x, y + 1, x, y2 - sizeArrow, transpose);
2307 DrawLine(dc, x, y3, x3, y2, transpose);
2308
2309 dc.SetPen(m_penBlack);
2310 DrawLine(dc, x3, y2, x2, y3, transpose);
2311 DrawLine(dc, x2, y3, x2, y - 1, transpose);
2312
2313 dc.SetPen(m_penDarkGrey);
2314 DrawLine(dc, x3, y2 - 1, x2 - 1, y3, transpose);
2315 DrawLine(dc, x2 - 1, y3, x2 - 1, y, transpose);
2316
2317 if ( flags & wxCONTROL_PRESSED )
2318 {
2319 // TODO: MSW fills the entire area inside, not just the rect
2320 wxRect rectInt = rect;
2321 if ( transpose )
2322 rectInt.SetRight(y3);
2323 else
2324 rectInt.SetBottom(y3);
2325 rectInt.Deflate(2);
2326
2327 static const char *stipple_xpm[] = {
2328 /* columns rows colors chars-per-pixel */
2329 "2 2 2 1",
2330 " c None",
2331 "w c white",
2332 /* pixels */
2333 "w ",
2334 " w",
2335 };
2336 dc.SetBrush(wxBrush(stipple_xpm));
2337
2338 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
2339 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
2340 dc.SetPen(*wxTRANSPARENT_PEN);
2341 dc.DrawRectangle(rectInt);
2342 }
2343}
2344
2345void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
2346 const wxRect& rect,
2347 const wxSize& sizeThumb,
2348 wxOrientation orient,
2349 int start,
2350 int end,
2351 int step,
2352 int flags)
2353{
2354 if ( end == start )
2355 {
2356 // empty slider?
2357 return;
2358 }
2359
2360 // the variable names correspond to horizontal case, but they can be used
2361 // for both orientations
2362 wxCoord x1, x2, y1, y2, len, widthThumb;
2363 if ( orient == wxHORIZONTAL )
2364 {
2365 x1 = rect.GetLeft();
2366 x2 = rect.GetRight();
2367
2368 // draw from bottom to top to leave one pixel space between the ticks
2369 // and the slider as Windows do
2370 y1 = rect.GetBottom();
2371 y2 = rect.GetTop();
2372
2373 len = rect.width;
2374
2375 widthThumb = sizeThumb.x;
2376 }
2377 else // vertical
2378 {
2379 x1 = rect.GetTop();
2380 x2 = rect.GetBottom();
2381
2382 y1 = rect.GetRight();
2383 y2 = rect.GetLeft();
2384
2385 len = rect.height;
2386
2387 widthThumb = sizeThumb.y;
2388 }
2389
2390 // the first tick should be positioned in such way that a thumb drawn in
2391 // the first position points down directly to it
2392 x1 += widthThumb / 2;
2393 x2 -= widthThumb / 2;
2394
2395 // this also means that we have slightly less space for the ticks in
2396 // between the first and the last
2397 len -= widthThumb;
2398
2399 dc.SetPen(m_penBlack);
2400
2401 int range = end - start;
2402 for ( int n = 0; n < range; n += step )
2403 {
2404 wxCoord x = x1 + (len*n) / range;
2405
2406 DrawLine(dc, x, y1, x, y2, orient == wxVERTICAL);
2407 }
2408
2409 // always draw the line at the end position
2410 DrawLine(dc, x2, y1, x2, y2, orient == wxVERTICAL);
2411}
2412
e766c8a9 2413#if wxUSE_MENUS
1e6feb95
VZ
2414// ----------------------------------------------------------------------------
2415// menu and menubar
2416// ----------------------------------------------------------------------------
2417
3379ed37
VZ
2418#if wxUSE_MENUS
2419
1e6feb95
VZ
2420// wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2421class WXDLLEXPORT wxWin32MenuGeometryInfo : public wxMenuGeometryInfo
2422{
2423public:
2424 virtual wxSize GetSize() const { return m_size; }
2425
2426 wxCoord GetLabelOffset() const { return m_ofsLabel; }
2427 wxCoord GetAccelOffset() const { return m_ofsAccel; }
2428
2429 wxCoord GetItemHeight() const { return m_heightItem; }
2430
2431private:
2432 // the total size of the menu
2433 wxSize m_size;
2434
2435 // the offset of the start of the menu item label
2436 wxCoord m_ofsLabel;
2437
2438 // the offset of the start of the accel label
2439 wxCoord m_ofsAccel;
2440
2441 // the height of a normal (not separator) item
2442 wxCoord m_heightItem;
2443
2444 friend wxMenuGeometryInfo *wxWin32Renderer::
2445 GetMenuGeometry(wxWindow *, const wxMenu&) const;
2446};
2447
3379ed37
VZ
2448#endif // wxUSE_WAVE
2449
1e6feb95
VZ
2450// FIXME: all constants are hardcoded but shouldn't be
2451static const wxCoord MENU_LEFT_MARGIN = 9;
2452static const wxCoord MENU_RIGHT_MARGIN = 18;
2453static const wxCoord MENU_VERT_MARGIN = 3;
2454
2455// the margin around bitmap/check marks (on each side)
2456static const wxCoord MENU_BMP_MARGIN = 2;
2457
2458// the margin between the labels and accel strings
2459static const wxCoord MENU_ACCEL_MARGIN = 8;
2460
2461// the separator height in pixels: in fact, strangely enough, the real height
2462// is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2463// account here
2464static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
2465
2466// the size of the standard checkmark bitmap
2467static const wxCoord MENU_CHECK_SIZE = 9;
2468
3379ed37
VZ
2469// we can't implement these methods without wxMenuGeometryInfo implementation
2470// which we don't have if !wxUSE_MENUS
2471#if wxUSE_MENUS
2472
1e6feb95
VZ
2473void wxWin32Renderer::DrawMenuBarItem(wxDC& dc,
2474 const wxRect& rectOrig,
2475 const wxString& label,
2476 int flags,
2477 int indexAccel)
2478{
2479 wxRect rect = rectOrig;
2480 rect.height--;
2481
2482 wxDCTextColourChanger colChanger(dc);
2483
2484 if ( flags & wxCONTROL_SELECTED )
2485 {
2486 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2487
2488 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2489 dc.SetBrush(wxBrush(colBg, wxSOLID));
2490 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2491 dc.DrawRectangle(rect);
2492 }
2493
2494 // don't draw the focus rect around menu bar items
2495 DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
2496 wxALIGN_CENTRE, indexAccel);
2497}
2498
2499void wxWin32Renderer::DrawMenuItem(wxDC& dc,
2500 wxCoord y,
2501 const wxMenuGeometryInfo& gi,
2502 const wxString& label,
2503 const wxString& accel,
2504 const wxBitmap& bitmap,
2505 int flags,
2506 int indexAccel)
2507{
2508 const wxWin32MenuGeometryInfo& geometryInfo =
2509 (const wxWin32MenuGeometryInfo&)gi;
2510
2511 wxRect rect;
2512 rect.x = 0;
2513 rect.y = y;
2514 rect.width = geometryInfo.GetSize().x;
2515 rect.height = geometryInfo.GetItemHeight();
2516
2517 // draw the selected item specially
2518 wxDCTextColourChanger colChanger(dc);
2519 if ( flags & wxCONTROL_SELECTED )
2520 {
2521 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
2522
2523 wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
2524 dc.SetBrush(wxBrush(colBg, wxSOLID));
2525 dc.SetPen(wxPen(colBg, 0, wxSOLID));
2526 dc.DrawRectangle(rect);
2527 }
2528
2529 // draw the bitmap: use the bitmap provided or the standard checkmark for
2530 // the checkable items
2531 wxBitmap bmp = bitmap;
2532 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKED) )
2533 {
2534 bmp = GetIndicator(IndicatorType_Menu, flags);
2535 }
2536
2537 if ( bmp.Ok() )
2538 {
2539 rect.SetRight(geometryInfo.GetLabelOffset());
2540 wxControlRenderer::DrawBitmap(dc, bmp, rect);
2541 }
2542
2543 // draw the label
2544 rect.x = geometryInfo.GetLabelOffset();
2545 rect.SetRight(geometryInfo.GetAccelOffset());
2546
2547 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
2548
2549 // draw the accel string
2550 rect.x = geometryInfo.GetAccelOffset();
2551 rect.SetRight(geometryInfo.GetSize().x);
2552
2553 // NB: no accel index here
2554 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
2555
2556 // draw the submenu indicator
2557 if ( flags & wxCONTROL_ISSUBMENU )
2558 {
2559 rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
2560 rect.width = MENU_RIGHT_MARGIN;
2561
2562 wxArrowStyle arrowStyle;
2563 if ( flags & wxCONTROL_DISABLED )
2564 arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InversedDisabled
2565 : Arrow_Disabled;
2566 else if ( flags & wxCONTROL_SELECTED )
2567 arrowStyle = Arrow_Inversed;
2568 else
2569 arrowStyle = Arrow_Normal;
2570
2571 DrawArrow(dc, rect, Arrow_Right, arrowStyle);
2572 }
2573}
2574
2575void wxWin32Renderer::DrawMenuSeparator(wxDC& dc,
2576 wxCoord y,
2577 const wxMenuGeometryInfo& geomInfo)
2578{
2579 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
2580}
2581
2582wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& sizeText) const
2583{
2584 wxSize size = sizeText;
2585
2586 // FIXME: menubar height is configurable under Windows
2587 size.x += 12;
2588 size.y += 6;
2589
2590 return size;
2591}
2592
2593wxMenuGeometryInfo *wxWin32Renderer::GetMenuGeometry(wxWindow *win,
2594 const wxMenu& menu) const
2595{
2596 // prepare the dc: for now we draw all the items with the system font
2597 wxClientDC dc(win);
2598 dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
2599
2600 // the height of a normal item
2601 wxCoord heightText = dc.GetCharHeight();
2602
2603 // the total height
2604 wxCoord height = 0;
2605
2606 // the max length of label and accel strings: the menu width is the sum of
2607 // them, even if they're for different items (as the accels should be
2608 // aligned)
2609 //
2610 // the max length of the bitmap is never 0 as Windows always leaves enough
2611 // space for a check mark indicator
2612 wxCoord widthLabelMax = 0,
2613 widthAccelMax = 0,
2614 widthBmpMax = MENU_LEFT_MARGIN;
2615
2616 for ( wxMenuItemList::Node *node = menu.GetMenuItems().GetFirst();
2617 node;
2618 node = node->GetNext() )
2619 {
2620 // height of this item
2621 wxCoord h;
2622
2623 wxMenuItem *item = node->GetData();
2624 if ( item->IsSeparator() )
2625 {
2626 h = MENU_SEPARATOR_HEIGHT;
2627 }
2628 else // not separator
2629 {
2630 h = heightText;
2631
2632 wxCoord widthLabel;
2633 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
2634 if ( widthLabel > widthLabelMax )
2635 {
2636 widthLabelMax = widthLabel;
2637 }
2638
2639 wxCoord widthAccel;
2640 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
2641 if ( widthAccel > widthAccelMax )
2642 {
2643 widthAccelMax = widthAccel;
2644 }
2645
2646 const wxBitmap& bmp = item->GetBitmap();
2647 if ( bmp.Ok() )
2648 {
2649 wxCoord widthBmp = bmp.GetWidth();
2650 if ( widthBmp > widthBmpMax )
2651 widthBmpMax = widthBmp;
2652 }
2653 //else if ( item->IsCheckable() ): no need to check for this as
2654 // MENU_LEFT_MARGIN is big enough to show the check mark
2655 }
2656
2657 h += 2*MENU_VERT_MARGIN;
2658
2659 // remember the item position and height
2660 item->SetGeometry(height, h);
2661
2662 height += h;
2663 }
2664
2665 // bundle the metrics into a struct and return it
2666 wxWin32MenuGeometryInfo *gi = new wxWin32MenuGeometryInfo;
2667
2668 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
2669 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
2670 if ( widthAccelMax > 0 )
2671 {
2672 // if we actually have any accesl, add a margin
2673 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
2674 }
2675
2676 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
2677
2678 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
2679 gi->m_size.y = height;
2680
2681 return gi;
2682}
e766c8a9
SC
2683<<<<<<< win32.cpp
2684#endif
2685=======
1e6feb95 2686
3379ed37
VZ
2687#else // !wxUSE_MENUS
2688
2689void wxWin32Renderer::DrawMenuBarItem(wxDC& WXUNUSED(dc),
2690 const wxRect& WXUNUSED(rectOrig),
2691 const wxString& WXUNUSED(label),
2692 int WXUNUSED(flags),
2693 int WXUNUSED(indexAccel))
2694{
2695}
2696
2697void wxWin32Renderer::DrawMenuItem(wxDC& WXUNUSED(dc),
2698 wxCoord WXUNUSED(y),
2699 const wxMenuGeometryInfo& WXUNUSED(gi),
2700 const wxString& WXUNUSED(label),
2701 const wxString& WXUNUSED(accel),
2702 const wxBitmap& WXUNUSED(bitmap),
2703 int WXUNUSED(flags),
2704 int WXUNUSED(indexAccel))
2705{
2706}
2707
2708void wxWin32Renderer::DrawMenuSeparator(wxDC& WXUNUSED(dc),
2709 wxCoord WXUNUSED(y),
2710 const wxMenuGeometryInfo& WXUNUSED(gi))
2711{
2712}
2713
2714wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& size) const
2715{
2716 return size;
2717}
2718
2719wxMenuGeometryInfo *
2720wxWin32Renderer::GetMenuGeometry(wxWindow *WXUNUSED(win),
2721 const wxMenu& WXUNUSED(menu)) const
2722{
2723 return NULL;
2724}
2725
2726#endif // wxUSE_MENUS/!wxUSE_MENUS
2727
e766c8a9 2728>>>>>>> 1.5
1e6feb95
VZ
2729// ----------------------------------------------------------------------------
2730// combobox
2731// ----------------------------------------------------------------------------
2732
2733void wxWin32Renderer::GetComboBitmaps(wxBitmap *bmpNormal,
2734 wxBitmap *bmpPressed,
2735 wxBitmap *bmpDisabled)
2736{
2737 static const wxCoord widthCombo = 16;
2738 static const wxCoord heightCombo = 17;
2739
2740 wxMemoryDC dcMem;
2741
2742 if ( bmpNormal )
2743 {
2744 bmpNormal->Create(widthCombo, heightCombo);
2745 dcMem.SelectObject(*bmpNormal);
2746 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2747 Arrow_Down, Arrow_Normal);
2748 }
2749
2750 if ( bmpPressed )
2751 {
2752 bmpPressed->Create(widthCombo, heightCombo);
2753 dcMem.SelectObject(*bmpPressed);
2754 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2755 Arrow_Down, Arrow_Pressed);
2756 }
2757
2758 if ( bmpDisabled )
2759 {
2760 bmpDisabled->Create(widthCombo, heightCombo);
2761 dcMem.SelectObject(*bmpDisabled);
2762 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
2763 Arrow_Down, Arrow_Disabled);
2764 }
2765}
2766
2767// ----------------------------------------------------------------------------
2768// background
2769// ----------------------------------------------------------------------------
2770
2771void wxWin32Renderer::DoDrawBackground(wxDC& dc,
2772 const wxColour& col,
2773 const wxRect& rect)
2774{
2775 wxBrush brush(col, wxSOLID);
2776 dc.SetBrush(brush);
2777 dc.SetPen(*wxTRANSPARENT_PEN);
2778 dc.DrawRectangle(rect);
2779}
2780
2781void wxWin32Renderer::DrawBackground(wxDC& dc,
2782 const wxColour& col,
2783 const wxRect& rect,
2784 int flags)
2785{
2786 // just fill it with the given or default bg colour
2787 wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL);
2788 DoDrawBackground(dc, colBg, rect);
2789}
2790
2791// ----------------------------------------------------------------------------
2792// scrollbar
2793// ----------------------------------------------------------------------------
2794
2795void wxWin32Renderer::DrawArrow(wxDC& dc,
2796 wxDirection dir,
2797 const wxRect& rect,
2798 int flags)
2799{
2800 // get the bitmap for this arrow
2801 wxArrowDirection arrowDir;
2802 switch ( dir )
2803 {
2804 case wxLEFT: arrowDir = Arrow_Left; break;
2805 case wxRIGHT: arrowDir = Arrow_Right; break;
2806 case wxUP: arrowDir = Arrow_Up; break;
2807 case wxDOWN: arrowDir = Arrow_Down; break;
2808
2809 default:
2810 wxFAIL_MSG(_T("unknown arrow direction"));
2811 return;
2812 }
2813
2814 wxArrowStyle arrowStyle;
2815 if ( flags & wxCONTROL_PRESSED )
2816 {
2817 // can't be pressed and disabled
2818 arrowStyle = Arrow_Pressed;
2819 }
2820 else
2821 {
2822 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
2823 }
2824
2825 DrawArrowButton(dc, rect, arrowDir, arrowStyle);
2826}
2827
2828void wxWin32Renderer::DrawArrow(wxDC& dc,
2829 const wxRect& rect,
2830 wxArrowDirection arrowDir,
2831 wxArrowStyle arrowStyle)
2832{
2833 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
2834
2835 // under Windows the arrows always have the same size so just centre it in
2836 // the provided rectangle
2837 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
2838 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
2839
2840 // Windows does it like this...
2841 if ( arrowDir == Arrow_Left )
2842 x--;
2843
2844 // draw it
2845 dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
2846}
2847
2848void wxWin32Renderer::DrawArrowButton(wxDC& dc,
2849 const wxRect& rectAll,
2850 wxArrowDirection arrowDir,
2851 wxArrowStyle arrowStyle)
2852{
2853 wxRect rect = rectAll;
2854 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
2855 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
2856 DrawArrow(dc, rect, arrowDir, arrowStyle);
2857}
2858
2859void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
2860 wxOrientation orient,
2861 const wxRect& rect,
2862 int flags)
2863{
2864 // we don't use the flags, the thumb never changes appearance
2865 wxRect rectThumb = rect;
2866 DrawArrowBorder(dc, &rectThumb);
2867 DrawBackground(dc, wxNullColour, rectThumb);
2868}
2869
2870void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
2871 wxOrientation orient,
2872 const wxRect& rectBar,
2873 int flags)
2874{
2875 wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
2876 ? wxColourScheme::SCROLLBAR_PRESSED
2877 : wxColourScheme::SCROLLBAR;
2878 DoDrawBackground(dc, m_scheme->Get(col), rectBar);
2879}
2880
2881void wxWin32Renderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
2882{
2883 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
2884}
2885
2886wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar,
2887 wxScrollBar::Element elem,
2888 int thumbPos) const
2889{
2890 return StandardGetScrollbarRect(scrollbar, elem,
2891 thumbPos, m_sizeScrollbarArrow);
2892}
2893
2894wxCoord wxWin32Renderer::GetScrollbarSize(const wxScrollBar *scrollbar)
2895{
2896 return StandardScrollBarSize(scrollbar, m_sizeScrollbarArrow);
2897}
2898
2899wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
2900 const wxPoint& pt) const
2901{
2902 return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow);
2903}
2904
2905wxCoord wxWin32Renderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
2906 int thumbPos)
2907{
2908 return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow);
2909}
2910
2911int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar,
2912 wxCoord coord)
2913{
2914 return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow);
2915}
2916
2917// ----------------------------------------------------------------------------
2918// text control geometry
2919// ----------------------------------------------------------------------------
2920
2921static inline int GetTextBorderWidth()
2922{
2923 return 1;
2924}
2925
2926wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
2927 const wxRect& rect)
2928{
2929 wxRect rectTotal = rect;
2930
2931 wxCoord widthBorder = GetTextBorderWidth();
1e6feb95
VZ
2932 rectTotal.Inflate(widthBorder);
2933
2934 // this is what Windows does
2935 rectTotal.height++;
2936
2937 return rectTotal;
2938}
2939
2940wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
2941 const wxRect& rect,
2942 wxCoord *extraSpaceBeyond)
2943{
2944 wxRect rectText = rect;
2945
2946 // undo GetTextTotalArea()
2947 if ( rectText.height > 0 )
2948 rectText.height--;
2949
2950 wxCoord widthBorder = GetTextBorderWidth();
1e6feb95
VZ
2951 rectText.Inflate(-widthBorder);
2952
2953 if ( extraSpaceBeyond )
2954 *extraSpaceBeyond = 0;
2955
2956 return rectText;
2957}
2958
2959// ----------------------------------------------------------------------------
2960// size adjustments
2961// ----------------------------------------------------------------------------
2962
2963void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
2964{
2965#if wxUSE_SCROLLBAR
2966 if ( wxDynamicCast(window, wxScrollBar) )
2967 {
2968 // we only set the width of vert scrollbars and height of the
2969 // horizontal ones
2970 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
2971 size->y = m_sizeScrollbarArrow.y;
2972 else
2973 size->x = m_sizeScrollbarArrow.x;
2974
2975 // skip border width adjustments, they don't make sense for us
2976 return;
2977 }
2978#endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2979
2980#if wxUSE_BUTTON
2981 if ( wxDynamicCast(window, wxButton) )
2982 {
2983 // TODO
2984 size->x += 3*window->GetCharWidth();
2985#if 0 // do allow creating small buttons if wanted
2986 wxSize sizeDef = wxButton::GetDefaultSize();
2987 if ( size->x < sizeDef.x )
2988 size->x = sizeDef.x;
2989#endif // 0
2990
2991 wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
2992 if ( size->y < heightBtn - 8 )
2993 size->y = heightBtn;
2994 else
2995 size->y += 9;
2996
2997 // no border width adjustments for buttons
2998 return;
2999 }
3000#endif // wxUSE_BUTTON
3001
3002 // take into account the border width
3003 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
3004 size->x += rectBorder.x + rectBorder.width;
3005 size->y += rectBorder.y + rectBorder.height;
3006}
3007
3008// ============================================================================
3009// wxInputHandler
3010// ============================================================================
3011
3012// ----------------------------------------------------------------------------
3013// wxWin32InputHandler
3014// ----------------------------------------------------------------------------
3015
3016wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer)
3017{
3018 m_renderer = renderer;
3019}
3020
3021bool wxWin32InputHandler::HandleKey(wxControl *control,
3022 const wxKeyEvent& event,
3023 bool pressed)
3024{
3025 return FALSE;
3026}
3027
3028bool wxWin32InputHandler::HandleMouse(wxControl *control,
3029 const wxMouseEvent& event)
3030{
3031 return FALSE;
3032}
3033
3034// ----------------------------------------------------------------------------
3035// wxWin32ScrollBarInputHandler
3036// ----------------------------------------------------------------------------
3037
3038wxWin32ScrollBarInputHandler::
3039wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
3040 wxInputHandler *handler)
3041 : wxStdScrollBarInputHandler(renderer, handler)
3042{
3043 m_scrollPaused = FALSE;
3044 m_interval = 0;
3045}
3046
3047bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
3048 const wxControlAction& action)
3049{
3050 // stop if went beyond the position of the original click (this can only
3051 // happen when we scroll by pages)
3052 bool stop = FALSE;
3053 if ( action == wxACTION_SCROLL_PAGE_DOWN )
3054 {
3055 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
3056 != wxHT_SCROLLBAR_BAR_2;
3057 }
3058 else if ( action == wxACTION_SCROLL_PAGE_UP )
3059 {
3060 stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
3061 != wxHT_SCROLLBAR_BAR_1;
3062 }
3063
3064 if ( stop )
3065 {
3066 StopScrolling(scrollbar);
3067
3068 scrollbar->Refresh();
3069
3070 return FALSE;
3071 }
3072
3073 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
3074}
3075
3076bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl *control,
3077 const wxMouseEvent& event)
3078{
3079 // remember the current state
3080 bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
3081
3082 // do process the message
3083 bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
3084
3085 // analyse the changes
3086 if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
3087 {
3088 // we just started dragging the thumb, remember its initial position to
3089 // be able to restore it if the drag is cancelled later
3090 m_eventStartDrag = event;
3091 }
3092
3093 return rc;
3094}
3095
3096bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *control,
3097 const wxMouseEvent& event)
3098{
3099 // we don't highlight scrollbar elements, so there is no need to process
3100 // mouse move events normally - only do it while mouse is captured (i.e.
3101 // when we're dragging the thumb or pressing on something)
3102 if ( !m_winCapture )
3103 return FALSE;
3104
3105 if ( event.Entering() )
3106 {
3107 // we're not interested in this at all
3108 return FALSE;
3109 }
3110
3111 wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar);
3112 wxHitTest ht;
3113 if ( m_scrollPaused )
3114 {
3115 // check if the mouse returned to its original location
3116
3117 if ( event.Leaving() )
3118 {
3119 // it surely didn't
3120 return FALSE;
3121 }
3122
3123 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
3124 if ( ht == m_htLast )
3125 {
3126 // yes it did, resume scrolling
3127 m_scrollPaused = FALSE;
3128 if ( m_timerScroll )
3129 {
3130 // we were scrolling by line/page, restart timer
3131 m_timerScroll->Start(m_interval);
3132
3133 Press(scrollbar, TRUE);
3134 }
3135 else // we were dragging the thumb
3136 {
3137 // restore its last location
3138 HandleThumbMove(scrollbar, m_eventLastDrag);
3139 }
3140
3141 return TRUE;
3142 }
3143 }
3144 else // normal case, scrolling hasn't been paused
3145 {
3146 // if we're scrolling the scrollbar because the arrow or the shaft was
3147 // pressed, check that the mouse stays on the same scrollbar element
3148
3149 if ( event.Moving() )
3150 {
3151 ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
3152 }
3153 else // event.Leaving()
3154 {
3155 ht = wxHT_NOWHERE;
3156 }
3157
3158 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3159 // is still ok - we only want to catch the case when the mouse leaves
3160 // the scrollbar here
3161 if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
3162 {
3163 ht = wxHT_SCROLLBAR_THUMB;
3164 }
3165
3166 if ( ht != m_htLast )
3167 {
3168 // what were we doing? 2 possibilities: either an arrow/shaft was
3169 // pressed in which case we have a timer and so we just stop it or
3170 // we were dragging the thumb
3171 if ( m_timerScroll )
3172 {
3173 // pause scrolling
3174 m_interval = m_timerScroll->GetInterval();
3175 m_timerScroll->Stop();
3176 m_scrollPaused = TRUE;
3177
3178 // unpress the arrow
3179 Press(scrollbar, FALSE);
3180 }
3181 else // we were dragging the thumb
3182 {
3183 // remember the current thumb position to be able to restore it
3184 // if the mouse returns to it later
3185 m_eventLastDrag = event;
3186
3187 // and restore the original position (before dragging) of the
3188 // thumb for now
3189 HandleThumbMove(scrollbar, m_eventStartDrag);
3190 }
3191
3192 return TRUE;
3193 }
3194 }
3195
3196 return wxStdScrollBarInputHandler::HandleMouseMove(control, event);
3197}
3198
3199// ----------------------------------------------------------------------------
3200// wxWin32CheckboxInputHandler
3201// ----------------------------------------------------------------------------
3202
3203bool wxWin32CheckboxInputHandler::HandleKey(wxControl *control,
3204 const wxKeyEvent& event,
3205 bool pressed)
3206{
3207 if ( pressed )
3208 {
3209 wxControlAction action;
3210 int keycode = event.GetKeyCode();
3211 switch ( keycode )
3212 {
3213 case WXK_SPACE:
3214 action = wxACTION_CHECKBOX_TOGGLE;
3215 break;
3216
3217 case WXK_SUBTRACT:
3218 case WXK_NUMPAD_SUBTRACT:
3219 action = wxACTION_CHECKBOX_CHECK;
3220 break;
3221
3222 case WXK_ADD:
3223 case WXK_NUMPAD_ADD:
3224 case WXK_NUMPAD_EQUAL:
3225 action = wxACTION_CHECKBOX_CLEAR;
3226 break;
3227 }
3228
3229 if ( !!action )
3230 {
3231 control->PerformAction(action);
3232
3233 return TRUE;
3234 }
3235 }
3236
3237 return FALSE;
3238}
3239
3240// ----------------------------------------------------------------------------
3241// wxWin32TextCtrlInputHandler
3242// ----------------------------------------------------------------------------
3243
3244bool wxWin32TextCtrlInputHandler::HandleKey(wxControl *control,
3245 const wxKeyEvent& event,
3246 bool pressed)
3247{
3248 // handle only MSW-specific text bindings here, the others are handled in
3249 // the base class
3250 if ( pressed )
3251 {
3252 int keycode = event.GetKeyCode();
3253
3254 wxControlAction action;
3255 if ( keycode == WXK_DELETE && event.ShiftDown() )
3256 {
3257 action = wxACTION_TEXT_CUT;
3258 }
3259 else if ( keycode == WXK_INSERT )
3260 {
3261 if ( event.ControlDown() )
3262 action = wxACTION_TEXT_COPY;
3263 else if ( event.ShiftDown() )
3264 action = wxACTION_TEXT_PASTE;
3265 }
3266
3267 if ( action != wxACTION_NONE )
3268 {
3269 control->PerformAction(action);
3270
3271 return TRUE;
3272 }
3273 }
3274
3275 return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed);
3276}
3277