1 // Name: univ/themes/metal.cpp
2 // Purpose: wxUniversal theme implementing Win32-like LNF
3 // Author: Vadim Zeitlin, Robert Roebling
7 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows license
9 ///////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
30 #include "wx/window.h"
32 #include "wx/dcmemory.h"
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 #include "wx/toolbar.h"
44 // for COLOR_* constants
45 #include "wx/msw/private.h"
49 #include "wx/notebook.h"
50 #include "wx/spinbutt.h"
51 #include "wx/settings.h"
53 #include "wx/artprov.h"
54 #include "wx/toplevel.h"
56 #include "wx/univ/scrtimer.h"
57 #include "wx/univ/renderer.h"
58 #include "wx/univ/inphand.h"
59 #include "wx/univ/colschem.h"
60 #include "wx/univ/theme.h"
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 static const int BORDER_THICKNESS
= 2;
68 // the offset between the label and focus rect around it
69 static const int FOCUS_RECT_OFFSET_X
= 1;
70 static const int FOCUS_RECT_OFFSET_Y
= 1;
72 static const int FRAME_BORDER_THICKNESS
= 3;
73 static const int RESIZEABLE_FRAME_BORDER_THICKNESS
= 4;
74 static const int FRAME_TITLEBAR_HEIGHT
= 18;
75 static const int FRAME_BUTTON_WIDTH
= 16;
76 static const int FRAME_BUTTON_HEIGHT
= 14;
78 static const size_t NUM_STATUSBAR_GRIP_BANDS
= 3;
79 static const size_t WIDTH_STATUSBAR_GRIP_BAND
= 4;
80 static const size_t STATUSBAR_GRIP_SIZE
=
81 WIDTH_STATUSBAR_GRIP_BAND
*NUM_STATUSBAR_GRIP_BANDS
;
93 IndicatorState_Normal
,
94 IndicatorState_Pressed
, // this one is for check/radioboxes
95 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
96 IndicatorState_Disabled
,
97 IndicatorState_SelectedDisabled
, // only for the menus
103 IndicatorStatus_Checked
,
104 IndicatorStatus_Unchecked
,
108 // wxMetalRenderer: draw the GUI elements in Metal style
109 // ----------------------------------------------------------------------------
111 class wxMetalRenderer
: public wxRenderer
115 enum wxArrowDirection
130 Arrow_InversedDisabled
,
134 enum wxFrameButtonType
137 FrameButton_Minimize
,
138 FrameButton_Maximize
,
145 wxMetalRenderer(const wxColourScheme
*scheme
);
148 void DrawMetal(wxDC
&dc
, const wxRect
&rect
);
150 // implement the base class pure virtuals
151 virtual void DrawBackground(wxDC
& dc
,
155 wxWindow
*window
= NULL
);
156 virtual void DrawButtonSurface(wxDC
& dc
,
160 virtual void DrawLabel(wxDC
& dc
,
161 const wxString
& label
,
164 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
166 wxRect
*rectBounds
= NULL
);
167 virtual void DrawButtonLabel(wxDC
& dc
,
168 const wxString
& label
,
169 const wxBitmap
& image
,
172 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
174 wxRect
*rectBounds
= NULL
);
175 virtual void DrawBorder(wxDC
& dc
,
179 wxRect
*rectIn
= (wxRect
*)NULL
);
180 virtual void DrawHorizontalLine(wxDC
& dc
,
181 wxCoord y
, wxCoord x1
, wxCoord x2
);
182 virtual void DrawVerticalLine(wxDC
& dc
,
183 wxCoord x
, wxCoord y1
, wxCoord y2
);
184 virtual void DrawFrame(wxDC
& dc
,
185 const wxString
& label
,
188 int alignment
= wxALIGN_LEFT
,
189 int indexAccel
= -1);
190 virtual void DrawTextBorder(wxDC
& dc
,
194 wxRect
*rectIn
= (wxRect
*)NULL
);
195 virtual void DrawButtonBorder(wxDC
& dc
,
198 wxRect
*rectIn
= (wxRect
*)NULL
);
199 virtual void DrawArrow(wxDC
& dc
,
203 virtual void DrawScrollbarArrow(wxDC
& dc
,
207 { DrawArrow(dc
, dir
, rect
, flags
); }
208 virtual void DrawScrollbarThumb(wxDC
& dc
,
209 wxOrientation orient
,
212 virtual void DrawScrollbarShaft(wxDC
& dc
,
213 wxOrientation orient
,
216 virtual void DrawScrollCorner(wxDC
& dc
,
218 virtual void DrawItem(wxDC
& dc
,
219 const wxString
& label
,
222 virtual void DrawCheckItem(wxDC
& dc
,
223 const wxString
& label
,
224 const wxBitmap
& bitmap
,
227 virtual void DrawCheckButton(wxDC
& dc
,
228 const wxString
& label
,
229 const wxBitmap
& bitmap
,
232 wxAlignment align
= wxALIGN_LEFT
,
233 int indexAccel
= -1);
234 virtual void DrawRadioButton(wxDC
& dc
,
235 const wxString
& label
,
236 const wxBitmap
& bitmap
,
239 wxAlignment align
= wxALIGN_LEFT
,
240 int indexAccel
= -1);
241 virtual void DrawToolBarButton(wxDC
& dc
,
242 const wxString
& label
,
243 const wxBitmap
& bitmap
,
246 virtual void DrawTextLine(wxDC
& dc
,
247 const wxString
& text
,
252 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
253 virtual void DrawTab(wxDC
& dc
,
256 const wxString
& label
,
257 const wxBitmap
& bitmap
= wxNullBitmap
,
259 int indexAccel
= -1);
261 virtual void DrawSliderShaft(wxDC
& dc
,
263 wxOrientation orient
,
265 wxRect
*rectShaft
= NULL
);
266 virtual void DrawSliderThumb(wxDC
& dc
,
268 wxOrientation orient
,
270 virtual void DrawSliderTicks(wxDC
& dc
,
272 const wxSize
& sizeThumb
,
273 wxOrientation orient
,
279 virtual void DrawMenuBarItem(wxDC
& dc
,
281 const wxString
& label
,
283 int indexAccel
= -1);
284 virtual void DrawMenuItem(wxDC
& dc
,
286 const wxMenuGeometryInfo
& geometryInfo
,
287 const wxString
& label
,
288 const wxString
& accel
,
289 const wxBitmap
& bitmap
= wxNullBitmap
,
291 int indexAccel
= -1);
292 virtual void DrawMenuSeparator(wxDC
& dc
,
294 const wxMenuGeometryInfo
& geomInfo
);
296 virtual void DrawStatusField(wxDC
& dc
,
298 const wxString
& label
,
302 virtual void DrawFrameTitleBar(wxDC
& dc
,
304 const wxString
& title
,
307 int specialButton
= 0,
308 int specialButtonFlags
= 0);
309 virtual void DrawFrameBorder(wxDC
& dc
,
312 virtual void DrawFrameBackground(wxDC
& dc
,
315 virtual void DrawFrameTitle(wxDC
& dc
,
317 const wxString
& title
,
319 virtual void DrawFrameIcon(wxDC
& dc
,
323 virtual void DrawFrameButton(wxDC
& dc
,
324 wxCoord x
, wxCoord y
,
327 virtual wxRect
GetFrameClientArea(const wxRect
& rect
, int flags
) const;
328 virtual wxSize
GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const;
329 virtual wxSize
GetFrameMinSize(int flags
) const;
330 virtual wxSize
GetFrameIconSize() const;
331 virtual int HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const;
333 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
335 wxBitmap
*bmpPressed
,
336 wxBitmap
*bmpDisabled
);
338 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
339 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
340 virtual bool AreScrollbarsInsideBorder() const;
342 virtual wxSize
GetScrollbarArrowSize() const
343 { return m_sizeScrollbarArrow
; }
344 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
345 wxScrollBar::Element elem
,
346 int thumbPos
= -1) const;
347 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
348 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
349 const wxPoint
& pt
) const;
350 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
352 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
353 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
354 { return fontHeight
+ 2; }
355 virtual wxSize
GetCheckBitmapSize() const
356 { return wxSize(13, 13); }
357 virtual wxSize
GetRadioBitmapSize() const
358 { return wxSize(12, 12); }
359 virtual wxCoord
GetCheckItemMargin() const
362 virtual wxSize
GetToolBarButtonSize(wxCoord
*separator
) const
363 { if ( separator
) *separator
= 5; return wxSize(16, 15); }
364 virtual wxSize
GetToolBarMargin() const
365 { return wxSize(4, 4); }
367 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
368 const wxRect
& rect
) const;
369 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
371 wxCoord
*extraSpaceBeyond
) const;
373 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
374 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
376 virtual wxCoord
GetSliderDim() const { return 20; }
377 virtual wxCoord
GetSliderTickLen() const { return 4; }
378 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
379 wxOrientation orient
) const;
380 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
381 wxOrientation orient
) const;
382 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
384 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
385 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
386 const wxMenu
& menu
) const;
388 virtual wxSize
GetStatusBarBorders(wxCoord
*borderBetweenFields
) const;
391 // helper of DrawLabel() and DrawCheckOrRadioButton()
392 void DoDrawLabel(wxDC
& dc
,
393 const wxString
& label
,
396 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
398 wxRect
*rectBounds
= NULL
,
399 const wxPoint
& focusOffset
400 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
402 // common part of DrawLabel() and DrawItem()
403 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
405 // DrawLabel() and DrawButtonLabel() helper
406 void DrawLabelShadow(wxDC
& dc
,
407 const wxString
& label
,
412 // DrawButtonBorder() helper
413 void DoDrawBackground(wxDC
& dc
,
416 wxWindow
*window
= NULL
);
418 // DrawBorder() helpers: all of them shift and clip the DC after drawing
421 // just draw a rectangle with the given pen
422 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
424 // draw the lower left part of rectangle
425 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
427 // draw the rectange using the first brush for the left and top sides and
428 // the second one for the bottom and right ones
429 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
430 const wxPen
& pen1
, const wxPen
& pen2
);
432 // draw the normal 3D border
433 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
435 // draw the sunken 3D border
436 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
438 // draw the border used for scrollbar arrows
439 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
441 // public DrawArrow()s helper
442 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
443 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
445 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
446 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
447 wxArrowDirection arrowDir
,
448 wxArrowStyle arrowStyle
);
450 // DrawCheckButton/DrawRadioButton helper
451 void DrawCheckOrRadioButton(wxDC
& dc
,
452 const wxString
& label
,
453 const wxBitmap
& bitmap
,
458 wxCoord focusOffsetY
);
460 // draw a normal or transposed line (useful for using the same code fo both
461 // horizontal and vertical widgets)
462 void DrawLine(wxDC
& dc
,
463 wxCoord x1
, wxCoord y1
,
464 wxCoord x2
, wxCoord y2
,
465 bool transpose
= FALSE
)
468 dc
.DrawLine(y1
, x1
, y2
, x2
);
470 dc
.DrawLine(x1
, y1
, x2
, y2
);
473 // get the standard check/radio button bitmap
474 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
475 wxBitmap
GetCheckBitmap(int flags
)
476 { return GetIndicator(IndicatorType_Check
, flags
); }
477 wxBitmap
GetRadioBitmap(int flags
)
478 { return GetIndicator(IndicatorType_Radio
, flags
); }
481 const wxColourScheme
*m_scheme
;
483 // the sizing parameters (TODO make them changeable)
484 wxSize m_sizeScrollbarArrow
;
486 // GDI objects we use for drawing
487 wxColour m_colDarkGrey
,
495 wxFont m_titlebarFont
;
497 // the checked and unchecked bitmaps for DrawCheckItem()
498 wxBitmap m_bmpCheckBitmaps
[IndicatorStatus_Max
];
500 // the bitmaps returned by GetIndicator()
501 wxBitmap m_bmpIndicators
[IndicatorType_Max
]
503 [IndicatorStatus_Max
];
506 wxBitmap m_bmpFrameButtons
[FrameButton_Max
];
508 // first row is for the normal state, second - for the disabled
509 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
512 // ----------------------------------------------------------------------------
513 // wxMetalInputHandler and derived classes: process the keyboard and mouse
514 // messages according to Windows standards
515 // ----------------------------------------------------------------------------
517 class wxMetalInputHandler
: public wxInputHandler
520 wxMetalInputHandler(wxMetalRenderer
*renderer
);
522 virtual bool HandleKey(wxInputConsumer
*control
,
523 const wxKeyEvent
& event
,
525 virtual bool HandleMouse(wxInputConsumer
*control
,
526 const wxMouseEvent
& event
);
529 wxMetalRenderer
*m_renderer
;
532 class wxMetalScrollBarInputHandler
: public wxStdScrollBarInputHandler
535 wxMetalScrollBarInputHandler(wxMetalRenderer
*renderer
,
536 wxInputHandler
*handler
);
538 virtual bool HandleMouse(wxInputConsumer
*control
, const wxMouseEvent
& event
);
539 virtual bool HandleMouseMove(wxInputConsumer
*control
, const wxMouseEvent
& event
);
541 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
542 const wxControlAction
& action
);
545 virtual bool IsAllowedButton(int button
) { return button
== 1; }
547 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
549 // we don't highlight anything
552 // the first and last event which caused the thumb to move
553 wxMouseEvent m_eventStartDrag
,
556 // have we paused the scrolling because the mouse moved?
559 // we remember the interval of the timer to be able to restart it
563 class wxMetalCheckboxInputHandler
: public wxStdCheckboxInputHandler
566 wxMetalCheckboxInputHandler(wxInputHandler
*handler
)
567 : wxStdCheckboxInputHandler(handler
) { }
569 virtual bool HandleKey(wxInputConsumer
*control
,
570 const wxKeyEvent
& event
,
574 class wxMetalTextCtrlInputHandler
: public wxStdTextCtrlInputHandler
577 wxMetalTextCtrlInputHandler(wxInputHandler
*handler
)
578 : wxStdTextCtrlInputHandler(handler
) { }
580 virtual bool HandleKey(wxInputConsumer
*control
,
581 const wxKeyEvent
& event
,
585 class wxMetalStatusBarInputHandler
: public wxStdInputHandler
588 wxMetalStatusBarInputHandler(wxInputHandler
*handler
);
590 virtual bool HandleMouse(wxInputConsumer
*consumer
,
591 const wxMouseEvent
& event
);
593 virtual bool HandleMouseMove(wxInputConsumer
*consumer
,
594 const wxMouseEvent
& event
);
597 // is the given point over the statusbar grip?
598 bool IsOnGrip(wxWindow
*statbar
, const wxPoint
& pt
) const;
601 // the cursor we had replaced with the resize one
602 wxCursor m_cursorOld
;
604 // was the mouse over the grip last time we checked?
608 class wxMetalSystemMenuEvtHandler
;
610 class wxMetalFrameInputHandler
: public wxStdFrameInputHandler
613 wxMetalFrameInputHandler(wxInputHandler
*handler
);
614 ~wxMetalFrameInputHandler();
616 virtual bool HandleMouse(wxInputConsumer
*control
,
617 const wxMouseEvent
& event
);
619 virtual bool HandleActivation(wxInputConsumer
*consumer
, bool activated
);
621 void PopupSystemMenu(wxTopLevelWindow
*window
, const wxPoint
& pos
) const;
624 // was the mouse over the grip last time we checked?
625 wxMetalSystemMenuEvtHandler
*m_menuHandler
;
628 // ----------------------------------------------------------------------------
629 // wxMetalColourScheme: uses (default) Metal colours
630 // ----------------------------------------------------------------------------
632 class wxMetalColourScheme
: public wxColourScheme
635 virtual wxColour
Get(StdColour col
) const;
636 virtual wxColour
GetBackground(wxWindow
*win
) const;
639 // ----------------------------------------------------------------------------
640 // wxMetalArtProvider
641 // ----------------------------------------------------------------------------
643 class wxMetalArtProvider
: public wxArtProvider
646 virtual wxBitmap
CreateBitmap(const wxArtID
& id
,
647 const wxArtClient
& client
,
651 // ----------------------------------------------------------------------------
653 // ----------------------------------------------------------------------------
655 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
657 class wxMetalTheme
: public wxTheme
661 virtual ~wxMetalTheme();
663 virtual wxRenderer
*GetRenderer();
664 virtual wxArtProvider
*GetArtProvider();
665 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
666 virtual wxColourScheme
*GetColourScheme();
669 // get the default input handler
670 wxInputHandler
*GetDefaultInputHandler();
672 wxMetalRenderer
*m_renderer
;
674 wxMetalArtProvider
*m_artProvider
;
676 // the names of the already created handlers and the handlers themselves
677 // (these arrays are synchronized)
678 wxSortedArrayString m_handlerNames
;
679 wxArrayHandlers m_handlers
;
681 wxMetalInputHandler
*m_handlerDefault
;
683 wxMetalColourScheme
*m_scheme
;
685 WX_DECLARE_THEME(Metal
)
688 // ----------------------------------------------------------------------------
690 // ----------------------------------------------------------------------------
692 // frame buttons bitmaps
694 static const char *frame_button_close_xpm
[] = {
709 static const char *frame_button_help_xpm
[] = {
724 static const char *frame_button_maximize_xpm
[] = {
739 static const char *frame_button_minimize_xpm
[] = {
754 static const char *frame_button_restore_xpm
[] = {
771 static const char *checked_menu_xpm
[] = {
772 /* columns rows colors chars-per-pixel */
788 static const char *selected_checked_menu_xpm
[] = {
789 /* columns rows colors chars-per-pixel */
805 static const char *disabled_checked_menu_xpm
[] = {
806 /* columns rows colors chars-per-pixel */
823 static const char *selected_disabled_checked_menu_xpm
[] = {
824 /* columns rows colors chars-per-pixel */
840 // checkbox and radiobox bitmaps below
842 static const char *checked_xpm
[] = {
843 /* columns rows colors chars-per-pixel */
866 static const char *pressed_checked_xpm
[] = {
867 /* columns rows colors chars-per-pixel */
889 static const char *pressed_disabled_checked_xpm
[] = {
890 /* columns rows colors chars-per-pixel */
912 static const char *checked_item_xpm
[] = {
913 /* columns rows colors chars-per-pixel */
934 static const char *unchecked_xpm
[] = {
935 /* columns rows colors chars-per-pixel */
958 static const char *pressed_unchecked_xpm
[] = {
959 /* columns rows colors chars-per-pixel */
981 static const char *unchecked_item_xpm
[] = {
982 /* columns rows colors chars-per-pixel */
1002 static const char *checked_radio_xpm
[] = {
1003 /* columns rows colors chars-per-pixel */
1026 static const char *pressed_checked_radio_xpm
[] = {
1027 /* columns rows colors chars-per-pixel */
1050 static const char *pressed_disabled_checked_radio_xpm
[] = {
1051 /* columns rows colors chars-per-pixel */
1074 static const char *unchecked_radio_xpm
[] = {
1075 /* columns rows colors chars-per-pixel */
1098 static const char *pressed_unchecked_radio_xpm
[] = {
1099 /* columns rows colors chars-per-pixel */
1122 static const char **
1123 xpmIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
1128 { checked_xpm
, unchecked_xpm
},
1131 { pressed_checked_xpm
, pressed_unchecked_xpm
},
1134 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
1140 { checked_radio_xpm
, unchecked_radio_xpm
},
1143 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1146 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1152 { checked_menu_xpm
, NULL
},
1155 { selected_checked_menu_xpm
, NULL
},
1158 { disabled_checked_menu_xpm
, NULL
},
1160 // disabled selected state
1161 { selected_disabled_checked_menu_xpm
, NULL
},
1165 static const char **xpmChecked
[IndicatorStatus_Max
] =
1171 // ============================================================================
1173 // ============================================================================
1175 WX_IMPLEMENT_THEME(wxMetalTheme
, Metal
, wxTRANSLATE("Metal theme"));
1177 // ----------------------------------------------------------------------------
1179 // ----------------------------------------------------------------------------
1181 wxMetalTheme::wxMetalTheme()
1185 m_handlerDefault
= NULL
;
1186 m_artProvider
= NULL
;
1189 wxMetalTheme::~wxMetalTheme()
1191 size_t count
= m_handlers
.GetCount();
1192 for ( size_t n
= 0; n
< count
; n
++ )
1194 if ( m_handlers
[n
] != m_handlerDefault
)
1195 delete m_handlers
[n
];
1198 delete m_handlerDefault
;
1204 wxRenderer
*wxMetalTheme::GetRenderer()
1208 m_renderer
= new wxMetalRenderer(GetColourScheme());
1214 wxArtProvider
*wxMetalTheme::GetArtProvider()
1216 if ( !m_artProvider
)
1218 m_artProvider
= new wxMetalArtProvider
;
1221 return m_artProvider
;
1224 wxInputHandler
*wxMetalTheme::GetDefaultInputHandler()
1226 if ( !m_handlerDefault
)
1228 m_handlerDefault
= new wxMetalInputHandler(m_renderer
);
1231 return m_handlerDefault
;
1234 wxInputHandler
*wxMetalTheme::GetInputHandler(const wxString
& control
)
1236 wxInputHandler
*handler
;
1237 int n
= m_handlerNames
.Index(control
);
1238 if ( n
== wxNOT_FOUND
)
1240 // create a new handler
1241 if ( control
== wxINP_HANDLER_SCROLLBAR
)
1242 handler
= new wxMetalScrollBarInputHandler(m_renderer
,
1243 GetDefaultInputHandler());
1245 else if ( control
== wxINP_HANDLER_BUTTON
)
1246 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
1247 #endif // wxUSE_BUTTON
1249 else if ( control
== wxINP_HANDLER_CHECKBOX
)
1250 handler
= new wxMetalCheckboxInputHandler(GetDefaultInputHandler());
1251 #endif // wxUSE_CHECKBOX
1253 else if ( control
== wxINP_HANDLER_COMBOBOX
)
1254 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1255 #endif // wxUSE_COMBOBOX
1257 else if ( control
== wxINP_HANDLER_LISTBOX
)
1258 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1259 #endif // wxUSE_LISTBOX
1260 #if wxUSE_CHECKLISTBOX
1261 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1262 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1263 #endif // wxUSE_CHECKLISTBOX
1265 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1266 handler
= new wxMetalTextCtrlInputHandler(GetDefaultInputHandler());
1267 #endif // wxUSE_TEXTCTRL
1269 else if ( control
== wxINP_HANDLER_SLIDER
)
1270 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1271 #endif // wxUSE_SLIDER
1273 else if ( control
== wxINP_HANDLER_SPINBTN
)
1274 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1275 #endif // wxUSE_SPINBTN
1277 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1278 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1279 #endif // wxUSE_NOTEBOOK
1281 else if ( control
== wxINP_HANDLER_STATUSBAR
)
1282 handler
= new wxMetalStatusBarInputHandler(GetDefaultInputHandler());
1283 #endif // wxUSE_STATUSBAR
1285 else if ( control
== wxINP_HANDLER_TOOLBAR
)
1286 handler
= new wxStdToolbarInputHandler(GetDefaultInputHandler());
1287 #endif // wxUSE_TOOLBAR
1288 else if ( control
== wxINP_HANDLER_TOPLEVEL
)
1289 handler
= new wxMetalFrameInputHandler(GetDefaultInputHandler());
1291 handler
= GetDefaultInputHandler();
1293 n
= m_handlerNames
.Add(control
);
1294 m_handlers
.Insert(handler
, n
);
1296 else // we already have it
1298 handler
= m_handlers
[n
];
1304 wxColourScheme
*wxMetalTheme::GetColourScheme()
1308 m_scheme
= new wxMetalColourScheme
;
1313 // ============================================================================
1314 // wxMetalColourScheme
1315 // ============================================================================
1317 wxColour
wxMetalColourScheme::GetBackground(wxWindow
*win
) const
1320 if ( win
->UseBgCol() )
1322 // use the user specified colour
1323 col
= win
->GetBackgroundColour();
1326 if ( win
->IsContainerWindow() )
1328 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1331 if ( !text
->IsEnabled() ) // not IsEditable()
1333 //else: execute code below
1338 // doesn't depend on the state
1344 int flags
= win
->GetStateFlags();
1346 // the colour set by the user should be used for the normal state
1347 // and for the states for which we don't have any specific colours
1348 if ( !col
.Ok() || (flags
& wxCONTROL_PRESSED
) != 0 )
1350 if ( wxDynamicCast(win
, wxScrollBar
) )
1351 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1361 wxColour
wxMetalColourScheme::Get(wxMetalColourScheme::StdColour col
) const
1365 // use the system colours under Windows
1366 #if defined(__WXMSW__)
1367 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1369 case CONTROL_PRESSED
:
1370 case CONTROL_CURRENT
:
1371 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1373 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1375 #if defined(COLOR_3DLIGHT)
1376 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_3DLIGHT
));
1378 case SCROLLBAR
: return wxColour(0xe0e0e0);
1380 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1382 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1383 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1385 #if defined(COLOR_3DDKSHADOW)
1386 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1388 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DHADOW
));
1391 case CONTROL_TEXT_DISABLED
:
1392 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1394 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1396 case CONTROL_TEXT_DISABLED_SHADOW
:
1397 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1399 case TITLEBAR
: return wxColour(GetSysColor(COLOR_INACTIVECAPTION
));
1400 case TITLEBAR_ACTIVE
: return wxColour(GetSysColor(COLOR_ACTIVECAPTION
));
1401 case TITLEBAR_TEXT
: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT
));
1402 case TITLEBAR_ACTIVE_TEXT
: return wxColour(GetSysColor(COLOR_CAPTIONTEXT
));
1404 case DESKTOP
: return wxColour(0x808000);
1406 // use the standard Windows colours elsewhere
1407 case WINDOW
: return *wxWHITE
;
1409 case CONTROL_PRESSED
:
1410 case CONTROL_CURRENT
:
1411 case CONTROL
: return wxColour(0xc0c0c0);
1413 case CONTROL_TEXT
: return *wxBLACK
;
1415 case SCROLLBAR
: return wxColour(0xe0e0e0);
1416 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1418 case HIGHLIGHT
: return wxColour(0x800000);
1419 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1421 case SHADOW_DARK
: return *wxBLACK
;
1423 case CONTROL_TEXT_DISABLED
:return wxColour(0xe0e0e0);
1424 case SHADOW_HIGHLIGHT
: return wxColour(0xffffff);
1426 case SHADOW_IN
: return wxColour(0xc0c0c0);
1428 case CONTROL_TEXT_DISABLED_SHADOW
:
1429 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1431 case TITLEBAR
: return wxColour(0xaeaaae);
1432 case TITLEBAR_ACTIVE
: return wxColour(0x820300);
1433 case TITLEBAR_TEXT
: return wxColour(0xc0c0c0);
1434 case TITLEBAR_ACTIVE_TEXT
:return *wxWHITE
;
1436 case DESKTOP
: return wxColour(0x808000);
1439 case GAUGE
: return Get(HIGHLIGHT
);
1443 wxFAIL_MSG(_T("invalid standard colour"));
1448 // ============================================================================
1450 // ============================================================================
1452 // ----------------------------------------------------------------------------
1454 // ----------------------------------------------------------------------------
1456 wxMetalRenderer::wxMetalRenderer(const wxColourScheme
*scheme
)
1460 m_sizeScrollbarArrow
= wxSize(16, 16);
1462 // init colours and pens
1463 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1465 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1466 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1468 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1470 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1471 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1473 m_titlebarFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
1474 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
1476 // init the arrow bitmaps
1477 static const size_t ARROW_WIDTH
= 7;
1478 static const size_t ARROW_LENGTH
= 4;
1481 wxMemoryDC dcNormal
,
1484 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1486 bool isVertical
= n
> Arrow_Right
;
1499 // disabled arrow is larger because of the shadow
1500 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1501 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1503 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1504 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1506 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1507 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1511 dcNormal
.SetPen(m_penBlack
);
1512 dcDisabled
.SetPen(m_penDarkGrey
);
1514 // calculate the position of the point of the arrow
1518 x1
= (ARROW_WIDTH
- 1)/2;
1519 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1523 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1524 y1
= (ARROW_WIDTH
- 1)/2;
1535 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1537 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1538 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1545 if ( n
== Arrow_Up
)
1556 else // left or right arrow
1561 if ( n
== Arrow_Left
)
1574 // draw the shadow for the disabled one
1575 dcDisabled
.SetPen(m_penHighlight
);
1580 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1584 x1
= ARROW_LENGTH
- 1;
1585 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1588 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1589 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1594 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1598 x1
= ARROW_WIDTH
- 1;
1600 x2
= (ARROW_WIDTH
- 1)/2;
1602 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1603 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1608 // create the inversed bitmap but only for the right arrow as we only
1609 // use it for the menus
1610 if ( n
== Arrow_Right
)
1612 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1613 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1615 dcInverse
.Blit(0, 0, w
, h
,
1618 dcInverse
.SelectObject(wxNullBitmap
);
1620 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1621 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1623 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1624 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1626 dcInverse
.Blit(0, 0, w
, h
,
1629 dcInverse
.SelectObject(wxNullBitmap
);
1631 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1632 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1635 dcNormal
.SelectObject(wxNullBitmap
);
1636 dcDisabled
.SelectObject(wxNullBitmap
);
1638 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1639 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1640 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1641 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1643 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1646 // init the frame buttons bitmaps
1647 m_bmpFrameButtons
[FrameButton_Close
] = wxBitmap(frame_button_close_xpm
);
1648 m_bmpFrameButtons
[FrameButton_Minimize
] = wxBitmap(frame_button_minimize_xpm
);
1649 m_bmpFrameButtons
[FrameButton_Maximize
] = wxBitmap(frame_button_maximize_xpm
);
1650 m_bmpFrameButtons
[FrameButton_Restore
] = wxBitmap(frame_button_restore_xpm
);
1651 m_bmpFrameButtons
[FrameButton_Help
] = wxBitmap(frame_button_help_xpm
);
1654 // ----------------------------------------------------------------------------
1656 // ----------------------------------------------------------------------------
1659 The raised border in Metal looks like this:
1661 IIIIIIIIIIIIIIIIIIIIIIB
1663 I GB I = white (HILIGHT)
1664 I GB H = light grey (LIGHT)
1665 I GB G = dark grey (SHADOI)
1666 I GB B = black (DKSHADOI)
1667 I GB I = hIghlight (COLOR_3DHILIGHT)
1669 IGGGGGGGGGGGGGGGGGGGGGB
1670 BBBBBBBBBBBBBBBBBBBBBBB
1672 The sunken border looks like this:
1674 GGGGGGGGGGGGGGGGGGGGGGI
1675 GBBBBBBBBBBBBBBBBBBBBHI
1682 GHHHHHHHHHHHHHHHHHHHHHI
1683 IIIIIIIIIIIIIIIIIIIIIII
1685 The static border (used for the controls which don't get focus) is like
1688 GGGGGGGGGGGGGGGGGGGGGGW
1696 WWWWWWWWWWWWWWWWWWWWWWW
1698 The most complicated is the double border:
1700 HHHHHHHHHHHHHHHHHHHHHHB
1701 HWWWWWWWWWWWWWWWWWWWWGB
1702 HWHHHHHHHHHHHHHHHHHHHGB
1707 HWHHHHHHHHHHHHHHHHHHHGB
1708 HGGGGGGGGGGGGGGGGGGGGGB
1709 BBBBBBBBBBBBBBBBBBBBBBB
1711 And the simple border is, well, simple:
1713 BBBBBBBBBBBBBBBBBBBBBBB
1722 BBBBBBBBBBBBBBBBBBBBBBB
1725 void wxMetalRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1729 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1730 dc
.DrawRectangle(*rect
);
1736 void wxMetalRenderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1738 // draw the bottom and right sides
1740 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1741 rect
->GetRight() + 1, rect
->GetBottom());
1742 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1743 rect
->GetRight(), rect
->GetBottom());
1750 void wxMetalRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1751 const wxPen
& pen1
, const wxPen
& pen2
)
1753 // draw the rectangle
1755 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1756 rect
->GetLeft(), rect
->GetBottom());
1757 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1758 rect
->GetRight(), rect
->GetTop());
1760 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1761 rect
->GetRight(), rect
->GetBottom());
1762 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1763 rect
->GetRight() + 1, rect
->GetBottom());
1769 void wxMetalRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1771 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1772 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1775 void wxMetalRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1777 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1778 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1781 void wxMetalRenderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1785 DrawRect(dc
, rect
, m_penDarkGrey
);
1787 // the arrow is usually drawn inside border of width 2 and is offset by
1788 // another pixel in both directions when it's pressed - as the border
1789 // in this case is more narrow as well, we have to adjust rect like
1797 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1798 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1802 void wxMetalRenderer::DrawBorder(wxDC
& dc
,
1804 const wxRect
& rectTotal
,
1805 int WXUNUSED(flags
),
1810 wxRect rect
= rectTotal
;
1814 case wxBORDER_SUNKEN
:
1815 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1817 DrawSunkenBorder(dc
, &rect
);
1821 case wxBORDER_STATIC
:
1822 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1825 case wxBORDER_RAISED
:
1826 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1828 DrawRaisedBorder(dc
, &rect
);
1832 case wxBORDER_DOUBLE
:
1833 DrawArrowBorder(dc
, &rect
);
1834 DrawRect(dc
, &rect
, m_penLightGrey
);
1837 case wxBORDER_SIMPLE
:
1838 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1840 DrawRect(dc
, &rect
, m_penBlack
);
1845 wxFAIL_MSG(_T("unknown border type"));
1848 case wxBORDER_DEFAULT
:
1857 wxRect
wxMetalRenderer::GetBorderDimensions(wxBorder border
) const
1862 case wxBORDER_RAISED
:
1863 case wxBORDER_SUNKEN
:
1864 width
= BORDER_THICKNESS
;
1867 case wxBORDER_SIMPLE
:
1868 case wxBORDER_STATIC
:
1872 case wxBORDER_DOUBLE
:
1878 // char *crash = NULL;
1880 wxFAIL_MSG(_T("unknown border type"));
1884 case wxBORDER_DEFAULT
:
1894 rect
.height
= width
;
1899 bool wxMetalRenderer::AreScrollbarsInsideBorder() const
1904 // ----------------------------------------------------------------------------
1906 // ----------------------------------------------------------------------------
1908 void wxMetalRenderer::DrawTextBorder(wxDC
& dc
,
1914 // text controls are not special under windows
1915 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1918 void wxMetalRenderer::DrawButtonBorder(wxDC
& dc
,
1919 const wxRect
& rectTotal
,
1923 wxRect rect
= rectTotal
;
1925 if ( flags
& wxCONTROL_PRESSED
)
1927 // button pressed: draw a double border around it
1928 DrawRect(dc
, &rect
, m_penBlack
);
1929 DrawRect(dc
, &rect
, m_penDarkGrey
);
1933 // button not pressed
1935 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1937 // button either default or focused (or both): add an extra border around it
1938 DrawRect(dc
, &rect
, m_penBlack
);
1941 // now draw a normal button
1942 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1943 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1952 // ----------------------------------------------------------------------------
1954 // ----------------------------------------------------------------------------
1956 void wxMetalRenderer::DrawHorizontalLine(wxDC
& dc
,
1957 wxCoord y
, wxCoord x1
, wxCoord x2
)
1959 dc
.SetPen(m_penDarkGrey
);
1960 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1961 dc
.SetPen(m_penHighlight
);
1963 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1966 void wxMetalRenderer::DrawVerticalLine(wxDC
& dc
,
1967 wxCoord x
, wxCoord y1
, wxCoord y2
)
1969 dc
.SetPen(m_penDarkGrey
);
1970 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1971 dc
.SetPen(m_penHighlight
);
1973 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1976 void wxMetalRenderer::DrawFrame(wxDC
& dc
,
1977 const wxString
& label
,
1983 wxCoord height
= 0; // of the label
1984 wxRect rectFrame
= rect
;
1985 if ( !label
.empty() )
1987 // the text should touch the top border of the rect, so the frame
1988 // itself should be lower
1989 dc
.GetTextExtent(label
, NULL
, &height
);
1990 rectFrame
.y
+= height
/ 2;
1991 rectFrame
.height
-= height
/ 2;
1993 // we have to draw each part of the frame individually as we can't
1994 // erase the background beyond the label as it might contain some
1995 // pixmap already, so drawing everything and then overwriting part of
1996 // the frame with label doesn't work
1998 // TODO: the +5 and space insertion should be customizable
2001 rectText
.x
= rectFrame
.x
+ 5;
2002 rectText
.y
= rect
.y
;
2003 rectText
.width
= rectFrame
.width
- 7; // +2 border width
2004 rectText
.height
= height
;
2007 label2
<< _T(' ') << label
<< _T(' ');
2008 if ( indexAccel
!= -1 )
2010 // adjust it as we prepended a space
2015 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
2017 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
2021 // just draw the complete frame
2022 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
2023 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
2027 // ----------------------------------------------------------------------------
2029 // ----------------------------------------------------------------------------
2031 void wxMetalRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
2033 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
2034 // pixels each while we really need dots here... PS_ALTERNATE might
2035 // work, but it is for NT 5 only
2037 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
2039 // draw the pixels manually: note that to behave in the same manner as
2040 // DrawRect(), we must exclude the bottom and right borders from the
2042 wxCoord x1
= rect
.GetLeft(),
2044 x2
= rect
.GetRight(),
2045 y2
= rect
.GetBottom();
2047 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
2049 // this seems to be closer than what Windows does than wxINVERT although
2050 // I'm still not sure if it's correct
2051 dc
.SetLogicalFunction(wxAND_REVERSE
);
2054 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
2055 dc
.DrawPoint(z
, rect
.GetTop());
2057 wxCoord shift
= z
== x2
? 0 : 1;
2058 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
2059 dc
.DrawPoint(x2
, z
);
2061 shift
= z
== y2
? 0 : 1;
2062 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
2063 dc
.DrawPoint(z
, y2
);
2065 shift
= z
== x1
? 0 : 1;
2066 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
2067 dc
.DrawPoint(x1
, z
);
2069 dc
.SetLogicalFunction(wxCOPY
);
2073 void wxMetalRenderer::DrawLabelShadow(wxDC
& dc
,
2074 const wxString
& label
,
2079 // draw shadow of the text
2080 dc
.SetTextForeground(m_colHighlight
);
2081 wxRect rectShadow
= rect
;
2084 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
2086 // make the text grey
2087 dc
.SetTextForeground(m_colDarkGrey
);
2090 void wxMetalRenderer::DrawLabel(wxDC
& dc
,
2091 const wxString
& label
,
2098 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
2101 void wxMetalRenderer::DoDrawLabel(wxDC
& dc
,
2102 const wxString
& label
,
2108 const wxPoint
& focusOffset
)
2110 // the underscores are not drawn for focused controls in wxMSW
2111 if ( flags
& wxCONTROL_FOCUSED
)
2116 if ( flags
& wxCONTROL_DISABLED
)
2118 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2119 // currently only can happen for a menu item and it seems that Windows
2120 // doesn't draw the shadow in this case, so we don't do it neither
2121 if ( flags
& wxCONTROL_SELECTED
)
2123 // just make the label text greyed out
2124 dc
.SetTextForeground(m_colDarkGrey
);
2126 else // draw normal disabled label
2128 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
2133 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
2135 if ( flags
& wxCONTROL_DISABLED
)
2137 // restore the fg colour
2138 dc
.SetTextForeground(*wxBLACK
);
2141 if ( flags
& wxCONTROL_FOCUSED
)
2143 if ( focusOffset
.x
|| focusOffset
.y
)
2145 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
2148 DrawFocusRect(dc
, rectLabel
);
2152 *rectBounds
= rectLabel
;
2155 void wxMetalRenderer::DrawButtonLabel(wxDC
& dc
,
2156 const wxString
& label
,
2157 const wxBitmap
& image
,
2164 // the underscores are not drawn for focused controls in wxMSW
2165 if ( flags
& wxCONTROL_PRESSED
)
2170 wxRect rectLabel
= rect
;
2171 if ( !label
.empty() )
2173 // shift the label if a button is pressed
2174 if ( flags
& wxCONTROL_PRESSED
)
2180 if ( flags
& wxCONTROL_DISABLED
)
2182 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
2185 // leave enough space for the focus rectangle
2186 if ( flags
& wxCONTROL_FOCUSED
)
2188 rectLabel
.Inflate(-2);
2192 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
2194 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
2196 if ( flags
& wxCONTROL_PRESSED
)
2198 // the focus rectangle is never pressed, so undo the shift done
2206 DrawFocusRect(dc
, rectLabel
);
2210 // ----------------------------------------------------------------------------
2211 // (check)listbox items
2212 // ----------------------------------------------------------------------------
2214 void wxMetalRenderer::DrawItem(wxDC
& dc
,
2215 const wxString
& label
,
2219 wxDCTextColourChanger
colChanger(dc
);
2221 if ( flags
& wxCONTROL_SELECTED
)
2223 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2225 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2226 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2227 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2228 dc
.DrawRectangle(rect
);
2231 wxRect rectText
= rect
;
2233 rectText
.width
-= 2;
2234 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
2236 if ( flags
& wxCONTROL_FOCUSED
)
2238 DrawFocusRect(dc
, rect
);
2242 void wxMetalRenderer::DrawCheckItem(wxDC
& dc
,
2243 const wxString
& label
,
2244 const wxBitmap
& bitmap
,
2253 else // use default bitmap
2255 IndicatorStatus i
= flags
& wxCONTROL_CHECKED
2256 ? IndicatorStatus_Checked
2257 : IndicatorStatus_Unchecked
;
2259 if ( !m_bmpCheckBitmaps
[i
].Ok() )
2261 m_bmpCheckBitmaps
[i
] = wxBitmap(xpmChecked
[i
]);
2264 bmp
= m_bmpCheckBitmaps
[i
];
2267 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
2268 TRUE
/* use mask */);
2270 wxRect rectLabel
= rect
;
2271 int bmpWidth
= bmp
.GetWidth();
2272 rectLabel
.x
+= bmpWidth
;
2273 rectLabel
.width
-= bmpWidth
;
2275 DrawItem(dc
, label
, rectLabel
, flags
);
2278 // ----------------------------------------------------------------------------
2279 // check/radio buttons
2280 // ----------------------------------------------------------------------------
2282 wxBitmap
wxMetalRenderer::GetIndicator(IndicatorType indType
, int flags
)
2284 IndicatorState indState
;
2285 if ( flags
& wxCONTROL_SELECTED
)
2286 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
2287 : IndicatorState_Selected
;
2288 else if ( flags
& wxCONTROL_DISABLED
)
2289 indState
= IndicatorState_Disabled
;
2290 else if ( flags
& wxCONTROL_PRESSED
)
2291 indState
= IndicatorState_Pressed
;
2293 indState
= IndicatorState_Normal
;
2295 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
2296 ? IndicatorStatus_Checked
2297 : IndicatorStatus_Unchecked
;
2299 wxBitmap bmp
= m_bmpIndicators
[indType
][indState
][indStatus
];
2302 const char **xpm
= xpmIndicators
[indType
][indState
][indStatus
];
2305 // create and cache it
2306 bmp
= wxBitmap(xpm
);
2307 m_bmpIndicators
[indType
][indState
][indStatus
] = bmp
;
2314 void wxMetalRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
2315 const wxString
& label
,
2316 const wxBitmap
& bitmap
,
2321 wxCoord focusOffsetY
)
2323 // calculate the position of the bitmap and of the label
2324 wxCoord heightBmp
= bitmap
.GetHeight();
2326 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2329 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2330 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2332 // align label vertically with the bitmap - looks nicer like this
2333 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2335 // calc horz position
2336 if ( align
== wxALIGN_RIGHT
)
2338 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2339 rectLabel
.x
= rect
.x
+ 3;
2340 rectLabel
.SetRight(xBmp
);
2342 else // normal (checkbox to the left of the text) case
2345 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2346 rectLabel
.SetRight(rect
.GetRight());
2349 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2352 dc
, label
, rectLabel
,
2354 wxALIGN_LEFT
| wxALIGN_TOP
,
2356 NULL
, // we don't need bounding rect
2357 // use custom vert focus rect offset
2358 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2362 void wxMetalRenderer::DrawRadioButton(wxDC
& dc
,
2363 const wxString
& label
,
2364 const wxBitmap
& bitmap
,
2374 bmp
= GetRadioBitmap(flags
);
2376 DrawCheckOrRadioButton(dc
, label
,
2378 rect
, flags
, align
, indexAccel
,
2379 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2382 void wxMetalRenderer::DrawCheckButton(wxDC
& dc
,
2383 const wxString
& label
,
2384 const wxBitmap
& bitmap
,
2394 bmp
= GetCheckBitmap(flags
);
2396 DrawCheckOrRadioButton(dc
, label
,
2398 rect
, flags
, align
, indexAccel
,
2399 0); // no focus rect offset for checkboxes
2402 void wxMetalRenderer::DrawToolBarButton(wxDC
& dc
,
2403 const wxString
& label
,
2404 const wxBitmap
& bitmap
,
2405 const wxRect
& rectOrig
,
2408 if ( !label
.empty() || bitmap
.Ok() )
2410 wxRect rect
= rectOrig
;
2411 rect
.Deflate(BORDER_THICKNESS
);
2413 if ( flags
& wxCONTROL_PRESSED
)
2415 DrawBorder(dc
, wxBORDER_SUNKEN
, rect
, flags
);
2417 else if ( flags
& wxCONTROL_CURRENT
)
2419 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
);
2422 dc
.DrawLabel(label
, bitmap
, rect
, wxALIGN_CENTRE
);
2426 // leave a small gap aroudn the line, also account for the toolbar
2428 DrawVerticalLine(dc
, rectOrig
.x
+ rectOrig
.width
/2,
2429 rectOrig
.y
+ 2*BORDER_THICKNESS
,
2430 rectOrig
.GetBottom() - BORDER_THICKNESS
);
2434 // ----------------------------------------------------------------------------
2436 // ----------------------------------------------------------------------------
2438 void wxMetalRenderer::DrawTextLine(wxDC
& dc
,
2439 const wxString
& text
,
2445 // nothing special to do here
2446 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2449 void wxMetalRenderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2451 // we don't draw them
2454 // ----------------------------------------------------------------------------
2456 // ----------------------------------------------------------------------------
2458 void wxMetalRenderer::DrawTab(wxDC
& dc
,
2459 const wxRect
& rectOrig
,
2461 const wxString
& label
,
2462 const wxBitmap
& bitmap
,
2466 wxRect rect
= rectOrig
;
2468 // the current tab is drawn indented (to the top for default case) and
2469 // bigger than the other ones
2470 const wxSize indent
= GetTabIndent();
2471 if ( flags
& wxCONTROL_SELECTED
)
2476 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2480 rect
.Inflate(indent
.x
, 0);
2482 rect
.height
+= indent
.y
;
2486 rect
.Inflate(indent
.x
, 0);
2487 rect
.height
+= indent
.y
;
2492 wxFAIL_MSG(_T("TODO"));
2497 // draw the text, image and the focus around them (if necessary)
2498 wxRect rectLabel
= rect
;
2499 rectLabel
.Deflate(1, 1);
2500 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2501 flags
, wxALIGN_CENTRE
, indexAccel
);
2503 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2504 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2507 x2
= rect
.GetRight(),
2508 y2
= rect
.GetBottom();
2510 // FIXME: all this code will break if the tab indent or the border width,
2511 // it is tied to the fact that both of them are equal to 2
2516 dc
.SetPen(m_penHighlight
);
2517 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2518 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2519 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2521 dc
.SetPen(m_penBlack
);
2522 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2523 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2525 dc
.SetPen(m_penDarkGrey
);
2526 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2528 if ( flags
& wxCONTROL_SELECTED
)
2530 dc
.SetPen(m_penLightGrey
);
2532 // overwrite the part of the border below this tab
2533 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2535 // and the shadow of the tab to the left of us
2536 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2541 dc
.SetPen(m_penHighlight
);
2542 // we need to continue one pixel further to overwrite the corner of
2543 // the border for the selected tab
2544 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2546 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2548 dc
.SetPen(m_penBlack
);
2549 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2550 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2551 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2553 dc
.SetPen(m_penDarkGrey
);
2554 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2555 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2557 if ( flags
& wxCONTROL_SELECTED
)
2559 dc
.SetPen(m_penLightGrey
);
2561 // overwrite the part of the (double!) border above this tab
2562 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2563 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2565 // and the shadow of the tab to the left of us
2566 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2572 wxFAIL_MSG(_T("TODO"));
2576 // ----------------------------------------------------------------------------
2578 // ----------------------------------------------------------------------------
2580 wxSize
wxMetalRenderer::GetSliderThumbSize(const wxRect
& rect
,
2581 wxOrientation orient
) const
2585 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2586 if ( orient
== wxHORIZONTAL
)
2588 size
.y
= rect
.height
- 6;
2589 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2593 size
.x
= rect
.width
- 6;
2594 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2600 wxRect
wxMetalRenderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2601 wxOrientation orient
) const
2603 static const wxCoord SLIDER_MARGIN
= 6;
2605 wxRect rect
= rectOrig
;
2607 if ( orient
== wxHORIZONTAL
)
2609 // make the rect of minimal width and centre it
2610 rect
.height
= 2*BORDER_THICKNESS
;
2611 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2615 // leave margins on the sides
2616 rect
.Deflate(SLIDER_MARGIN
, 0);
2620 // same as above but in other direction
2621 rect
.width
= 2*BORDER_THICKNESS
;
2622 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2626 rect
.Deflate(0, SLIDER_MARGIN
);
2632 void wxMetalRenderer::DrawSliderShaft(wxDC
& dc
,
2633 const wxRect
& rectOrig
,
2634 wxOrientation orient
,
2638 if ( flags
& wxCONTROL_FOCUSED
)
2640 DrawFocusRect(dc
, rectOrig
);
2643 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2648 DrawSunkenBorder(dc
, &rect
);
2651 void wxMetalRenderer::DrawSliderThumb(wxDC
& dc
,
2653 wxOrientation orient
,
2657 we are drawing a shape of this form
2662 H DB where H is hightlight colour
2675 The interior of this shape is filled with the hatched brush if the thumb
2679 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2681 bool transpose
= orient
== wxVERTICAL
;
2683 wxCoord x
, y
, x2
, y2
;
2688 x2
= rect
.GetBottom();
2689 y2
= rect
.GetRight();
2695 x2
= rect
.GetRight();
2696 y2
= rect
.GetBottom();
2699 // the size of the pointed part of the thumb
2700 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2702 wxCoord x3
= x
+ sizeArrow
,
2703 y3
= y2
- sizeArrow
;
2705 dc
.SetPen(m_penHighlight
);
2706 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2707 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2708 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2710 dc
.SetPen(m_penBlack
);
2711 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2712 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2714 dc
.SetPen(m_penDarkGrey
);
2715 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2716 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2718 if ( flags
& wxCONTROL_PRESSED
)
2720 // TODO: MSW fills the entire area inside, not just the rect
2721 wxRect rectInt
= rect
;
2723 rectInt
.SetRight(y3
);
2725 rectInt
.SetBottom(y3
);
2728 #if !defined(__WXMGL__)
2729 static const char *stipple_xpm
[] = {
2730 /* columns rows colors chars-per-pixel */
2739 // VS: MGL can only do 8x8 stipple brushes
2740 static const char *stipple_xpm
[] = {
2741 /* columns rows colors chars-per-pixel */
2756 dc
.SetBrush(wxBrush(stipple_xpm
));
2758 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2759 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2760 dc
.SetPen(*wxTRANSPARENT_PEN
);
2761 dc
.DrawRectangle(rectInt
);
2765 void wxMetalRenderer::DrawSliderTicks(wxDC
& dc
,
2767 const wxSize
& sizeThumb
,
2768 wxOrientation orient
,
2780 // the variable names correspond to horizontal case, but they can be used
2781 // for both orientations
2782 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2783 if ( orient
== wxHORIZONTAL
)
2785 x1
= rect
.GetLeft();
2786 x2
= rect
.GetRight();
2788 // draw from bottom to top to leave one pixel space between the ticks
2789 // and the slider as Windows do
2790 y1
= rect
.GetBottom();
2795 widthThumb
= sizeThumb
.x
;
2800 x2
= rect
.GetBottom();
2802 y1
= rect
.GetRight();
2803 y2
= rect
.GetLeft();
2807 widthThumb
= sizeThumb
.y
;
2810 // the first tick should be positioned in such way that a thumb drawn in
2811 // the first position points down directly to it
2812 x1
+= widthThumb
/ 2;
2813 x2
-= widthThumb
/ 2;
2815 // this also means that we have slightly less space for the ticks in
2816 // between the first and the last
2819 dc
.SetPen(m_penBlack
);
2821 int range
= end
- start
;
2822 for ( int n
= 0; n
< range
; n
+= step
)
2824 wxCoord x
= x1
+ (len
*n
) / range
;
2826 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2829 // always draw the line at the end position
2830 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2833 // ----------------------------------------------------------------------------
2835 // ----------------------------------------------------------------------------
2837 // wxMetalMenuGeometryInfo: the wxMenuGeometryInfo used by wxMetalRenderer
2838 class WXDLLEXPORT wxMetalMenuGeometryInfo
: public wxMenuGeometryInfo
2841 virtual wxSize
GetSize() const { return m_size
; }
2843 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2844 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2846 wxCoord
GetItemHeight() const { return m_heightItem
; }
2849 // the total size of the menu
2852 // the offset of the start of the menu item label
2855 // the offset of the start of the accel label
2858 // the height of a normal (not separator) item
2859 wxCoord m_heightItem
;
2861 friend wxMenuGeometryInfo
*
2862 wxMetalRenderer::GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2865 // FIXME: all constants are hardcoded but shouldn't be
2866 static const wxCoord MENU_LEFT_MARGIN
= 9;
2867 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2868 static const wxCoord MENU_VERT_MARGIN
= 3;
2870 // the margin around bitmap/check marks (on each side)
2871 static const wxCoord MENU_BMP_MARGIN
= 2;
2873 // the margin between the labels and accel strings
2874 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2876 // the separator height in pixels: in fact, strangely enough, the real height
2877 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2879 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2881 // the size of the standard checkmark bitmap
2882 static const wxCoord MENU_CHECK_SIZE
= 9;
2884 void wxMetalRenderer::DrawMenuBarItem(wxDC
& dc
,
2885 const wxRect
& rectOrig
,
2886 const wxString
& label
,
2890 wxRect rect
= rectOrig
;
2893 wxDCTextColourChanger
colChanger(dc
);
2895 if ( flags
& wxCONTROL_SELECTED
)
2897 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2899 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2900 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2901 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2902 dc
.DrawRectangle(rect
);
2905 // don't draw the focus rect around menu bar items
2906 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2907 wxALIGN_CENTRE
, indexAccel
);
2910 void wxMetalRenderer::DrawMenuItem(wxDC
& dc
,
2912 const wxMenuGeometryInfo
& gi
,
2913 const wxString
& label
,
2914 const wxString
& accel
,
2915 const wxBitmap
& bitmap
,
2919 const wxMetalMenuGeometryInfo
& geometryInfo
=
2920 (const wxMetalMenuGeometryInfo
&)gi
;
2925 rect
.width
= geometryInfo
.GetSize().x
;
2926 rect
.height
= geometryInfo
.GetItemHeight();
2928 // draw the selected item specially
2929 wxDCTextColourChanger
colChanger(dc
);
2930 if ( flags
& wxCONTROL_SELECTED
)
2932 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2934 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2935 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2936 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2937 dc
.DrawRectangle(rect
);
2940 // draw the bitmap: use the bitmap provided or the standard checkmark for
2941 // the checkable items
2942 wxBitmap bmp
= bitmap
;
2943 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2945 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2950 rect
.SetRight(geometryInfo
.GetLabelOffset());
2951 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2955 rect
.x
= geometryInfo
.GetLabelOffset();
2956 rect
.SetRight(geometryInfo
.GetAccelOffset());
2958 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2960 // draw the accel string
2961 rect
.x
= geometryInfo
.GetAccelOffset();
2962 rect
.SetRight(geometryInfo
.GetSize().x
);
2964 // NB: no accel index here
2965 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2967 // draw the submenu indicator
2968 if ( flags
& wxCONTROL_ISSUBMENU
)
2970 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2971 rect
.width
= MENU_RIGHT_MARGIN
;
2973 wxArrowStyle arrowStyle
;
2974 if ( flags
& wxCONTROL_DISABLED
)
2975 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2977 else if ( flags
& wxCONTROL_SELECTED
)
2978 arrowStyle
= Arrow_Inversed
;
2980 arrowStyle
= Arrow_Normal
;
2982 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2986 void wxMetalRenderer::DrawMenuSeparator(wxDC
& dc
,
2988 const wxMenuGeometryInfo
& geomInfo
)
2990 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2993 wxSize
wxMetalRenderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2995 wxSize size
= sizeText
;
2997 // FIXME: menubar height is configurable under Windows
3004 wxMenuGeometryInfo
*wxMetalRenderer::GetMenuGeometry(wxWindow
*win
,
3005 const wxMenu
& menu
) const
3007 // prepare the dc: for now we draw all the items with the system font
3009 dc
.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
3011 // the height of a normal item
3012 wxCoord heightText
= dc
.GetCharHeight();
3017 // the max length of label and accel strings: the menu width is the sum of
3018 // them, even if they're for different items (as the accels should be
3021 // the max length of the bitmap is never 0 as Windows always leaves enough
3022 // space for a check mark indicator
3023 wxCoord widthLabelMax
= 0,
3025 widthBmpMax
= MENU_LEFT_MARGIN
;
3027 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
3029 node
= node
->GetNext() )
3031 // height of this item
3034 wxMenuItem
*item
= node
->GetData();
3035 if ( item
->IsSeparator() )
3037 h
= MENU_SEPARATOR_HEIGHT
;
3039 else // not separator
3044 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
3045 if ( widthLabel
> widthLabelMax
)
3047 widthLabelMax
= widthLabel
;
3051 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
3052 if ( widthAccel
> widthAccelMax
)
3054 widthAccelMax
= widthAccel
;
3057 const wxBitmap
& bmp
= item
->GetBitmap();
3060 wxCoord widthBmp
= bmp
.GetWidth();
3061 if ( widthBmp
> widthBmpMax
)
3062 widthBmpMax
= widthBmp
;
3064 //else if ( item->IsCheckable() ): no need to check for this as
3065 // MENU_LEFT_MARGIN is big enough to show the check mark
3068 h
+= 2*MENU_VERT_MARGIN
;
3070 // remember the item position and height
3071 item
->SetGeometry(height
, h
);
3076 // bundle the metrics into a struct and return it
3077 wxMetalMenuGeometryInfo
*gi
= new wxMetalMenuGeometryInfo
;
3079 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
3080 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
3081 if ( widthAccelMax
> 0 )
3083 // if we actually have any accesl, add a margin
3084 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
3087 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
3089 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
3090 gi
->m_size
.y
= height
;
3095 // ----------------------------------------------------------------------------
3097 // ----------------------------------------------------------------------------
3099 static const wxCoord STATBAR_BORDER_X
= 2;
3100 static const wxCoord STATBAR_BORDER_Y
= 2;
3102 wxSize
wxMetalRenderer::GetStatusBarBorders(wxCoord
*borderBetweenFields
) const
3104 if ( borderBetweenFields
)
3105 *borderBetweenFields
= 2;
3107 return wxSize(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3110 void wxMetalRenderer::DrawStatusField(wxDC
& dc
,
3112 const wxString
& label
,
3117 if ( flags
& wxCONTROL_ISDEFAULT
)
3119 // draw the size grip: it is a normal rect except that in the lower
3120 // right corner we have several bands which may be used for dragging
3121 // the status bar corner
3123 // each band consists of 4 stripes: m_penHighlight, double
3124 // m_penDarkGrey and transparent one
3125 wxCoord x2
= rect
.GetRight(),
3126 y2
= rect
.GetBottom();
3128 // draw the upper left part of the rect normally
3129 dc
.SetPen(m_penDarkGrey
);
3130 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(), rect
.GetLeft(), y2
);
3131 dc
.DrawLine(rect
.GetLeft() + 1, rect
.GetTop(), x2
, rect
.GetTop());
3133 // draw the grey stripes of the grip
3135 wxCoord ofs
= WIDTH_STATUSBAR_GRIP_BAND
- 1;
3136 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3138 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3139 dc
.DrawLine(x2
- ofs
, y2
- 1, x2
, y2
- ofs
- 1);
3142 // draw the white stripes
3143 dc
.SetPen(m_penHighlight
);
3144 ofs
= WIDTH_STATUSBAR_GRIP_BAND
+ 1;
3145 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3147 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3150 // draw the remaining rect boundaries
3151 ofs
-= WIDTH_STATUSBAR_GRIP_BAND
;
3152 dc
.DrawLine(x2
, rect
.GetTop(), x2
, y2
- ofs
+ 1);
3153 dc
.DrawLine(rect
.GetLeft(), y2
, x2
- ofs
+ 1, y2
);
3158 rectIn
.width
-= STATUSBAR_GRIP_SIZE
;
3162 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
3165 rectIn
.Deflate(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3167 wxDCClipper
clipper(dc
, rectIn
);
3168 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3171 // ----------------------------------------------------------------------------
3173 // ----------------------------------------------------------------------------
3175 void wxMetalRenderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
3177 wxBitmap
*bmpPressed
,
3178 wxBitmap
*bmpDisabled
)
3180 static const wxCoord widthCombo
= 16;
3181 static const wxCoord heightCombo
= 17;
3187 bmpNormal
->Create(widthCombo
, heightCombo
);
3188 dcMem
.SelectObject(*bmpNormal
);
3189 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3190 Arrow_Down
, Arrow_Normal
);
3195 bmpPressed
->Create(widthCombo
, heightCombo
);
3196 dcMem
.SelectObject(*bmpPressed
);
3197 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3198 Arrow_Down
, Arrow_Pressed
);
3203 bmpDisabled
->Create(widthCombo
, heightCombo
);
3204 dcMem
.SelectObject(*bmpDisabled
);
3205 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3206 Arrow_Down
, Arrow_Disabled
);
3210 // ----------------------------------------------------------------------------
3212 // ----------------------------------------------------------------------------
3214 void wxMetalRenderer::DrawMetal(wxDC
&dc
, const wxRect
&rect
)
3216 dc
.SetPen(*wxTRANSPARENT_PEN
);
3217 for (int y
= rect
.y
; y
< rect
.height
+rect
.y
; y
++)
3219 int intens
= 230 + 80 * (rect
.y
-y
) / rect
.height
;
3220 dc
.SetBrush( wxBrush( wxColour(intens
,intens
,intens
), wxSOLID
) );
3221 dc
.DrawRectangle( rect
.x
, y
, rect
.width
, 1 );
3225 // ----------------------------------------------------------------------------
3227 // ----------------------------------------------------------------------------
3229 void wxMetalRenderer::DrawButtonSurface(wxDC
& dc
,
3230 const wxColour
& col
,
3234 DrawMetal( dc
, rect
);
3237 void wxMetalRenderer::DoDrawBackground(wxDC
& dc
,
3238 const wxColour
& col
,
3242 dc
.SetPen(*wxTRANSPARENT_PEN
);
3243 wxBrush
brush(col
, wxSOLID
);
3245 dc
.DrawRectangle(rect
);
3248 void wxMetalRenderer::DrawBackground(wxDC
& dc
,
3249 const wxColour
& col
,
3254 // just fill it with the given or default bg colour
3255 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
3256 DoDrawBackground(dc
, colBg
, rect
, window
);
3259 // ----------------------------------------------------------------------------
3261 // ----------------------------------------------------------------------------
3263 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
3268 // get the bitmap for this arrow
3269 wxArrowDirection arrowDir
;
3272 case wxLEFT
: arrowDir
= Arrow_Left
; break;
3273 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
3274 case wxUP
: arrowDir
= Arrow_Up
; break;
3275 case wxDOWN
: arrowDir
= Arrow_Down
; break;
3278 wxFAIL_MSG(_T("unknown arrow direction"));
3282 wxArrowStyle arrowStyle
;
3283 if ( flags
& wxCONTROL_PRESSED
)
3285 // can't be pressed and disabled
3286 arrowStyle
= Arrow_Pressed
;
3290 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
3293 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
3296 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
3298 wxArrowDirection arrowDir
,
3299 wxArrowStyle arrowStyle
)
3301 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
3303 // under Windows the arrows always have the same size so just centre it in
3304 // the provided rectangle
3305 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
3306 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
3308 // Windows does it like this...
3309 if ( arrowDir
== Arrow_Left
)
3313 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
3316 void wxMetalRenderer::DrawArrowButton(wxDC
& dc
,
3317 const wxRect
& rectAll
,
3318 wxArrowDirection arrowDir
,
3319 wxArrowStyle arrowStyle
)
3321 wxRect rect
= rectAll
;
3322 DrawMetal( dc
, rect
);
3323 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
3324 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
3327 void wxMetalRenderer::DrawScrollbarThumb(wxDC
& dc
,
3328 wxOrientation orient
,
3332 // we don't use the flags, the thumb never changes appearance
3333 wxRect rectThumb
= rect
;
3334 DrawArrowBorder(dc
, &rectThumb
);
3335 DrawMetal( dc
, rectThumb
);
3338 void wxMetalRenderer::DrawScrollbarShaft(wxDC
& dc
,
3339 wxOrientation orient
,
3340 const wxRect
& rectBar
,
3343 DrawMetal( dc
, rectBar
);
3346 void wxMetalRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
3348 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3351 wxRect
wxMetalRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
3352 wxScrollBar::Element elem
,
3355 return StandardGetScrollbarRect(scrollbar
, elem
,
3356 thumbPos
, m_sizeScrollbarArrow
);
3359 wxCoord
wxMetalRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
3361 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
3364 wxHitTest
wxMetalRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
3365 const wxPoint
& pt
) const
3367 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
3370 wxCoord
wxMetalRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
3373 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
3376 int wxMetalRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
3379 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
3382 // ----------------------------------------------------------------------------
3383 // top level windows
3384 // ----------------------------------------------------------------------------
3386 int wxMetalRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
3388 wxRect client
= GetFrameClientArea(rect
, flags
);
3390 if ( client
.Inside(pt
) )
3391 return wxHT_TOPLEVEL_CLIENT_AREA
;
3393 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3395 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3397 if ( flags
& wxTOPLEVEL_ICON
)
3399 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Inside(pt
) )
3400 return wxHT_TOPLEVEL_ICON
;
3403 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
3404 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
3405 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3407 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3409 if ( btnRect
.Inside(pt
) )
3410 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
3411 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
3413 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3415 if ( btnRect
.Inside(pt
) )
3416 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
3417 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3419 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3421 if ( btnRect
.Inside(pt
) )
3422 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
3423 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3425 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3427 if ( btnRect
.Inside(pt
) )
3428 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
3429 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3431 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3433 if ( btnRect
.Inside(pt
) )
3434 return wxHT_TOPLEVEL_BUTTON_HELP
;
3435 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3438 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
3439 return wxHT_TOPLEVEL_TITLEBAR
;
3442 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3444 // we are certainly at one of borders, lets decide which one:
3447 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3448 if ( pt
.x
< client
.x
)
3449 border
|= wxHT_TOPLEVEL_BORDER_W
;
3450 else if ( pt
.x
>= client
.width
+ client
.x
)
3451 border
|= wxHT_TOPLEVEL_BORDER_E
;
3452 if ( pt
.y
< client
.y
)
3453 border
|= wxHT_TOPLEVEL_BORDER_N
;
3454 else if ( pt
.y
>= client
.height
+ client
.y
)
3455 border
|= wxHT_TOPLEVEL_BORDER_S
;
3459 return wxHT_NOWHERE
;
3462 void wxMetalRenderer::DrawFrameTitleBar(wxDC
& dc
,
3464 const wxString
& title
,
3468 int specialButtonFlags
)
3470 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3472 DrawFrameBorder(dc
, rect
, flags
);
3474 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3476 DrawFrameBackground(dc
, rect
, flags
);
3477 if ( flags
& wxTOPLEVEL_ICON
)
3478 DrawFrameIcon(dc
, rect
, icon
, flags
);
3479 DrawFrameTitle(dc
, rect
, title
, flags
);
3481 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3483 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
3484 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
3486 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3488 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
3489 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
3490 specialButtonFlags
: 0);
3491 x
-= FRAME_BUTTON_WIDTH
+ 2;
3493 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3495 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
3496 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
3497 specialButtonFlags
: 0);
3498 x
-= FRAME_BUTTON_WIDTH
;
3500 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3502 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
3503 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
3504 specialButtonFlags
: 0);
3505 x
-= FRAME_BUTTON_WIDTH
;
3507 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3509 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
3510 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
3511 specialButtonFlags
: 0);
3512 x
-= FRAME_BUTTON_WIDTH
;
3514 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3516 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
3517 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
3518 specialButtonFlags
: 0);
3519 x
-= FRAME_BUTTON_WIDTH
;
3524 void wxMetalRenderer::DrawFrameBorder(wxDC
& dc
,
3528 if ( !(flags
& wxTOPLEVEL_BORDER
) ) return;
3532 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penBlack
);
3533 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penDarkGrey
);
3534 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3535 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
3536 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3539 void wxMetalRenderer::DrawFrameBackground(wxDC
& dc
,
3543 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) ) return;
3545 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3546 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE
) :
3547 wxSCHEME_COLOUR(m_scheme
, TITLEBAR
);
3549 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3550 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3552 DrawBackground(dc
, col
, r
);
3555 void wxMetalRenderer::DrawFrameTitle(wxDC
& dc
,
3557 const wxString
& title
,
3560 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3561 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE_TEXT
) :
3562 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_TEXT
);
3564 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3565 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3566 if ( flags
& wxTOPLEVEL_ICON
)
3568 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
3569 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
3577 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3578 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
3579 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3580 r
.width
-= FRAME_BUTTON_WIDTH
;
3581 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3582 r
.width
-= FRAME_BUTTON_WIDTH
;
3583 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3584 r
.width
-= FRAME_BUTTON_WIDTH
;
3585 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3586 r
.width
-= FRAME_BUTTON_WIDTH
;
3588 dc
.SetFont(m_titlebarFont
);
3589 dc
.SetTextForeground(col
);
3592 dc
.GetTextExtent(title
, &textW
, NULL
);
3593 if ( textW
> r
.width
)
3595 // text is too big, let's shorten it and add "..." after it:
3596 size_t len
= title
.length();
3597 wxCoord WSoFar
, letterW
;
3599 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
3600 if ( WSoFar
> r
.width
)
3602 // not enough space to draw anything
3608 for (size_t i
= 0; i
< len
; i
++)
3610 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
3611 if ( letterW
+ WSoFar
> r
.width
)
3617 dc
.DrawLabel(s
, wxNullBitmap
, r
,
3618 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3621 dc
.DrawLabel(title
, wxNullBitmap
, r
,
3622 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3625 void wxMetalRenderer::DrawFrameIcon(wxDC
& dc
,
3632 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3633 dc
.DrawIcon(icon
, r
.x
, r
.y
);
3637 void wxMetalRenderer::DrawFrameButton(wxDC
& dc
,
3638 wxCoord x
, wxCoord y
,
3642 wxRect
r(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3647 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
3648 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
3649 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
3650 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
3651 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
3653 wxFAIL_MSG(wxT("incorrect button specification"));
3656 if ( flags
& wxCONTROL_PRESSED
)
3658 DrawShadedRect(dc
, &r
, m_penBlack
, m_penHighlight
);
3659 DrawShadedRect(dc
, &r
, m_penDarkGrey
, m_penLightGrey
);
3660 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3661 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
+1, r
.y
+1, TRUE
);
3665 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penBlack
);
3666 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penDarkGrey
);
3667 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3668 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
, r
.y
, TRUE
);
3673 wxRect
wxMetalRenderer::GetFrameClientArea(const wxRect
& rect
,
3678 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3680 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3681 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3682 FRAME_BORDER_THICKNESS
;
3685 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3687 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
3688 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
3694 wxSize
wxMetalRenderer::GetFrameTotalSize(const wxSize
& clientSize
,
3697 wxSize
s(clientSize
);
3699 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3701 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3702 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3703 FRAME_BORDER_THICKNESS
;
3707 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3708 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3713 wxSize
wxMetalRenderer::GetFrameMinSize(int flags
) const
3717 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3719 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3720 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3721 FRAME_BORDER_THICKNESS
;
3726 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3728 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3730 if ( flags
& wxTOPLEVEL_ICON
)
3731 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
3732 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3733 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
3734 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3735 s
.x
+= FRAME_BUTTON_WIDTH
;
3736 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3737 s
.x
+= FRAME_BUTTON_WIDTH
;
3738 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3739 s
.x
+= FRAME_BUTTON_WIDTH
;
3740 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3741 s
.x
+= FRAME_BUTTON_WIDTH
;
3747 wxSize
wxMetalRenderer::GetFrameIconSize() const
3749 return wxSize(16, 16);
3753 // ----------------------------------------------------------------------------
3755 // ----------------------------------------------------------------------------
3757 static char *error_xpm
[]={
3764 "...........########.............",
3765 "........###aaaaaaaa###..........",
3766 ".......#aaaaaaaaaaaaaa#.........",
3767 ".....##aaaaaaaaaaaaaaaa##.......",
3768 "....#aaaaaaaaaaaaaaaaaaaa#......",
3769 "...#aaaaaaaaaaaaaaaaaaaaaa#.....",
3770 "...#aaaaaaaaaaaaaaaaaaaaaa#b....",
3771 "..#aaaaaacaaaaaaaaaacaaaaaa#b...",
3772 ".#aaaaaacccaaaaaaaacccaaaaaa#...",
3773 ".#aaaaacccccaaaaaacccccaaaaa#b..",
3774 ".#aaaaaacccccaaaacccccaaaaaa#bb.",
3775 "#aaaaaaaacccccaacccccaaaaaaaa#b.",
3776 "#aaaaaaaaaccccccccccaaaaaaaaa#b.",
3777 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3778 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3779 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3780 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3781 "#aaaaaaaaaccccccccccaaaaaaaaa#bb",
3782 "#aaaaaaaacccccaacccccaaaaaaaa#bb",
3783 ".#aaaaaacccccaaaacccccaaaaaa#bbb",
3784 ".#aaaaacccccaaaaaacccccaaaaa#bbb",
3785 ".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
3786 "..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
3787 "...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
3788 "...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
3789 "....#aaaaaaaaaaaaaaaaaaaa#bbb...",
3790 ".....##aaaaaaaaaaaaaaaa##bbbb...",
3791 "......b#aaaaaaaaaaaaaa#bbbbb....",
3792 ".......b###aaaaaaaa###bbbbb.....",
3793 ".........bb########bbbbbb.......",
3794 "..........bbbbbbbbbbbbbb........",
3795 ".............bbbbbbbb..........."};
3797 static char *info_xpm
[]={
3805 "...........########.............",
3806 "........###abbbbbba###..........",
3807 "......##abbbbbbbbbbbba##........",
3808 ".....#abbbbbbbbbbbbbbbba#.......",
3809 "....#bbbbbbbaccccabbbbbbbd......",
3810 "...#bbbbbbbbccccccbbbbbbbbd.....",
3811 "..#bbbbbbbbbccccccbbbbbbbbbd....",
3812 ".#abbbbbbbbbaccccabbbbbbbbbad...",
3813 ".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
3814 "#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
3815 "#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
3816 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3817 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3818 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3819 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3820 "#abbbbbbbbbbbcccccbbbbbbbbbbad##",
3821 ".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
3822 ".#abbbbbbbbbbcccccbbbbbbbbbad###",
3823 "..#bbbbbbbbcccccccccbbbbbbbd###.",
3824 "...dbbbbbbbbbbbbbbbbbbbbbbd####.",
3825 "....dbbbbbbbbbbbbbbbbbbbbd####..",
3826 ".....dabbbbbbbbbbbbbbbbad####...",
3827 "......ddabbbbbbbbbbbbadd####....",
3828 ".......#dddabbbbbbaddd#####.....",
3829 "........###dddabbbd#######......",
3830 "..........####dbbbd#####........",
3831 ".............#dbbbd##...........",
3832 "...............dbbd##...........",
3833 "................dbd##...........",
3834 ".................dd##...........",
3835 "..................###...........",
3836 "...................##..........."};
3838 static char *question_xpm
[]={
3846 "...........########.............",
3847 "........###abbbbbba###..........",
3848 "......##abbbbbbbbbbbba##........",
3849 ".....#abbbbbbbbbbbbbbbba#.......",
3850 "....#bbbbbbbbbbbbbbbbbbbbc......",
3851 "...#bbbbbbbaddddddabbbbbbbc.....",
3852 "..#bbbbbbbadabbddddabbbbbbbc....",
3853 ".#abbbbbbbddbbbbddddbbbbbbbac...",
3854 ".#bbbbbbbbddddbbddddbbbbbbbbc#..",
3855 "#abbbbbbbbddddbaddddbbbbbbbbac#.",
3856 "#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
3857 "#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
3858 "#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
3859 "#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
3860 "#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
3861 "#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
3862 ".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
3863 ".#abbbbbbbbbbddddbbbbbbbbbbac###",
3864 "..#bbbbbbbbbbddddbbbbbbbbbbc###.",
3865 "...cbbbbbbbbbaddabbbbbbbbbc####.",
3866 "....cbbbbbbbbbbbbbbbbbbbbc####..",
3867 ".....cabbbbbbbbbbbbbbbbac####...",
3868 "......ccabbbbbbbbbbbbacc####....",
3869 ".......#cccabbbbbbaccc#####.....",
3870 "........###cccabbbc#######......",
3871 "..........####cbbbc#####........",
3872 ".............#cbbbc##...........",
3873 "...............cbbc##...........",
3874 "................cbc##...........",
3875 ".................cc##...........",
3876 "..................###...........",
3877 "...................##..........."};
3879 static char *warning_xpm
[]={
3887 ".............###................",
3888 "............#aabc...............",
3889 "...........#aaaabcd.............",
3890 "...........#aaaaacdd............",
3891 "..........#aaaaaabcdd...........",
3892 "..........#aaaaaaacdd...........",
3893 ".........#aaaaaaaabcdd..........",
3894 ".........#aaaaaaaaacdd..........",
3895 "........#aaaaaaaaaabcdd.........",
3896 "........#aaabcccbaaacdd.........",
3897 ".......#aaaacccccaaabcdd........",
3898 ".......#aaaacccccaaaacdd........",
3899 "......#aaaaacccccaaaabcdd.......",
3900 "......#aaaaacccccaaaaacdd.......",
3901 ".....#aaaaaacccccaaaaabcdd......",
3902 ".....#aaaaaa#ccc#aaaaaacdd......",
3903 "....#aaaaaaabcccbaaaaaabcdd.....",
3904 "....#aaaaaaaacccaaaaaaaacdd.....",
3905 "...#aaaaaaaaa#c#aaaaaaaabcdd....",
3906 "...#aaaaaaaaabcbaaaaaaaaacdd....",
3907 "..#aaaaaaaaaaacaaaaaaaaaabcdd...",
3908 "..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
3909 ".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
3910 ".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
3911 "#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
3912 "#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
3913 "#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
3914 "#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
3915 ".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
3916 "..#ccccccccccccccccccccccccddddd",
3917 "....ddddddddddddddddddddddddddd.",
3918 ".....ddddddddddddddddddddddddd.."};
3920 wxBitmap
wxMetalArtProvider::CreateBitmap(const wxArtID
& id
,
3921 const wxArtClient
& WXUNUSED(client
),
3922 const wxSize
& WXUNUSED(size
))
3924 if ( id
== wxART_INFORMATION
)
3925 return wxBitmap(info_xpm
);
3926 if ( id
== wxART_ERROR
)
3927 return wxBitmap(error_xpm
);
3928 if ( id
== wxART_WARNING
)
3929 return wxBitmap(warning_xpm
);
3930 if ( id
== wxART_QUESTION
)
3931 return wxBitmap(question_xpm
);
3932 return wxNullBitmap
;
3936 // ----------------------------------------------------------------------------
3937 // text control geometry
3938 // ----------------------------------------------------------------------------
3940 static inline int GetTextBorderWidth()
3945 wxRect
wxMetalRenderer::GetTextTotalArea(const wxTextCtrl
*text
,
3946 const wxRect
& rect
) const
3948 wxRect rectTotal
= rect
;
3950 wxCoord widthBorder
= GetTextBorderWidth();
3951 rectTotal
.Inflate(widthBorder
);
3953 // this is what Windows does
3959 wxRect
wxMetalRenderer::GetTextClientArea(const wxTextCtrl
*text
,
3961 wxCoord
*extraSpaceBeyond
) const
3963 wxRect rectText
= rect
;
3965 // undo GetTextTotalArea()
3966 if ( rectText
.height
> 0 )
3969 wxCoord widthBorder
= GetTextBorderWidth();
3970 rectText
.Inflate(-widthBorder
);
3972 if ( extraSpaceBeyond
)
3973 *extraSpaceBeyond
= 0;
3978 // ----------------------------------------------------------------------------
3980 // ----------------------------------------------------------------------------
3982 void wxMetalRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
3985 if ( wxDynamicCast(window
, wxScrollBar
) )
3987 // we only set the width of vert scrollbars and height of the
3989 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3990 size
->y
= m_sizeScrollbarArrow
.y
;
3992 size
->x
= m_sizeScrollbarArrow
.x
;
3994 // skip border width adjustments, they don't make sense for us
3997 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
4000 if ( wxDynamicCast(window
, wxButton
) )
4002 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
4004 // TODO: don't harcode all this
4005 size
->x
+= 3*window
->GetCharWidth();
4007 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
4008 if ( size
->y
< heightBtn
- 8 )
4009 size
->y
= heightBtn
;
4014 // no border width adjustments for buttons
4017 #endif // wxUSE_BUTTON
4019 // take into account the border width
4020 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
4021 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
4022 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
4025 // ============================================================================
4027 // ============================================================================
4029 // ----------------------------------------------------------------------------
4030 // wxMetalInputHandler
4031 // ----------------------------------------------------------------------------
4033 wxMetalInputHandler::wxMetalInputHandler(wxMetalRenderer
*renderer
)
4035 m_renderer
= renderer
;
4038 bool wxMetalInputHandler::HandleKey(wxInputConsumer
*control
,
4039 const wxKeyEvent
& event
,
4045 bool wxMetalInputHandler::HandleMouse(wxInputConsumer
*control
,
4046 const wxMouseEvent
& event
)
4048 // clicking on the control gives it focus
4049 if ( event
.ButtonDown() )
4051 wxWindow
*win
= control
->GetInputWindow();
4053 if (( wxWindow::FindFocus() != control
->GetInputWindow() ) &&
4054 ( win
->AcceptsFocus() ) )
4065 // ----------------------------------------------------------------------------
4066 // wxMetalScrollBarInputHandler
4067 // ----------------------------------------------------------------------------
4069 wxMetalScrollBarInputHandler::
4070 wxMetalScrollBarInputHandler(wxMetalRenderer
*renderer
,
4071 wxInputHandler
*handler
)
4072 : wxStdScrollBarInputHandler(renderer
, handler
)
4074 m_scrollPaused
= FALSE
;
4078 bool wxMetalScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
4079 const wxControlAction
& action
)
4081 // stop if went beyond the position of the original click (this can only
4082 // happen when we scroll by pages)
4084 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
4086 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4087 != wxHT_SCROLLBAR_BAR_2
;
4089 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
4091 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4092 != wxHT_SCROLLBAR_BAR_1
;
4097 StopScrolling(scrollbar
);
4099 scrollbar
->Refresh();
4104 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
4107 bool wxMetalScrollBarInputHandler::HandleMouse(wxInputConsumer
*control
,
4108 const wxMouseEvent
& event
)
4110 // remember the current state
4111 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
4113 // do process the message
4114 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
4116 // analyse the changes
4117 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
4119 // we just started dragging the thumb, remember its initial position to
4120 // be able to restore it if the drag is cancelled later
4121 m_eventStartDrag
= event
;
4127 bool wxMetalScrollBarInputHandler::HandleMouseMove(wxInputConsumer
*control
,
4128 const wxMouseEvent
& event
)
4130 // we don't highlight scrollbar elements, so there is no need to process
4131 // mouse move events normally - only do it while mouse is captured (i.e.
4132 // when we're dragging the thumb or pressing on something)
4133 if ( !m_winCapture
)
4136 if ( event
.Entering() )
4138 // we're not interested in this at all
4142 wxScrollBar
*scrollbar
= wxStaticCast(control
->GetInputWindow(), wxScrollBar
);
4144 if ( m_scrollPaused
)
4146 // check if the mouse returned to its original location
4148 if ( event
.Leaving() )
4154 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4155 if ( ht
== m_htLast
)
4157 // yes it did, resume scrolling
4158 m_scrollPaused
= FALSE
;
4159 if ( m_timerScroll
)
4161 // we were scrolling by line/page, restart timer
4162 m_timerScroll
->Start(m_interval
);
4164 Press(scrollbar
, TRUE
);
4166 else // we were dragging the thumb
4168 // restore its last location
4169 HandleThumbMove(scrollbar
, m_eventLastDrag
);
4175 else // normal case, scrolling hasn't been paused
4177 // if we're scrolling the scrollbar because the arrow or the shaft was
4178 // pressed, check that the mouse stays on the same scrollbar element
4181 // Always let thumb jump back if we leave the scrollbar
4182 if ( event
.Moving() )
4184 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4186 else // event.Leaving()
4191 // Jump back only if we get far away from it
4192 wxPoint pos
= event
.GetPosition();
4193 if (scrollbar
->HasFlag( wxVERTICAL
))
4195 if (pos
.x
> -40 && pos
.x
< scrollbar
->GetSize().x
+40)
4200 if (pos
.y
> -40 && pos
.y
< scrollbar
->GetSize().y
+40)
4203 ht
= m_renderer
->HitTestScrollbar(scrollbar
, pos
);
4206 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4207 // is still ok - we only want to catch the case when the mouse leaves
4208 // the scrollbar here
4209 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
4211 ht
= wxHT_SCROLLBAR_THUMB
;
4214 if ( ht
!= m_htLast
)
4216 // what were we doing? 2 possibilities: either an arrow/shaft was
4217 // pressed in which case we have a timer and so we just stop it or
4218 // we were dragging the thumb
4219 if ( m_timerScroll
)
4222 m_interval
= m_timerScroll
->GetInterval();
4223 m_timerScroll
->Stop();
4224 m_scrollPaused
= TRUE
;
4226 // unpress the arrow
4227 Press(scrollbar
, FALSE
);
4229 else // we were dragging the thumb
4231 // remember the current thumb position to be able to restore it
4232 // if the mouse returns to it later
4233 m_eventLastDrag
= event
;
4235 // and restore the original position (before dragging) of the
4237 HandleThumbMove(scrollbar
, m_eventStartDrag
);
4244 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
4247 // ----------------------------------------------------------------------------
4248 // wxMetalCheckboxInputHandler
4249 // ----------------------------------------------------------------------------
4251 bool wxMetalCheckboxInputHandler::HandleKey(wxInputConsumer
*control
,
4252 const wxKeyEvent
& event
,
4257 wxControlAction action
;
4258 int keycode
= event
.GetKeyCode();
4262 action
= wxACTION_CHECKBOX_TOGGLE
;
4266 case WXK_NUMPAD_SUBTRACT
:
4267 action
= wxACTION_CHECKBOX_CHECK
;
4271 case WXK_NUMPAD_ADD
:
4272 case WXK_NUMPAD_EQUAL
:
4273 action
= wxACTION_CHECKBOX_CLEAR
;
4279 control
->PerformAction(action
);
4288 // ----------------------------------------------------------------------------
4289 // wxMetalTextCtrlInputHandler
4290 // ----------------------------------------------------------------------------
4292 bool wxMetalTextCtrlInputHandler::HandleKey(wxInputConsumer
*control
,
4293 const wxKeyEvent
& event
,
4296 // handle only MSW-specific text bindings here, the others are handled in
4300 int keycode
= event
.GetKeyCode();
4302 wxControlAction action
;
4303 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
4305 action
= wxACTION_TEXT_CUT
;
4307 else if ( keycode
== WXK_INSERT
)
4309 if ( event
.ControlDown() )
4310 action
= wxACTION_TEXT_COPY
;
4311 else if ( event
.ShiftDown() )
4312 action
= wxACTION_TEXT_PASTE
;
4315 if ( action
!= wxACTION_NONE
)
4317 control
->PerformAction(action
);
4323 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);
4326 // ----------------------------------------------------------------------------
4327 // wxMetalStatusBarInputHandler
4328 // ----------------------------------------------------------------------------
4330 wxMetalStatusBarInputHandler::
4331 wxMetalStatusBarInputHandler(wxInputHandler
*handler
)
4332 : wxStdInputHandler(handler
)
4337 bool wxMetalStatusBarInputHandler::IsOnGrip(wxWindow
*statbar
,
4338 const wxPoint
& pt
) const
4340 if ( statbar
->HasFlag(wxST_SIZEGRIP
) &&
4341 statbar
->GetParent()->HasFlag(wxRESIZE_BORDER
) )
4344 parentTLW
= wxDynamicCast(statbar
->GetParent(), wxTopLevelWindow
);
4346 wxCHECK_MSG( parentTLW
, FALSE
,
4347 _T("the status bar should be a child of a TLW") );
4349 // a maximized window can't be resized anyhow
4350 if ( !parentTLW
->IsMaximized() )
4352 // VZ: I think that the standard Windows behaviour is to only
4353 // show the resizing cursor when the mouse is on top of the
4354 // grip itself but apparently different Windows versions behave
4355 // differently (?) and it seems a better UI to allow resizing
4356 // the status bar even when the mouse is above the grip
4357 wxSize sizeSbar
= statbar
->GetSize();
4359 int diff
= sizeSbar
.x
- pt
.x
;
4360 return diff
>= 0 && diff
< (wxCoord
)STATUSBAR_GRIP_SIZE
;
4367 bool wxMetalStatusBarInputHandler::HandleMouse(wxInputConsumer
*consumer
,
4368 const wxMouseEvent
& event
)
4370 if ( event
.Button(1) )
4372 if ( event
.ButtonDown(1) )
4374 wxWindow
*statbar
= consumer
->GetInputWindow();
4376 if ( IsOnGrip(statbar
, event
.GetPosition()) )
4378 wxTopLevelWindow
*tlw
= wxDynamicCast(statbar
->GetParent(),
4382 tlw
->PerformAction(wxACTION_TOPLEVEL_RESIZE
,
4383 wxHT_TOPLEVEL_BORDER_SE
);
4385 statbar
->SetCursor(m_cursorOld
);
4393 return wxStdInputHandler::HandleMouse(consumer
, event
);
4396 bool wxMetalStatusBarInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
4397 const wxMouseEvent
& event
)
4399 wxWindow
*statbar
= consumer
->GetInputWindow();
4401 bool isOnGrip
= IsOnGrip(statbar
, event
.GetPosition());
4402 if ( isOnGrip
!= m_isOnGrip
)
4404 m_isOnGrip
= isOnGrip
;
4407 m_cursorOld
= statbar
->GetCursor();
4408 statbar
->SetCursor(wxCURSOR_SIZENWSE
);
4412 statbar
->SetCursor(m_cursorOld
);
4416 return wxStdInputHandler::HandleMouseMove(consumer
, event
);
4419 // ----------------------------------------------------------------------------
4420 // wxMetalFrameInputHandler
4421 // ----------------------------------------------------------------------------
4423 class wxMetalSystemMenuEvtHandler
: public wxEvtHandler
4426 wxMetalSystemMenuEvtHandler(wxMetalFrameInputHandler
*handler
);
4428 void Attach(wxInputConsumer
*consumer
);
4432 DECLARE_EVENT_TABLE()
4433 void OnSystemMenu(wxCommandEvent
&event
);
4434 void OnCloseFrame(wxCommandEvent
&event
);
4435 void OnClose(wxCloseEvent
&event
);
4437 wxMetalFrameInputHandler
*m_inputHnd
;
4438 wxTopLevelWindow
*m_wnd
;
4439 wxAcceleratorTable m_oldAccelTable
;
4442 wxMetalSystemMenuEvtHandler::wxMetalSystemMenuEvtHandler(
4443 wxMetalFrameInputHandler
*handler
)
4445 m_inputHnd
= handler
;
4449 void wxMetalSystemMenuEvtHandler::Attach(wxInputConsumer
*consumer
)
4451 wxASSERT_MSG( m_wnd
== NULL
, _T("can't attach the handler twice!") );
4453 m_wnd
= wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4454 m_wnd
->PushEventHandler(this);
4456 // VS: This code relies on using generic implementation of
4457 // wxAcceleratorTable in wxUniv!
4458 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4459 m_oldAccelTable
= table
;
4460 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_SPACE
, wxID_SYSTEM_MENU
));
4461 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_F4
, wxID_CLOSE_FRAME
));
4462 m_wnd
->SetAcceleratorTable(table
);
4465 void wxMetalSystemMenuEvtHandler::Detach()
4469 m_wnd
->SetAcceleratorTable(m_oldAccelTable
);
4470 m_wnd
->RemoveEventHandler(this);
4475 BEGIN_EVENT_TABLE(wxMetalSystemMenuEvtHandler
, wxEvtHandler
)
4476 EVT_MENU(wxID_SYSTEM_MENU
, wxMetalSystemMenuEvtHandler::OnSystemMenu
)
4477 EVT_MENU(wxID_CLOSE_FRAME
, wxMetalSystemMenuEvtHandler::OnCloseFrame
)
4478 EVT_CLOSE(wxMetalSystemMenuEvtHandler::OnClose
)
4481 void wxMetalSystemMenuEvtHandler::OnSystemMenu(wxCommandEvent
&WXUNUSED(event
))
4483 int border
= ((m_wnd
->GetWindowStyle() & wxRESIZE_BORDER
) &&
4484 !m_wnd
->IsMaximized()) ?
4485 RESIZEABLE_FRAME_BORDER_THICKNESS
:
4486 FRAME_BORDER_THICKNESS
;
4487 wxPoint pt
= m_wnd
->GetClientAreaOrigin();
4488 pt
.x
= -pt
.x
+ border
;
4489 pt
.y
= -pt
.y
+ border
+ FRAME_TITLEBAR_HEIGHT
;
4491 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4492 m_wnd
->SetAcceleratorTable(wxNullAcceleratorTable
);
4493 m_inputHnd
->PopupSystemMenu(m_wnd
, pt
);
4494 m_wnd
->SetAcceleratorTable(table
);
4497 void wxMetalSystemMenuEvtHandler::OnCloseFrame(wxCommandEvent
&WXUNUSED(event
))
4499 m_wnd
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4500 wxTOPLEVEL_BUTTON_CLOSE
);
4503 void wxMetalSystemMenuEvtHandler::OnClose(wxCloseEvent
&event
)
4510 wxMetalFrameInputHandler::wxMetalFrameInputHandler(wxInputHandler
*handler
)
4511 : wxStdFrameInputHandler(handler
)
4513 m_menuHandler
= new wxMetalSystemMenuEvtHandler(this);
4516 wxMetalFrameInputHandler::~wxMetalFrameInputHandler()
4518 if ( m_menuHandler
)
4520 m_menuHandler
->Detach();
4521 delete m_menuHandler
;
4525 bool wxMetalFrameInputHandler::HandleMouse(wxInputConsumer
*consumer
,
4526 const wxMouseEvent
& event
)
4528 if ( event
.LeftDClick() || event
.LeftDown() || event
.RightDown() )
4530 wxTopLevelWindow
*tlw
=
4531 wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4533 long hit
= tlw
->HitTest(event
.GetPosition());
4535 if ( event
.LeftDClick() && hit
== wxHT_TOPLEVEL_TITLEBAR
)
4537 tlw
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4538 tlw
->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4539 : wxTOPLEVEL_BUTTON_MAXIMIZE
);
4542 else if ( tlw
->GetWindowStyle() & wxSYSTEM_MENU
)
4544 if ( (event
.LeftDown() && hit
== wxHT_TOPLEVEL_ICON
) ||
4545 (event
.RightDown() &&
4546 (hit
== wxHT_TOPLEVEL_TITLEBAR
||
4547 hit
== wxHT_TOPLEVEL_ICON
)) )
4549 PopupSystemMenu(tlw
, event
.GetPosition());
4555 return wxStdFrameInputHandler::HandleMouse(consumer
, event
);
4558 void wxMetalFrameInputHandler::PopupSystemMenu(wxTopLevelWindow
*window
,
4559 const wxPoint
& pos
) const
4561 wxMenu
*menu
= new wxMenu
;
4563 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4564 menu
->Append(wxID_RESTORE_FRAME
, _("&Restore"));
4565 menu
->Append(wxID_MOVE_FRAME
, _("&Move"));
4566 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4567 menu
->Append(wxID_RESIZE_FRAME
, _("&Size"));
4568 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME
) )
4569 menu
->Append(wxID_ICONIZE_FRAME
, _("Mi&nimize"));
4570 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4571 menu
->Append(wxID_MAXIMIZE_FRAME
, _("Ma&ximize"));
4572 menu
->AppendSeparator();
4573 menu
->Append(wxID_CLOSE_FRAME
, _("Close\tAlt-F4"));
4575 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4577 if ( window
->IsMaximized() )
4579 menu
->Enable(wxID_MAXIMIZE_FRAME
, FALSE
);
4580 menu
->Enable(wxID_MOVE_FRAME
, FALSE
);
4581 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4582 menu
->Enable(wxID_RESIZE_FRAME
, FALSE
);
4585 menu
->Enable(wxID_RESTORE_FRAME
, FALSE
);
4588 window
->PopupMenu(menu
, pos
);
4592 bool wxMetalFrameInputHandler::HandleActivation(wxInputConsumer
*consumer
,
4595 if ( consumer
->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU
)
4597 // always detach if active frame changed:
4598 m_menuHandler
->Detach();
4602 m_menuHandler
->Attach(consumer
);
4606 return wxStdFrameInputHandler::HandleActivation(consumer
, activated
);