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
);
147 // implement the base class pure virtuals
148 virtual void DrawBackground(wxDC
& dc
,
152 virtual void DrawLabel(wxDC
& dc
,
153 const wxString
& label
,
156 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
158 wxRect
*rectBounds
= NULL
);
159 virtual void DrawButtonLabel(wxDC
& dc
,
160 const wxString
& label
,
161 const wxBitmap
& image
,
164 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
166 wxRect
*rectBounds
= NULL
);
167 virtual void DrawBorder(wxDC
& dc
,
171 wxRect
*rectIn
= (wxRect
*)NULL
);
172 virtual void DrawHorizontalLine(wxDC
& dc
,
173 wxCoord y
, wxCoord x1
, wxCoord x2
);
174 virtual void DrawVerticalLine(wxDC
& dc
,
175 wxCoord x
, wxCoord y1
, wxCoord y2
);
176 virtual void DrawFrame(wxDC
& dc
,
177 const wxString
& label
,
180 int alignment
= wxALIGN_LEFT
,
181 int indexAccel
= -1);
182 virtual void DrawTextBorder(wxDC
& dc
,
186 wxRect
*rectIn
= (wxRect
*)NULL
);
187 virtual void DrawButtonBorder(wxDC
& dc
,
190 wxRect
*rectIn
= (wxRect
*)NULL
);
191 virtual void DrawArrow(wxDC
& dc
,
195 virtual void DrawScrollbarArrow(wxDC
& dc
,
199 { DrawArrow(dc
, dir
, rect
, flags
); }
200 virtual void DrawScrollbarThumb(wxDC
& dc
,
201 wxOrientation orient
,
204 virtual void DrawScrollbarShaft(wxDC
& dc
,
205 wxOrientation orient
,
208 virtual void DrawScrollCorner(wxDC
& dc
,
210 virtual void DrawItem(wxDC
& dc
,
211 const wxString
& label
,
214 virtual void DrawCheckItem(wxDC
& dc
,
215 const wxString
& label
,
216 const wxBitmap
& bitmap
,
219 virtual void DrawCheckButton(wxDC
& dc
,
220 const wxString
& label
,
221 const wxBitmap
& bitmap
,
224 wxAlignment align
= wxALIGN_LEFT
,
225 int indexAccel
= -1);
226 virtual void DrawRadioButton(wxDC
& dc
,
227 const wxString
& label
,
228 const wxBitmap
& bitmap
,
231 wxAlignment align
= wxALIGN_LEFT
,
232 int indexAccel
= -1);
233 virtual void DrawToolBarButton(wxDC
& dc
,
234 const wxString
& label
,
235 const wxBitmap
& bitmap
,
238 virtual void DrawTextLine(wxDC
& dc
,
239 const wxString
& text
,
244 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
245 virtual void DrawTab(wxDC
& dc
,
248 const wxString
& label
,
249 const wxBitmap
& bitmap
= wxNullBitmap
,
251 int indexAccel
= -1);
253 virtual void DrawSliderShaft(wxDC
& dc
,
255 wxOrientation orient
,
257 wxRect
*rectShaft
= NULL
);
258 virtual void DrawSliderThumb(wxDC
& dc
,
260 wxOrientation orient
,
262 virtual void DrawSliderTicks(wxDC
& dc
,
264 const wxSize
& sizeThumb
,
265 wxOrientation orient
,
271 virtual void DrawMenuBarItem(wxDC
& dc
,
273 const wxString
& label
,
275 int indexAccel
= -1);
276 virtual void DrawMenuItem(wxDC
& dc
,
278 const wxMenuGeometryInfo
& geometryInfo
,
279 const wxString
& label
,
280 const wxString
& accel
,
281 const wxBitmap
& bitmap
= wxNullBitmap
,
283 int indexAccel
= -1);
284 virtual void DrawMenuSeparator(wxDC
& dc
,
286 const wxMenuGeometryInfo
& geomInfo
);
288 virtual void DrawStatusField(wxDC
& dc
,
290 const wxString
& label
,
294 virtual void DrawFrameTitleBar(wxDC
& dc
,
296 const wxString
& title
,
299 int specialButton
= 0,
300 int specialButtonFlags
= 0);
301 virtual void DrawFrameBorder(wxDC
& dc
,
304 virtual void DrawFrameBackground(wxDC
& dc
,
307 virtual void DrawFrameTitle(wxDC
& dc
,
309 const wxString
& title
,
311 virtual void DrawFrameIcon(wxDC
& dc
,
315 virtual void DrawFrameButton(wxDC
& dc
,
316 wxCoord x
, wxCoord y
,
319 virtual wxRect
GetFrameClientArea(const wxRect
& rect
, int flags
) const;
320 virtual wxSize
GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const;
321 virtual wxSize
GetFrameMinSize(int flags
) const;
322 virtual wxSize
GetFrameIconSize() const;
323 virtual int HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const;
325 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
327 wxBitmap
*bmpPressed
,
328 wxBitmap
*bmpDisabled
);
330 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
331 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
332 virtual bool AreScrollbarsInsideBorder() const;
334 virtual wxSize
GetScrollbarArrowSize() const
335 { return m_sizeScrollbarArrow
; }
336 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
337 wxScrollBar::Element elem
,
338 int thumbPos
= -1) const;
339 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
340 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
341 const wxPoint
& pt
) const;
342 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
344 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
345 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
346 { return fontHeight
+ 2; }
347 virtual wxSize
GetCheckBitmapSize() const
348 { return wxSize(13, 13); }
349 virtual wxSize
GetRadioBitmapSize() const
350 { return wxSize(12, 12); }
351 virtual wxCoord
GetCheckItemMargin() const
354 virtual wxSize
GetToolBarButtonSize(wxCoord
*separator
) const
355 { if ( separator
) *separator
= 5; return wxSize(16, 15); }
356 virtual wxSize
GetToolBarMargin() const
357 { return wxSize(4, 4); }
359 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
360 const wxRect
& rect
) const;
361 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
363 wxCoord
*extraSpaceBeyond
) const;
365 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
366 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
368 virtual wxCoord
GetSliderDim() const { return 20; }
369 virtual wxCoord
GetSliderTickLen() const { return 4; }
370 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
371 wxOrientation orient
) const;
372 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
373 wxOrientation orient
) const;
374 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
376 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
377 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
378 const wxMenu
& menu
) const;
380 virtual wxSize
GetStatusBarBorders(wxCoord
*borderBetweenFields
) const;
383 // helper of DrawLabel() and DrawCheckOrRadioButton()
384 void DoDrawLabel(wxDC
& dc
,
385 const wxString
& label
,
388 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
390 wxRect
*rectBounds
= NULL
,
391 const wxPoint
& focusOffset
392 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
394 // common part of DrawLabel() and DrawItem()
395 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
397 // DrawLabel() and DrawButtonLabel() helper
398 void DrawLabelShadow(wxDC
& dc
,
399 const wxString
& label
,
404 // DrawButtonBorder() helper
405 void DoDrawBackground(wxDC
& dc
,
409 // DrawBorder() helpers: all of them shift and clip the DC after drawing
412 // just draw a rectangle with the given pen
413 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
415 // draw the lower left part of rectangle
416 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
418 // draw the rectange using the first brush for the left and top sides and
419 // the second one for the bottom and right ones
420 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
421 const wxPen
& pen1
, const wxPen
& pen2
);
423 // draw the normal 3D border
424 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
426 // draw the sunken 3D border
427 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
429 // draw the border used for scrollbar arrows
430 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
432 // public DrawArrow()s helper
433 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
434 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
436 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
437 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
438 wxArrowDirection arrowDir
,
439 wxArrowStyle arrowStyle
);
441 // DrawCheckButton/DrawRadioButton helper
442 void DrawCheckOrRadioButton(wxDC
& dc
,
443 const wxString
& label
,
444 const wxBitmap
& bitmap
,
449 wxCoord focusOffsetY
);
451 // draw a normal or transposed line (useful for using the same code fo both
452 // horizontal and vertical widgets)
453 void DrawLine(wxDC
& dc
,
454 wxCoord x1
, wxCoord y1
,
455 wxCoord x2
, wxCoord y2
,
456 bool transpose
= FALSE
)
459 dc
.DrawLine(y1
, x1
, y2
, x2
);
461 dc
.DrawLine(x1
, y1
, x2
, y2
);
464 // get the standard check/radio button bitmap
465 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
466 wxBitmap
GetCheckBitmap(int flags
)
467 { return GetIndicator(IndicatorType_Check
, flags
); }
468 wxBitmap
GetRadioBitmap(int flags
)
469 { return GetIndicator(IndicatorType_Radio
, flags
); }
472 const wxColourScheme
*m_scheme
;
474 // the sizing parameters (TODO make them changeable)
475 wxSize m_sizeScrollbarArrow
;
477 // GDI objects we use for drawing
478 wxColour m_colDarkGrey
,
486 wxFont m_titlebarFont
;
488 // the checked and unchecked bitmaps for DrawCheckItem()
489 wxBitmap m_bmpCheckBitmaps
[IndicatorStatus_Max
];
491 // the bitmaps returned by GetIndicator()
492 wxBitmap m_bmpIndicators
[IndicatorType_Max
]
494 [IndicatorStatus_Max
];
497 wxBitmap m_bmpFrameButtons
[FrameButton_Max
];
499 // first row is for the normal state, second - for the disabled
500 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
503 // ----------------------------------------------------------------------------
504 // wxMetalInputHandler and derived classes: process the keyboard and mouse
505 // messages according to Windows standards
506 // ----------------------------------------------------------------------------
508 class wxMetalInputHandler
: public wxInputHandler
511 wxMetalInputHandler(wxMetalRenderer
*renderer
);
513 virtual bool HandleKey(wxInputConsumer
*control
,
514 const wxKeyEvent
& event
,
516 virtual bool HandleMouse(wxInputConsumer
*control
,
517 const wxMouseEvent
& event
);
520 wxMetalRenderer
*m_renderer
;
523 class wxMetalScrollBarInputHandler
: public wxStdScrollBarInputHandler
526 wxMetalScrollBarInputHandler(wxMetalRenderer
*renderer
,
527 wxInputHandler
*handler
);
529 virtual bool HandleMouse(wxInputConsumer
*control
, const wxMouseEvent
& event
);
530 virtual bool HandleMouseMove(wxInputConsumer
*control
, const wxMouseEvent
& event
);
532 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
533 const wxControlAction
& action
);
536 virtual bool IsAllowedButton(int button
) { return button
== 1; }
538 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
540 // we don't highlight anything
543 // the first and last event which caused the thumb to move
544 wxMouseEvent m_eventStartDrag
,
547 // have we paused the scrolling because the mouse moved?
550 // we remember the interval of the timer to be able to restart it
554 class wxMetalCheckboxInputHandler
: public wxStdCheckboxInputHandler
557 wxMetalCheckboxInputHandler(wxInputHandler
*handler
)
558 : wxStdCheckboxInputHandler(handler
) { }
560 virtual bool HandleKey(wxInputConsumer
*control
,
561 const wxKeyEvent
& event
,
565 class wxMetalTextCtrlInputHandler
: public wxStdTextCtrlInputHandler
568 wxMetalTextCtrlInputHandler(wxInputHandler
*handler
)
569 : wxStdTextCtrlInputHandler(handler
) { }
571 virtual bool HandleKey(wxInputConsumer
*control
,
572 const wxKeyEvent
& event
,
576 class wxMetalStatusBarInputHandler
: public wxStdInputHandler
579 wxMetalStatusBarInputHandler(wxInputHandler
*handler
);
581 virtual bool HandleMouse(wxInputConsumer
*consumer
,
582 const wxMouseEvent
& event
);
584 virtual bool HandleMouseMove(wxInputConsumer
*consumer
,
585 const wxMouseEvent
& event
);
588 // is the given point over the statusbar grip?
589 bool IsOnGrip(wxWindow
*statbar
, const wxPoint
& pt
) const;
592 // the cursor we had replaced with the resize one
593 wxCursor m_cursorOld
;
595 // was the mouse over the grip last time we checked?
599 class wxMetalSystemMenuEvtHandler
;
601 class wxMetalFrameInputHandler
: public wxStdFrameInputHandler
604 wxMetalFrameInputHandler(wxInputHandler
*handler
);
605 ~wxMetalFrameInputHandler();
607 virtual bool HandleMouse(wxInputConsumer
*control
,
608 const wxMouseEvent
& event
);
610 virtual bool HandleActivation(wxInputConsumer
*consumer
, bool activated
);
612 void PopupSystemMenu(wxTopLevelWindow
*window
, const wxPoint
& pos
) const;
615 // was the mouse over the grip last time we checked?
616 wxMetalSystemMenuEvtHandler
*m_menuHandler
;
619 // ----------------------------------------------------------------------------
620 // wxMetalColourScheme: uses (default) Metal colours
621 // ----------------------------------------------------------------------------
623 class wxMetalColourScheme
: public wxColourScheme
626 virtual wxColour
Get(StdColour col
) const;
627 virtual wxColour
GetBackground(wxWindow
*win
) const;
630 // ----------------------------------------------------------------------------
631 // wxMetalArtProvider
632 // ----------------------------------------------------------------------------
634 class wxMetalArtProvider
: public wxArtProvider
637 virtual wxBitmap
CreateBitmap(const wxArtID
& id
,
638 const wxArtClient
& client
,
642 // ----------------------------------------------------------------------------
644 // ----------------------------------------------------------------------------
646 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
648 class wxMetalTheme
: public wxTheme
652 virtual ~wxMetalTheme();
654 virtual wxRenderer
*GetRenderer();
655 virtual wxArtProvider
*GetArtProvider();
656 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
657 virtual wxColourScheme
*GetColourScheme();
660 // get the default input handler
661 wxInputHandler
*GetDefaultInputHandler();
663 wxMetalRenderer
*m_renderer
;
665 wxMetalArtProvider
*m_artProvider
;
667 // the names of the already created handlers and the handlers themselves
668 // (these arrays are synchronized)
669 wxSortedArrayString m_handlerNames
;
670 wxArrayHandlers m_handlers
;
672 wxMetalInputHandler
*m_handlerDefault
;
674 wxMetalColourScheme
*m_scheme
;
676 WX_DECLARE_THEME(Metal
)
679 // ----------------------------------------------------------------------------
681 // ----------------------------------------------------------------------------
683 // frame buttons bitmaps
685 static const char *frame_button_close_xpm
[] = {
700 static const char *frame_button_help_xpm
[] = {
715 static const char *frame_button_maximize_xpm
[] = {
730 static const char *frame_button_minimize_xpm
[] = {
745 static const char *frame_button_restore_xpm
[] = {
762 static const char *checked_menu_xpm
[] = {
763 /* columns rows colors chars-per-pixel */
779 static const char *selected_checked_menu_xpm
[] = {
780 /* columns rows colors chars-per-pixel */
796 static const char *disabled_checked_menu_xpm
[] = {
797 /* columns rows colors chars-per-pixel */
814 static const char *selected_disabled_checked_menu_xpm
[] = {
815 /* columns rows colors chars-per-pixel */
831 // checkbox and radiobox bitmaps below
833 static const char *checked_xpm
[] = {
834 /* columns rows colors chars-per-pixel */
857 static const char *pressed_checked_xpm
[] = {
858 /* columns rows colors chars-per-pixel */
880 static const char *pressed_disabled_checked_xpm
[] = {
881 /* columns rows colors chars-per-pixel */
903 static const char *checked_item_xpm
[] = {
904 /* columns rows colors chars-per-pixel */
925 static const char *unchecked_xpm
[] = {
926 /* columns rows colors chars-per-pixel */
949 static const char *pressed_unchecked_xpm
[] = {
950 /* columns rows colors chars-per-pixel */
972 static const char *unchecked_item_xpm
[] = {
973 /* columns rows colors chars-per-pixel */
993 static const char *checked_radio_xpm
[] = {
994 /* columns rows colors chars-per-pixel */
1017 static const char *pressed_checked_radio_xpm
[] = {
1018 /* columns rows colors chars-per-pixel */
1041 static const char *pressed_disabled_checked_radio_xpm
[] = {
1042 /* columns rows colors chars-per-pixel */
1065 static const char *unchecked_radio_xpm
[] = {
1066 /* columns rows colors chars-per-pixel */
1089 static const char *pressed_unchecked_radio_xpm
[] = {
1090 /* columns rows colors chars-per-pixel */
1113 static const char **
1114 xpmIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
1119 { checked_xpm
, unchecked_xpm
},
1122 { pressed_checked_xpm
, pressed_unchecked_xpm
},
1125 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
1131 { checked_radio_xpm
, unchecked_radio_xpm
},
1134 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1137 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1143 { checked_menu_xpm
, NULL
},
1146 { selected_checked_menu_xpm
, NULL
},
1149 { disabled_checked_menu_xpm
, NULL
},
1151 // disabled selected state
1152 { selected_disabled_checked_menu_xpm
, NULL
},
1156 static const char **xpmChecked
[IndicatorStatus_Max
] =
1162 // ============================================================================
1164 // ============================================================================
1166 WX_IMPLEMENT_THEME(wxMetalTheme
, Metal
, wxTRANSLATE("Metal theme"));
1168 // ----------------------------------------------------------------------------
1170 // ----------------------------------------------------------------------------
1172 wxMetalTheme::wxMetalTheme()
1176 m_handlerDefault
= NULL
;
1179 wxMetalTheme::~wxMetalTheme()
1181 size_t count
= m_handlers
.GetCount();
1182 for ( size_t n
= 0; n
< count
; n
++ )
1184 if ( m_handlers
[n
] != m_handlerDefault
)
1185 delete m_handlers
[n
];
1188 delete m_handlerDefault
;
1194 wxRenderer
*wxMetalTheme::GetRenderer()
1198 m_renderer
= new wxMetalRenderer(GetColourScheme());
1204 wxArtProvider
*wxMetalTheme::GetArtProvider()
1206 if ( !m_artProvider
)
1208 m_artProvider
= new wxMetalArtProvider
;
1211 return m_artProvider
;
1214 wxInputHandler
*wxMetalTheme::GetDefaultInputHandler()
1216 if ( !m_handlerDefault
)
1218 m_handlerDefault
= new wxMetalInputHandler(m_renderer
);
1221 return m_handlerDefault
;
1224 wxInputHandler
*wxMetalTheme::GetInputHandler(const wxString
& control
)
1226 wxInputHandler
*handler
;
1227 int n
= m_handlerNames
.Index(control
);
1228 if ( n
== wxNOT_FOUND
)
1230 // create a new handler
1231 if ( control
== wxINP_HANDLER_SCROLLBAR
)
1232 handler
= new wxMetalScrollBarInputHandler(m_renderer
,
1233 GetDefaultInputHandler());
1235 else if ( control
== wxINP_HANDLER_BUTTON
)
1236 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
1237 #endif // wxUSE_BUTTON
1239 else if ( control
== wxINP_HANDLER_CHECKBOX
)
1240 handler
= new wxMetalCheckboxInputHandler(GetDefaultInputHandler());
1241 #endif // wxUSE_CHECKBOX
1243 else if ( control
== wxINP_HANDLER_COMBOBOX
)
1244 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1245 #endif // wxUSE_COMBOBOX
1247 else if ( control
== wxINP_HANDLER_LISTBOX
)
1248 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1249 #endif // wxUSE_LISTBOX
1250 #if wxUSE_CHECKLISTBOX
1251 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1252 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1253 #endif // wxUSE_CHECKLISTBOX
1255 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1256 handler
= new wxMetalTextCtrlInputHandler(GetDefaultInputHandler());
1257 #endif // wxUSE_TEXTCTRL
1259 else if ( control
== wxINP_HANDLER_SLIDER
)
1260 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1261 #endif // wxUSE_SLIDER
1263 else if ( control
== wxINP_HANDLER_SPINBTN
)
1264 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1265 #endif // wxUSE_SPINBTN
1267 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1268 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1269 #endif // wxUSE_NOTEBOOK
1271 else if ( control
== wxINP_HANDLER_STATUSBAR
)
1272 handler
= new wxMetalStatusBarInputHandler(GetDefaultInputHandler());
1273 #endif // wxUSE_STATUSBAR
1275 else if ( control
== wxINP_HANDLER_TOOLBAR
)
1276 handler
= new wxStdToolbarInputHandler(GetDefaultInputHandler());
1277 #endif // wxUSE_TOOLBAR
1278 else if ( control
== wxINP_HANDLER_TOPLEVEL
)
1279 handler
= new wxMetalFrameInputHandler(GetDefaultInputHandler());
1281 handler
= GetDefaultInputHandler();
1283 n
= m_handlerNames
.Add(control
);
1284 m_handlers
.Insert(handler
, n
);
1286 else // we already have it
1288 handler
= m_handlers
[n
];
1294 wxColourScheme
*wxMetalTheme::GetColourScheme()
1298 m_scheme
= new wxMetalColourScheme
;
1303 // ============================================================================
1304 // wxMetalColourScheme
1305 // ============================================================================
1307 wxColour
wxMetalColourScheme::GetBackground(wxWindow
*win
) const
1310 if ( win
->UseBgCol() )
1312 // use the user specified colour
1313 col
= win
->GetBackgroundColour();
1316 if ( win
->IsContainerWindow() )
1318 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1321 if ( !text
->IsEnabled() ) // not IsEditable()
1323 //else: execute code below
1328 // doesn't depend on the state
1334 if ( win
->HasDialogBackground() )
1336 col
= win
->GetParent()->GetBackgroundColour();
1340 int flags
= win
->GetStateFlags();
1342 // the colour set by the user should be used for the normal state
1343 // and for the states for which we don't have any specific colours
1344 if ( !col
.Ok() || (flags
& wxCONTROL_PRESSED
) != 0 )
1346 if ( wxDynamicCast(win
, wxScrollBar
) )
1347 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1357 wxColour
wxMetalColourScheme::Get(wxMetalColourScheme::StdColour col
) const
1361 // use the system colours under Windows
1362 #if defined(__WXMSW__)
1363 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1365 case CONTROL_PRESSED
:
1366 case CONTROL_CURRENT
:
1367 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1369 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1371 #if defined(COLOR_3DLIGHT)
1372 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_3DLIGHT
));
1374 case SCROLLBAR
: return wxColour(0xe0e0e0);
1376 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1378 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1379 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1381 #if defined(COLOR_3DDKSHADOW)
1382 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1384 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DHADOW
));
1387 case CONTROL_TEXT_DISABLED
:
1388 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1390 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1392 case CONTROL_TEXT_DISABLED_SHADOW
:
1393 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1395 case TITLEBAR
: return wxColour(GetSysColor(COLOR_INACTIVECAPTION
));
1396 case TITLEBAR_ACTIVE
: return wxColour(GetSysColor(COLOR_ACTIVECAPTION
));
1397 case TITLEBAR_TEXT
: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT
));
1398 case TITLEBAR_ACTIVE_TEXT
: return wxColour(GetSysColor(COLOR_CAPTIONTEXT
));
1400 case DESKTOP
: return wxColour(0x808000);
1402 // use the standard Windows colours elsewhere
1403 case WINDOW
: return *wxWHITE
;
1405 case CONTROL_PRESSED
:
1406 case CONTROL_CURRENT
:
1407 case CONTROL
: return wxColour(0xc0c0c0);
1409 case CONTROL_TEXT
: return *wxBLACK
;
1411 case SCROLLBAR
: return wxColour(0xe0e0e0);
1412 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1414 case HIGHLIGHT
: return wxColour(0x800000);
1415 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1417 case SHADOW_DARK
: return *wxBLACK
;
1419 case CONTROL_TEXT_DISABLED
:return wxColour(0xe0e0e0);
1420 case SHADOW_HIGHLIGHT
: return wxColour(0xffffff);
1422 case SHADOW_IN
: return wxColour(0xc0c0c0);
1424 case CONTROL_TEXT_DISABLED_SHADOW
:
1425 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1427 case TITLEBAR
: return wxColour(0xaeaaae);
1428 case TITLEBAR_ACTIVE
: return wxColour(0x820300);
1429 case TITLEBAR_TEXT
: return wxColour(0xc0c0c0);
1430 case TITLEBAR_ACTIVE_TEXT
:return *wxWHITE
;
1432 case DESKTOP
: return wxColour(0x808000);
1435 case GAUGE
: return Get(HIGHLIGHT
);
1439 wxFAIL_MSG(_T("invalid standard colour"));
1444 // ============================================================================
1446 // ============================================================================
1448 // ----------------------------------------------------------------------------
1450 // ----------------------------------------------------------------------------
1452 wxMetalRenderer::wxMetalRenderer(const wxColourScheme
*scheme
)
1456 m_sizeScrollbarArrow
= wxSize(16, 16);
1458 // init colours and pens
1459 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1461 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1462 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1464 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1466 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1467 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1469 m_titlebarFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
1470 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
1472 // init the arrow bitmaps
1473 static const size_t ARROW_WIDTH
= 7;
1474 static const size_t ARROW_LENGTH
= 4;
1477 wxMemoryDC dcNormal
,
1480 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1482 bool isVertical
= n
> Arrow_Right
;
1495 // disabled arrow is larger because of the shadow
1496 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1497 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1499 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1500 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1502 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1503 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1507 dcNormal
.SetPen(m_penBlack
);
1508 dcDisabled
.SetPen(m_penDarkGrey
);
1510 // calculate the position of the point of the arrow
1514 x1
= (ARROW_WIDTH
- 1)/2;
1515 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1519 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1520 y1
= (ARROW_WIDTH
- 1)/2;
1531 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1533 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1534 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1541 if ( n
== Arrow_Up
)
1552 else // left or right arrow
1557 if ( n
== Arrow_Left
)
1570 // draw the shadow for the disabled one
1571 dcDisabled
.SetPen(m_penHighlight
);
1576 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1580 x1
= ARROW_LENGTH
- 1;
1581 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1584 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1585 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1590 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1594 x1
= ARROW_WIDTH
- 1;
1596 x2
= (ARROW_WIDTH
- 1)/2;
1598 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1599 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1604 // create the inversed bitmap but only for the right arrow as we only
1605 // use it for the menus
1606 if ( n
== Arrow_Right
)
1608 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1609 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1611 dcInverse
.Blit(0, 0, w
, h
,
1614 dcInverse
.SelectObject(wxNullBitmap
);
1616 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1617 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1619 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1620 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1622 dcInverse
.Blit(0, 0, w
, h
,
1625 dcInverse
.SelectObject(wxNullBitmap
);
1627 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1628 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1631 dcNormal
.SelectObject(wxNullBitmap
);
1632 dcDisabled
.SelectObject(wxNullBitmap
);
1634 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1635 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1636 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1637 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1639 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1642 // init the frame buttons bitmaps
1643 m_bmpFrameButtons
[FrameButton_Close
] = wxBitmap(frame_button_close_xpm
);
1644 m_bmpFrameButtons
[FrameButton_Minimize
] = wxBitmap(frame_button_minimize_xpm
);
1645 m_bmpFrameButtons
[FrameButton_Maximize
] = wxBitmap(frame_button_maximize_xpm
);
1646 m_bmpFrameButtons
[FrameButton_Restore
] = wxBitmap(frame_button_restore_xpm
);
1647 m_bmpFrameButtons
[FrameButton_Help
] = wxBitmap(frame_button_help_xpm
);
1650 // ----------------------------------------------------------------------------
1652 // ----------------------------------------------------------------------------
1655 The raised border in Metal looks like this:
1657 IIIIIIIIIIIIIIIIIIIIIIB
1659 I GB I = white (HILIGHT)
1660 I GB H = light grey (LIGHT)
1661 I GB G = dark grey (SHADOI)
1662 I GB B = black (DKSHADOI)
1663 I GB I = hIghlight (COLOR_3DHILIGHT)
1665 IGGGGGGGGGGGGGGGGGGGGGB
1666 BBBBBBBBBBBBBBBBBBBBBBB
1668 The sunken border looks like this:
1670 GGGGGGGGGGGGGGGGGGGGGGI
1671 GBBBBBBBBBBBBBBBBBBBBHI
1678 GHHHHHHHHHHHHHHHHHHHHHI
1679 IIIIIIIIIIIIIIIIIIIIIII
1681 The static border (used for the controls which don't get focus) is like
1684 GGGGGGGGGGGGGGGGGGGGGGW
1692 WWWWWWWWWWWWWWWWWWWWWWW
1694 The most complicated is the double border:
1696 HHHHHHHHHHHHHHHHHHHHHHB
1697 HWWWWWWWWWWWWWWWWWWWWGB
1698 HWHHHHHHHHHHHHHHHHHHHGB
1703 HWHHHHHHHHHHHHHHHHHHHGB
1704 HGGGGGGGGGGGGGGGGGGGGGB
1705 BBBBBBBBBBBBBBBBBBBBBBB
1707 And the simple border is, well, simple:
1709 BBBBBBBBBBBBBBBBBBBBBBB
1718 BBBBBBBBBBBBBBBBBBBBBBB
1721 void wxMetalRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1725 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1726 dc
.DrawRectangle(*rect
);
1732 void wxMetalRenderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1734 // draw the bottom and right sides
1736 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1737 rect
->GetRight() + 1, rect
->GetBottom());
1738 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1739 rect
->GetRight(), rect
->GetBottom());
1746 void wxMetalRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1747 const wxPen
& pen1
, const wxPen
& pen2
)
1749 // draw the rectangle
1751 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1752 rect
->GetLeft(), rect
->GetBottom());
1753 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1754 rect
->GetRight(), rect
->GetTop());
1756 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1757 rect
->GetRight(), rect
->GetBottom());
1758 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1759 rect
->GetRight() + 1, rect
->GetBottom());
1765 void wxMetalRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1767 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1768 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1771 void wxMetalRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1773 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1774 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1777 void wxMetalRenderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1781 DrawRect(dc
, rect
, m_penDarkGrey
);
1783 // the arrow is usually drawn inside border of width 2 and is offset by
1784 // another pixel in both directions when it's pressed - as the border
1785 // in this case is more narrow as well, we have to adjust rect like
1793 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1794 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1798 void wxMetalRenderer::DrawBorder(wxDC
& dc
,
1800 const wxRect
& rectTotal
,
1801 int WXUNUSED(flags
),
1806 wxRect rect
= rectTotal
;
1810 case wxBORDER_SUNKEN
:
1811 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1813 DrawSunkenBorder(dc
, &rect
);
1817 case wxBORDER_STATIC
:
1818 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1821 case wxBORDER_RAISED
:
1822 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1824 DrawRaisedBorder(dc
, &rect
);
1828 case wxBORDER_DOUBLE
:
1829 DrawArrowBorder(dc
, &rect
);
1830 DrawRect(dc
, &rect
, m_penLightGrey
);
1833 case wxBORDER_SIMPLE
:
1834 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1836 DrawRect(dc
, &rect
, m_penBlack
);
1841 wxFAIL_MSG(_T("unknown border type"));
1844 case wxBORDER_DEFAULT
:
1853 wxRect
wxMetalRenderer::GetBorderDimensions(wxBorder border
) const
1858 case wxBORDER_RAISED
:
1859 case wxBORDER_SUNKEN
:
1860 width
= BORDER_THICKNESS
;
1863 case wxBORDER_SIMPLE
:
1864 case wxBORDER_STATIC
:
1868 case wxBORDER_DOUBLE
:
1874 // char *crash = NULL;
1876 wxFAIL_MSG(_T("unknown border type"));
1880 case wxBORDER_DEFAULT
:
1890 rect
.height
= width
;
1895 bool wxMetalRenderer::AreScrollbarsInsideBorder() const
1900 // ----------------------------------------------------------------------------
1902 // ----------------------------------------------------------------------------
1904 void wxMetalRenderer::DrawTextBorder(wxDC
& dc
,
1910 // text controls are not special under windows
1911 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1914 void wxMetalRenderer::DrawButtonBorder(wxDC
& dc
,
1915 const wxRect
& rectTotal
,
1919 wxRect rect
= rectTotal
;
1921 if ( flags
& wxCONTROL_PRESSED
)
1923 // button pressed: draw a double border around it
1924 DrawRect(dc
, &rect
, m_penBlack
);
1925 DrawRect(dc
, &rect
, m_penDarkGrey
);
1929 // button not pressed
1931 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1933 // button either default or focused (or both): add an extra border around it
1934 DrawRect(dc
, &rect
, m_penBlack
);
1937 // now draw a normal button
1938 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1939 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1948 // ----------------------------------------------------------------------------
1950 // ----------------------------------------------------------------------------
1952 void wxMetalRenderer::DrawHorizontalLine(wxDC
& dc
,
1953 wxCoord y
, wxCoord x1
, wxCoord x2
)
1955 dc
.SetPen(m_penDarkGrey
);
1956 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1957 dc
.SetPen(m_penHighlight
);
1959 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1962 void wxMetalRenderer::DrawVerticalLine(wxDC
& dc
,
1963 wxCoord x
, wxCoord y1
, wxCoord y2
)
1965 dc
.SetPen(m_penDarkGrey
);
1966 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1967 dc
.SetPen(m_penHighlight
);
1969 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1972 void wxMetalRenderer::DrawFrame(wxDC
& dc
,
1973 const wxString
& label
,
1979 wxCoord height
= 0; // of the label
1980 wxRect rectFrame
= rect
;
1981 if ( !label
.empty() )
1983 // the text should touch the top border of the rect, so the frame
1984 // itself should be lower
1985 dc
.GetTextExtent(label
, NULL
, &height
);
1986 rectFrame
.y
+= height
/ 2;
1987 rectFrame
.height
-= height
/ 2;
1989 // we have to draw each part of the frame individually as we can't
1990 // erase the background beyond the label as it might contain some
1991 // pixmap already, so drawing everything and then overwriting part of
1992 // the frame with label doesn't work
1994 // TODO: the +5 and space insertion should be customizable
1997 rectText
.x
= rectFrame
.x
+ 5;
1998 rectText
.y
= rect
.y
;
1999 rectText
.width
= rectFrame
.width
- 7; // +2 border width
2000 rectText
.height
= height
;
2003 label2
<< _T(' ') << label
<< _T(' ');
2004 if ( indexAccel
!= -1 )
2006 // adjust it as we prepended a space
2011 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
2013 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
2017 // just draw the complete frame
2018 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
2019 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
2023 // ----------------------------------------------------------------------------
2025 // ----------------------------------------------------------------------------
2027 void wxMetalRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
2029 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
2030 // pixels each while we really need dots here... PS_ALTERNATE might
2031 // work, but it is for NT 5 only
2033 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
2035 // draw the pixels manually: note that to behave in the same manner as
2036 // DrawRect(), we must exclude the bottom and right borders from the
2038 wxCoord x1
= rect
.GetLeft(),
2040 x2
= rect
.GetRight(),
2041 y2
= rect
.GetBottom();
2043 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
2045 // this seems to be closer than what Windows does than wxINVERT although
2046 // I'm still not sure if it's correct
2047 dc
.SetLogicalFunction(wxAND_REVERSE
);
2050 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
2051 dc
.DrawPoint(z
, rect
.GetTop());
2053 wxCoord shift
= z
== x2
? 0 : 1;
2054 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
2055 dc
.DrawPoint(x2
, z
);
2057 shift
= z
== y2
? 0 : 1;
2058 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
2059 dc
.DrawPoint(z
, y2
);
2061 shift
= z
== x1
? 0 : 1;
2062 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
2063 dc
.DrawPoint(x1
, z
);
2065 dc
.SetLogicalFunction(wxCOPY
);
2069 void wxMetalRenderer::DrawLabelShadow(wxDC
& dc
,
2070 const wxString
& label
,
2075 // draw shadow of the text
2076 dc
.SetTextForeground(m_colHighlight
);
2077 wxRect rectShadow
= rect
;
2080 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
2082 // make the text grey
2083 dc
.SetTextForeground(m_colDarkGrey
);
2086 void wxMetalRenderer::DrawLabel(wxDC
& dc
,
2087 const wxString
& label
,
2094 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
2097 void wxMetalRenderer::DoDrawLabel(wxDC
& dc
,
2098 const wxString
& label
,
2104 const wxPoint
& focusOffset
)
2106 // the underscores are not drawn for focused controls in wxMSW
2107 if ( flags
& wxCONTROL_FOCUSED
)
2112 if ( flags
& wxCONTROL_DISABLED
)
2114 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2115 // currently only can happen for a menu item and it seems that Windows
2116 // doesn't draw the shadow in this case, so we don't do it neither
2117 if ( flags
& wxCONTROL_SELECTED
)
2119 // just make the label text greyed out
2120 dc
.SetTextForeground(m_colDarkGrey
);
2122 else // draw normal disabled label
2124 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
2129 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
2131 if ( flags
& wxCONTROL_DISABLED
)
2133 // restore the fg colour
2134 dc
.SetTextForeground(*wxBLACK
);
2137 if ( flags
& wxCONTROL_FOCUSED
)
2139 if ( focusOffset
.x
|| focusOffset
.y
)
2141 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
2144 DrawFocusRect(dc
, rectLabel
);
2148 *rectBounds
= rectLabel
;
2151 void wxMetalRenderer::DrawButtonLabel(wxDC
& dc
,
2152 const wxString
& label
,
2153 const wxBitmap
& image
,
2160 // the underscores are not drawn for focused controls in wxMSW
2161 if ( flags
& wxCONTROL_PRESSED
)
2166 wxRect rectLabel
= rect
;
2167 if ( !label
.empty() )
2169 // shift the label if a button is pressed
2170 if ( flags
& wxCONTROL_PRESSED
)
2176 if ( flags
& wxCONTROL_DISABLED
)
2178 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
2181 // leave enough space for the focus rectangle
2182 if ( flags
& wxCONTROL_FOCUSED
)
2184 rectLabel
.Inflate(-2);
2188 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
2190 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
2192 if ( flags
& wxCONTROL_PRESSED
)
2194 // the focus rectangle is never pressed, so undo the shift done
2202 DrawFocusRect(dc
, rectLabel
);
2206 // ----------------------------------------------------------------------------
2207 // (check)listbox items
2208 // ----------------------------------------------------------------------------
2210 void wxMetalRenderer::DrawItem(wxDC
& dc
,
2211 const wxString
& label
,
2215 wxDCTextColourChanger
colChanger(dc
);
2217 if ( flags
& wxCONTROL_SELECTED
)
2219 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2221 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2222 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2223 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2224 dc
.DrawRectangle(rect
);
2227 wxRect rectText
= rect
;
2229 rectText
.width
-= 2;
2230 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
2232 if ( flags
& wxCONTROL_FOCUSED
)
2234 DrawFocusRect(dc
, rect
);
2238 void wxMetalRenderer::DrawCheckItem(wxDC
& dc
,
2239 const wxString
& label
,
2240 const wxBitmap
& bitmap
,
2249 else // use default bitmap
2251 IndicatorStatus i
= flags
& wxCONTROL_CHECKED
2252 ? IndicatorStatus_Checked
2253 : IndicatorStatus_Unchecked
;
2255 if ( !m_bmpCheckBitmaps
[i
].Ok() )
2257 m_bmpCheckBitmaps
[i
] = wxBitmap(xpmChecked
[i
]);
2260 bmp
= m_bmpCheckBitmaps
[i
];
2263 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
2264 TRUE
/* use mask */);
2266 wxRect rectLabel
= rect
;
2267 int bmpWidth
= bmp
.GetWidth();
2268 rectLabel
.x
+= bmpWidth
;
2269 rectLabel
.width
-= bmpWidth
;
2271 DrawItem(dc
, label
, rectLabel
, flags
);
2274 // ----------------------------------------------------------------------------
2275 // check/radio buttons
2276 // ----------------------------------------------------------------------------
2278 wxBitmap
wxMetalRenderer::GetIndicator(IndicatorType indType
, int flags
)
2280 IndicatorState indState
;
2281 if ( flags
& wxCONTROL_SELECTED
)
2282 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
2283 : IndicatorState_Selected
;
2284 else if ( flags
& wxCONTROL_DISABLED
)
2285 indState
= IndicatorState_Disabled
;
2286 else if ( flags
& wxCONTROL_PRESSED
)
2287 indState
= IndicatorState_Pressed
;
2289 indState
= IndicatorState_Normal
;
2291 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
2292 ? IndicatorStatus_Checked
2293 : IndicatorStatus_Unchecked
;
2295 wxBitmap bmp
= m_bmpIndicators
[indType
][indState
][indStatus
];
2298 const char **xpm
= xpmIndicators
[indType
][indState
][indStatus
];
2301 // create and cache it
2302 bmp
= wxBitmap(xpm
);
2303 m_bmpIndicators
[indType
][indState
][indStatus
] = bmp
;
2310 void wxMetalRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
2311 const wxString
& label
,
2312 const wxBitmap
& bitmap
,
2317 wxCoord focusOffsetY
)
2319 // calculate the position of the bitmap and of the label
2320 wxCoord heightBmp
= bitmap
.GetHeight();
2322 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2325 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2326 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2328 // align label vertically with the bitmap - looks nicer like this
2329 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2331 // calc horz position
2332 if ( align
== wxALIGN_RIGHT
)
2334 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2335 rectLabel
.x
= rect
.x
+ 3;
2336 rectLabel
.SetRight(xBmp
);
2338 else // normal (checkbox to the left of the text) case
2341 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2342 rectLabel
.SetRight(rect
.GetRight());
2345 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2348 dc
, label
, rectLabel
,
2350 wxALIGN_LEFT
| wxALIGN_TOP
,
2352 NULL
, // we don't need bounding rect
2353 // use custom vert focus rect offset
2354 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2358 void wxMetalRenderer::DrawRadioButton(wxDC
& dc
,
2359 const wxString
& label
,
2360 const wxBitmap
& bitmap
,
2370 bmp
= GetRadioBitmap(flags
);
2372 DrawCheckOrRadioButton(dc
, label
,
2374 rect
, flags
, align
, indexAccel
,
2375 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2378 void wxMetalRenderer::DrawCheckButton(wxDC
& dc
,
2379 const wxString
& label
,
2380 const wxBitmap
& bitmap
,
2390 bmp
= GetCheckBitmap(flags
);
2392 DrawCheckOrRadioButton(dc
, label
,
2394 rect
, flags
, align
, indexAccel
,
2395 0); // no focus rect offset for checkboxes
2398 void wxMetalRenderer::DrawToolBarButton(wxDC
& dc
,
2399 const wxString
& label
,
2400 const wxBitmap
& bitmap
,
2401 const wxRect
& rectOrig
,
2404 if ( !label
.empty() || bitmap
.Ok() )
2406 wxRect rect
= rectOrig
;
2407 rect
.Deflate(BORDER_THICKNESS
);
2409 if ( flags
& wxCONTROL_PRESSED
)
2411 DrawBorder(dc
, wxBORDER_SUNKEN
, rect
, flags
);
2413 else if ( flags
& wxCONTROL_CURRENT
)
2415 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
);
2418 dc
.DrawLabel(label
, bitmap
, rect
, wxALIGN_CENTRE
);
2422 // leave a small gap aroudn the line, also account for the toolbar
2424 DrawVerticalLine(dc
, rectOrig
.x
+ rectOrig
.width
/2,
2425 rectOrig
.y
+ 2*BORDER_THICKNESS
,
2426 rectOrig
.GetBottom() - BORDER_THICKNESS
);
2430 // ----------------------------------------------------------------------------
2432 // ----------------------------------------------------------------------------
2434 void wxMetalRenderer::DrawTextLine(wxDC
& dc
,
2435 const wxString
& text
,
2441 // nothing special to do here
2442 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2445 void wxMetalRenderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2447 // we don't draw them
2450 // ----------------------------------------------------------------------------
2452 // ----------------------------------------------------------------------------
2454 void wxMetalRenderer::DrawTab(wxDC
& dc
,
2455 const wxRect
& rectOrig
,
2457 const wxString
& label
,
2458 const wxBitmap
& bitmap
,
2462 wxRect rect
= rectOrig
;
2464 // the current tab is drawn indented (to the top for default case) and
2465 // bigger than the other ones
2466 const wxSize indent
= GetTabIndent();
2467 if ( flags
& wxCONTROL_SELECTED
)
2472 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2476 rect
.Inflate(indent
.x
, 0);
2478 rect
.height
+= indent
.y
;
2482 rect
.Inflate(indent
.x
, 0);
2483 rect
.height
+= indent
.y
;
2488 wxFAIL_MSG(_T("TODO"));
2493 // draw the text, image and the focus around them (if necessary)
2494 wxRect rectLabel
= rect
;
2495 rectLabel
.Deflate(1, 1);
2496 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2497 flags
, wxALIGN_CENTRE
, indexAccel
);
2499 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2500 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2503 x2
= rect
.GetRight(),
2504 y2
= rect
.GetBottom();
2506 // FIXME: all this code will break if the tab indent or the border width,
2507 // it is tied to the fact that both of them are equal to 2
2512 dc
.SetPen(m_penHighlight
);
2513 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2514 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2515 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2517 dc
.SetPen(m_penBlack
);
2518 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2519 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2521 dc
.SetPen(m_penDarkGrey
);
2522 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2524 if ( flags
& wxCONTROL_SELECTED
)
2526 dc
.SetPen(m_penLightGrey
);
2528 // overwrite the part of the border below this tab
2529 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2531 // and the shadow of the tab to the left of us
2532 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2537 dc
.SetPen(m_penHighlight
);
2538 // we need to continue one pixel further to overwrite the corner of
2539 // the border for the selected tab
2540 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2542 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2544 dc
.SetPen(m_penBlack
);
2545 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2546 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2547 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2549 dc
.SetPen(m_penDarkGrey
);
2550 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2551 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2553 if ( flags
& wxCONTROL_SELECTED
)
2555 dc
.SetPen(m_penLightGrey
);
2557 // overwrite the part of the (double!) border above this tab
2558 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2559 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2561 // and the shadow of the tab to the left of us
2562 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2568 wxFAIL_MSG(_T("TODO"));
2572 // ----------------------------------------------------------------------------
2574 // ----------------------------------------------------------------------------
2576 wxSize
wxMetalRenderer::GetSliderThumbSize(const wxRect
& rect
,
2577 wxOrientation orient
) const
2581 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2582 if ( orient
== wxHORIZONTAL
)
2584 size
.y
= rect
.height
- 6;
2585 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2589 size
.x
= rect
.width
- 6;
2590 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2596 wxRect
wxMetalRenderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2597 wxOrientation orient
) const
2599 static const wxCoord SLIDER_MARGIN
= 6;
2601 wxRect rect
= rectOrig
;
2603 if ( orient
== wxHORIZONTAL
)
2605 // make the rect of minimal width and centre it
2606 rect
.height
= 2*BORDER_THICKNESS
;
2607 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2611 // leave margins on the sides
2612 rect
.Deflate(SLIDER_MARGIN
, 0);
2616 // same as above but in other direction
2617 rect
.width
= 2*BORDER_THICKNESS
;
2618 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2622 rect
.Deflate(0, SLIDER_MARGIN
);
2628 void wxMetalRenderer::DrawSliderShaft(wxDC
& dc
,
2629 const wxRect
& rectOrig
,
2630 wxOrientation orient
,
2634 if ( flags
& wxCONTROL_FOCUSED
)
2636 DrawFocusRect(dc
, rectOrig
);
2639 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2644 DrawSunkenBorder(dc
, &rect
);
2647 void wxMetalRenderer::DrawSliderThumb(wxDC
& dc
,
2649 wxOrientation orient
,
2653 we are drawing a shape of this form
2658 H DB where H is hightlight colour
2671 The interior of this shape is filled with the hatched brush if the thumb
2675 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2677 bool transpose
= orient
== wxVERTICAL
;
2679 wxCoord x
, y
, x2
, y2
;
2684 x2
= rect
.GetBottom();
2685 y2
= rect
.GetRight();
2691 x2
= rect
.GetRight();
2692 y2
= rect
.GetBottom();
2695 // the size of the pointed part of the thumb
2696 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2698 wxCoord x3
= x
+ sizeArrow
,
2699 y3
= y2
- sizeArrow
;
2701 dc
.SetPen(m_penHighlight
);
2702 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2703 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2704 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2706 dc
.SetPen(m_penBlack
);
2707 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2708 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2710 dc
.SetPen(m_penDarkGrey
);
2711 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2712 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2714 if ( flags
& wxCONTROL_PRESSED
)
2716 // TODO: MSW fills the entire area inside, not just the rect
2717 wxRect rectInt
= rect
;
2719 rectInt
.SetRight(y3
);
2721 rectInt
.SetBottom(y3
);
2724 #if !defined(__WXMGL__)
2725 static const char *stipple_xpm
[] = {
2726 /* columns rows colors chars-per-pixel */
2735 // VS: MGL can only do 8x8 stipple brushes
2736 static const char *stipple_xpm
[] = {
2737 /* columns rows colors chars-per-pixel */
2752 dc
.SetBrush(wxBrush(stipple_xpm
));
2754 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2755 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2756 dc
.SetPen(*wxTRANSPARENT_PEN
);
2757 dc
.DrawRectangle(rectInt
);
2761 void wxMetalRenderer::DrawSliderTicks(wxDC
& dc
,
2763 const wxSize
& sizeThumb
,
2764 wxOrientation orient
,
2776 // the variable names correspond to horizontal case, but they can be used
2777 // for both orientations
2778 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2779 if ( orient
== wxHORIZONTAL
)
2781 x1
= rect
.GetLeft();
2782 x2
= rect
.GetRight();
2784 // draw from bottom to top to leave one pixel space between the ticks
2785 // and the slider as Windows do
2786 y1
= rect
.GetBottom();
2791 widthThumb
= sizeThumb
.x
;
2796 x2
= rect
.GetBottom();
2798 y1
= rect
.GetRight();
2799 y2
= rect
.GetLeft();
2803 widthThumb
= sizeThumb
.y
;
2806 // the first tick should be positioned in such way that a thumb drawn in
2807 // the first position points down directly to it
2808 x1
+= widthThumb
/ 2;
2809 x2
-= widthThumb
/ 2;
2811 // this also means that we have slightly less space for the ticks in
2812 // between the first and the last
2815 dc
.SetPen(m_penBlack
);
2817 int range
= end
- start
;
2818 for ( int n
= 0; n
< range
; n
+= step
)
2820 wxCoord x
= x1
+ (len
*n
) / range
;
2822 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2825 // always draw the line at the end position
2826 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2829 // ----------------------------------------------------------------------------
2831 // ----------------------------------------------------------------------------
2833 // wxMetalMenuGeometryInfo: the wxMenuGeometryInfo used by wxMetalRenderer
2834 class WXDLLEXPORT wxMetalMenuGeometryInfo
: public wxMenuGeometryInfo
2837 virtual wxSize
GetSize() const { return m_size
; }
2839 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2840 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2842 wxCoord
GetItemHeight() const { return m_heightItem
; }
2845 // the total size of the menu
2848 // the offset of the start of the menu item label
2851 // the offset of the start of the accel label
2854 // the height of a normal (not separator) item
2855 wxCoord m_heightItem
;
2857 friend wxMenuGeometryInfo
*
2858 wxMetalRenderer::GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2861 // FIXME: all constants are hardcoded but shouldn't be
2862 static const wxCoord MENU_LEFT_MARGIN
= 9;
2863 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2864 static const wxCoord MENU_VERT_MARGIN
= 3;
2866 // the margin around bitmap/check marks (on each side)
2867 static const wxCoord MENU_BMP_MARGIN
= 2;
2869 // the margin between the labels and accel strings
2870 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2872 // the separator height in pixels: in fact, strangely enough, the real height
2873 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2875 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2877 // the size of the standard checkmark bitmap
2878 static const wxCoord MENU_CHECK_SIZE
= 9;
2880 void wxMetalRenderer::DrawMenuBarItem(wxDC
& dc
,
2881 const wxRect
& rectOrig
,
2882 const wxString
& label
,
2886 wxRect rect
= rectOrig
;
2889 wxDCTextColourChanger
colChanger(dc
);
2891 if ( flags
& wxCONTROL_SELECTED
)
2893 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2895 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2896 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2897 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2898 dc
.DrawRectangle(rect
);
2901 // don't draw the focus rect around menu bar items
2902 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2903 wxALIGN_CENTRE
, indexAccel
);
2906 void wxMetalRenderer::DrawMenuItem(wxDC
& dc
,
2908 const wxMenuGeometryInfo
& gi
,
2909 const wxString
& label
,
2910 const wxString
& accel
,
2911 const wxBitmap
& bitmap
,
2915 const wxMetalMenuGeometryInfo
& geometryInfo
=
2916 (const wxMetalMenuGeometryInfo
&)gi
;
2921 rect
.width
= geometryInfo
.GetSize().x
;
2922 rect
.height
= geometryInfo
.GetItemHeight();
2924 // draw the selected item specially
2925 wxDCTextColourChanger
colChanger(dc
);
2926 if ( flags
& wxCONTROL_SELECTED
)
2928 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2930 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2931 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2932 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2933 dc
.DrawRectangle(rect
);
2936 // draw the bitmap: use the bitmap provided or the standard checkmark for
2937 // the checkable items
2938 wxBitmap bmp
= bitmap
;
2939 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2941 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2946 rect
.SetRight(geometryInfo
.GetLabelOffset());
2947 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2951 rect
.x
= geometryInfo
.GetLabelOffset();
2952 rect
.SetRight(geometryInfo
.GetAccelOffset());
2954 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2956 // draw the accel string
2957 rect
.x
= geometryInfo
.GetAccelOffset();
2958 rect
.SetRight(geometryInfo
.GetSize().x
);
2960 // NB: no accel index here
2961 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2963 // draw the submenu indicator
2964 if ( flags
& wxCONTROL_ISSUBMENU
)
2966 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2967 rect
.width
= MENU_RIGHT_MARGIN
;
2969 wxArrowStyle arrowStyle
;
2970 if ( flags
& wxCONTROL_DISABLED
)
2971 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2973 else if ( flags
& wxCONTROL_SELECTED
)
2974 arrowStyle
= Arrow_Inversed
;
2976 arrowStyle
= Arrow_Normal
;
2978 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2982 void wxMetalRenderer::DrawMenuSeparator(wxDC
& dc
,
2984 const wxMenuGeometryInfo
& geomInfo
)
2986 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2989 wxSize
wxMetalRenderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2991 wxSize size
= sizeText
;
2993 // FIXME: menubar height is configurable under Windows
3000 wxMenuGeometryInfo
*wxMetalRenderer::GetMenuGeometry(wxWindow
*win
,
3001 const wxMenu
& menu
) const
3003 // prepare the dc: for now we draw all the items with the system font
3005 dc
.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
3007 // the height of a normal item
3008 wxCoord heightText
= dc
.GetCharHeight();
3013 // the max length of label and accel strings: the menu width is the sum of
3014 // them, even if they're for different items (as the accels should be
3017 // the max length of the bitmap is never 0 as Windows always leaves enough
3018 // space for a check mark indicator
3019 wxCoord widthLabelMax
= 0,
3021 widthBmpMax
= MENU_LEFT_MARGIN
;
3023 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
3025 node
= node
->GetNext() )
3027 // height of this item
3030 wxMenuItem
*item
= node
->GetData();
3031 if ( item
->IsSeparator() )
3033 h
= MENU_SEPARATOR_HEIGHT
;
3035 else // not separator
3040 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
3041 if ( widthLabel
> widthLabelMax
)
3043 widthLabelMax
= widthLabel
;
3047 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
3048 if ( widthAccel
> widthAccelMax
)
3050 widthAccelMax
= widthAccel
;
3053 const wxBitmap
& bmp
= item
->GetBitmap();
3056 wxCoord widthBmp
= bmp
.GetWidth();
3057 if ( widthBmp
> widthBmpMax
)
3058 widthBmpMax
= widthBmp
;
3060 //else if ( item->IsCheckable() ): no need to check for this as
3061 // MENU_LEFT_MARGIN is big enough to show the check mark
3064 h
+= 2*MENU_VERT_MARGIN
;
3066 // remember the item position and height
3067 item
->SetGeometry(height
, h
);
3072 // bundle the metrics into a struct and return it
3073 wxMetalMenuGeometryInfo
*gi
= new wxMetalMenuGeometryInfo
;
3075 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
3076 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
3077 if ( widthAccelMax
> 0 )
3079 // if we actually have any accesl, add a margin
3080 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
3083 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
3085 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
3086 gi
->m_size
.y
= height
;
3091 // ----------------------------------------------------------------------------
3093 // ----------------------------------------------------------------------------
3095 static const wxCoord STATBAR_BORDER_X
= 2;
3096 static const wxCoord STATBAR_BORDER_Y
= 2;
3098 wxSize
wxMetalRenderer::GetStatusBarBorders(wxCoord
*borderBetweenFields
) const
3100 if ( borderBetweenFields
)
3101 *borderBetweenFields
= 2;
3103 return wxSize(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3106 void wxMetalRenderer::DrawStatusField(wxDC
& dc
,
3108 const wxString
& label
,
3113 if ( flags
& wxCONTROL_ISDEFAULT
)
3115 // draw the size grip: it is a normal rect except that in the lower
3116 // right corner we have several bands which may be used for dragging
3117 // the status bar corner
3119 // each band consists of 4 stripes: m_penHighlight, double
3120 // m_penDarkGrey and transparent one
3121 wxCoord x2
= rect
.GetRight(),
3122 y2
= rect
.GetBottom();
3124 // draw the upper left part of the rect normally
3125 dc
.SetPen(m_penDarkGrey
);
3126 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(), rect
.GetLeft(), y2
);
3127 dc
.DrawLine(rect
.GetLeft() + 1, rect
.GetTop(), x2
, rect
.GetTop());
3129 // draw the grey stripes of the grip
3131 wxCoord ofs
= WIDTH_STATUSBAR_GRIP_BAND
- 1;
3132 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3134 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3135 dc
.DrawLine(x2
- ofs
, y2
- 1, x2
, y2
- ofs
- 1);
3138 // draw the white stripes
3139 dc
.SetPen(m_penHighlight
);
3140 ofs
= WIDTH_STATUSBAR_GRIP_BAND
+ 1;
3141 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3143 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3146 // draw the remaining rect boundaries
3147 ofs
-= WIDTH_STATUSBAR_GRIP_BAND
;
3148 dc
.DrawLine(x2
, rect
.GetTop(), x2
, y2
- ofs
+ 1);
3149 dc
.DrawLine(rect
.GetLeft(), y2
, x2
- ofs
+ 1, y2
);
3154 rectIn
.width
-= STATUSBAR_GRIP_SIZE
;
3158 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
3161 rectIn
.Deflate(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3163 wxDCClipper
clipper(dc
, rectIn
);
3164 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3167 // ----------------------------------------------------------------------------
3169 // ----------------------------------------------------------------------------
3171 void wxMetalRenderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
3173 wxBitmap
*bmpPressed
,
3174 wxBitmap
*bmpDisabled
)
3176 static const wxCoord widthCombo
= 16;
3177 static const wxCoord heightCombo
= 17;
3183 bmpNormal
->Create(widthCombo
, heightCombo
);
3184 dcMem
.SelectObject(*bmpNormal
);
3185 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3186 Arrow_Down
, Arrow_Normal
);
3191 bmpPressed
->Create(widthCombo
, heightCombo
);
3192 dcMem
.SelectObject(*bmpPressed
);
3193 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3194 Arrow_Down
, Arrow_Pressed
);
3199 bmpDisabled
->Create(widthCombo
, heightCombo
);
3200 dcMem
.SelectObject(*bmpDisabled
);
3201 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3202 Arrow_Down
, Arrow_Disabled
);
3206 // ----------------------------------------------------------------------------
3208 // ----------------------------------------------------------------------------
3210 void wxMetalRenderer::DoDrawBackground(wxDC
& dc
,
3211 const wxColour
& col
,
3214 dc
.SetPen(*wxTRANSPARENT_PEN
);
3215 if (col
== wxTheme::Get()->GetColourScheme()->Get( wxColourScheme::CONTROL
))
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 );
3226 wxBrush
brush(col
, wxSOLID
);
3228 dc
.DrawRectangle(rect
);
3232 void wxMetalRenderer::DrawBackground(wxDC
& dc
,
3233 const wxColour
& col
,
3237 // just fill it with the given or default bg colour
3238 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
3239 DoDrawBackground(dc
, colBg
, rect
);
3242 // ----------------------------------------------------------------------------
3244 // ----------------------------------------------------------------------------
3246 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
3251 // get the bitmap for this arrow
3252 wxArrowDirection arrowDir
;
3255 case wxLEFT
: arrowDir
= Arrow_Left
; break;
3256 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
3257 case wxUP
: arrowDir
= Arrow_Up
; break;
3258 case wxDOWN
: arrowDir
= Arrow_Down
; break;
3261 wxFAIL_MSG(_T("unknown arrow direction"));
3265 wxArrowStyle arrowStyle
;
3266 if ( flags
& wxCONTROL_PRESSED
)
3268 // can't be pressed and disabled
3269 arrowStyle
= Arrow_Pressed
;
3273 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
3276 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
3279 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
3281 wxArrowDirection arrowDir
,
3282 wxArrowStyle arrowStyle
)
3284 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
3286 // under Windows the arrows always have the same size so just centre it in
3287 // the provided rectangle
3288 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
3289 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
3291 // Windows does it like this...
3292 if ( arrowDir
== Arrow_Left
)
3296 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
3299 void wxMetalRenderer::DrawArrowButton(wxDC
& dc
,
3300 const wxRect
& rectAll
,
3301 wxArrowDirection arrowDir
,
3302 wxArrowStyle arrowStyle
)
3304 wxRect rect
= rectAll
;
3305 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3306 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
3307 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
3310 void wxMetalRenderer::DrawScrollbarThumb(wxDC
& dc
,
3311 wxOrientation orient
,
3315 // we don't use the flags, the thumb never changes appearance
3316 wxRect rectThumb
= rect
;
3317 DrawArrowBorder(dc
, &rectThumb
);
3318 DrawBackground(dc
, wxNullColour
, rectThumb
);
3321 void wxMetalRenderer::DrawScrollbarShaft(wxDC
& dc
,
3322 wxOrientation orient
,
3323 const wxRect
& rectBar
,
3326 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
3327 ? wxColourScheme::SCROLLBAR_PRESSED
3328 : wxColourScheme::SCROLLBAR
;
3329 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
3332 void wxMetalRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
3334 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3337 wxRect
wxMetalRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
3338 wxScrollBar::Element elem
,
3341 return StandardGetScrollbarRect(scrollbar
, elem
,
3342 thumbPos
, m_sizeScrollbarArrow
);
3345 wxCoord
wxMetalRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
3347 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
3350 wxHitTest
wxMetalRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
3351 const wxPoint
& pt
) const
3353 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
3356 wxCoord
wxMetalRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
3359 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
3362 int wxMetalRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
3365 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
3368 // ----------------------------------------------------------------------------
3369 // top level windows
3370 // ----------------------------------------------------------------------------
3372 int wxMetalRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
3374 wxRect client
= GetFrameClientArea(rect
, flags
);
3376 if ( client
.Inside(pt
) )
3377 return wxHT_TOPLEVEL_CLIENT_AREA
;
3379 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3381 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3383 if ( flags
& wxTOPLEVEL_ICON
)
3385 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Inside(pt
) )
3386 return wxHT_TOPLEVEL_ICON
;
3389 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
3390 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
3391 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3393 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3395 if ( btnRect
.Inside(pt
) )
3396 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
3397 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
3399 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3401 if ( btnRect
.Inside(pt
) )
3402 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
3403 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3405 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3407 if ( btnRect
.Inside(pt
) )
3408 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
3409 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3411 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3413 if ( btnRect
.Inside(pt
) )
3414 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
3415 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3417 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3419 if ( btnRect
.Inside(pt
) )
3420 return wxHT_TOPLEVEL_BUTTON_HELP
;
3421 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3424 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
3425 return wxHT_TOPLEVEL_TITLEBAR
;
3428 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3430 // we are certainly at one of borders, lets decide which one:
3433 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3434 if ( pt
.x
< client
.x
)
3435 border
|= wxHT_TOPLEVEL_BORDER_W
;
3436 else if ( pt
.x
>= client
.width
+ client
.x
)
3437 border
|= wxHT_TOPLEVEL_BORDER_E
;
3438 if ( pt
.y
< client
.y
)
3439 border
|= wxHT_TOPLEVEL_BORDER_N
;
3440 else if ( pt
.y
>= client
.height
+ client
.y
)
3441 border
|= wxHT_TOPLEVEL_BORDER_S
;
3445 return wxHT_NOWHERE
;
3448 void wxMetalRenderer::DrawFrameTitleBar(wxDC
& dc
,
3450 const wxString
& title
,
3454 int specialButtonFlags
)
3456 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3458 DrawFrameBorder(dc
, rect
, flags
);
3460 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3462 DrawFrameBackground(dc
, rect
, flags
);
3463 if ( flags
& wxTOPLEVEL_ICON
)
3464 DrawFrameIcon(dc
, rect
, icon
, flags
);
3465 DrawFrameTitle(dc
, rect
, title
, flags
);
3467 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3469 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
3470 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
3472 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3474 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
3475 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
3476 specialButtonFlags
: 0);
3477 x
-= FRAME_BUTTON_WIDTH
+ 2;
3479 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3481 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
3482 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
3483 specialButtonFlags
: 0);
3484 x
-= FRAME_BUTTON_WIDTH
;
3486 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3488 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
3489 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
3490 specialButtonFlags
: 0);
3491 x
-= FRAME_BUTTON_WIDTH
;
3493 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3495 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
3496 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
3497 specialButtonFlags
: 0);
3498 x
-= FRAME_BUTTON_WIDTH
;
3500 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3502 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
3503 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
3504 specialButtonFlags
: 0);
3505 x
-= FRAME_BUTTON_WIDTH
;
3510 void wxMetalRenderer::DrawFrameBorder(wxDC
& dc
,
3514 if ( !(flags
& wxTOPLEVEL_BORDER
) ) return;
3518 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penBlack
);
3519 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penDarkGrey
);
3520 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3521 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
3522 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3525 void wxMetalRenderer::DrawFrameBackground(wxDC
& dc
,
3529 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) ) return;
3531 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3532 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE
) :
3533 wxSCHEME_COLOUR(m_scheme
, TITLEBAR
);
3535 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3536 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3538 DrawBackground(dc
, col
, r
);
3541 void wxMetalRenderer::DrawFrameTitle(wxDC
& dc
,
3543 const wxString
& title
,
3546 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3547 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE_TEXT
) :
3548 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_TEXT
);
3550 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3551 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3552 if ( flags
& wxTOPLEVEL_ICON
)
3554 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
3555 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
3563 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3564 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
3565 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3566 r
.width
-= FRAME_BUTTON_WIDTH
;
3567 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3568 r
.width
-= FRAME_BUTTON_WIDTH
;
3569 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3570 r
.width
-= FRAME_BUTTON_WIDTH
;
3571 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3572 r
.width
-= FRAME_BUTTON_WIDTH
;
3574 dc
.SetFont(m_titlebarFont
);
3575 dc
.SetTextForeground(col
);
3578 dc
.GetTextExtent(title
, &textW
, NULL
);
3579 if ( textW
> r
.width
)
3581 // text is too big, let's shorten it and add "..." after it:
3582 size_t len
= title
.length();
3583 wxCoord WSoFar
, letterW
;
3585 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
3586 if ( WSoFar
> r
.width
)
3588 // not enough space to draw anything
3594 for (size_t i
= 0; i
< len
; i
++)
3596 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
3597 if ( letterW
+ WSoFar
> r
.width
)
3603 dc
.DrawLabel(s
, wxNullBitmap
, r
,
3604 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3607 dc
.DrawLabel(title
, wxNullBitmap
, r
,
3608 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3611 void wxMetalRenderer::DrawFrameIcon(wxDC
& dc
,
3618 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3619 dc
.DrawIcon(icon
, r
.x
, r
.y
);
3623 void wxMetalRenderer::DrawFrameButton(wxDC
& dc
,
3624 wxCoord x
, wxCoord y
,
3628 wxRect
r(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3633 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
3634 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
3635 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
3636 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
3637 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
3639 wxFAIL_MSG(wxT("incorrect button specification"));
3642 if ( flags
& wxCONTROL_PRESSED
)
3644 DrawShadedRect(dc
, &r
, m_penBlack
, m_penHighlight
);
3645 DrawShadedRect(dc
, &r
, m_penDarkGrey
, m_penLightGrey
);
3646 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3647 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
+1, r
.y
+1, TRUE
);
3651 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penBlack
);
3652 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penDarkGrey
);
3653 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3654 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
, r
.y
, TRUE
);
3659 wxRect
wxMetalRenderer::GetFrameClientArea(const wxRect
& rect
,
3664 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3666 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3667 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3668 FRAME_BORDER_THICKNESS
;
3671 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3673 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
3674 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
3680 wxSize
wxMetalRenderer::GetFrameTotalSize(const wxSize
& clientSize
,
3683 wxSize
s(clientSize
);
3685 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3687 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3688 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3689 FRAME_BORDER_THICKNESS
;
3693 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3694 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3699 wxSize
wxMetalRenderer::GetFrameMinSize(int flags
) const
3703 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3705 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3706 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3707 FRAME_BORDER_THICKNESS
;
3712 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3714 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3716 if ( flags
& wxTOPLEVEL_ICON
)
3717 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
3718 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3719 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
3720 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3721 s
.x
+= FRAME_BUTTON_WIDTH
;
3722 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3723 s
.x
+= FRAME_BUTTON_WIDTH
;
3724 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3725 s
.x
+= FRAME_BUTTON_WIDTH
;
3726 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3727 s
.x
+= FRAME_BUTTON_WIDTH
;
3733 wxSize
wxMetalRenderer::GetFrameIconSize() const
3735 return wxSize(16, 16);
3739 // ----------------------------------------------------------------------------
3741 // ----------------------------------------------------------------------------
3743 static char *error_xpm
[]={
3750 "...........########.............",
3751 "........###aaaaaaaa###..........",
3752 ".......#aaaaaaaaaaaaaa#.........",
3753 ".....##aaaaaaaaaaaaaaaa##.......",
3754 "....#aaaaaaaaaaaaaaaaaaaa#......",
3755 "...#aaaaaaaaaaaaaaaaaaaaaa#.....",
3756 "...#aaaaaaaaaaaaaaaaaaaaaa#b....",
3757 "..#aaaaaacaaaaaaaaaacaaaaaa#b...",
3758 ".#aaaaaacccaaaaaaaacccaaaaaa#...",
3759 ".#aaaaacccccaaaaaacccccaaaaa#b..",
3760 ".#aaaaaacccccaaaacccccaaaaaa#bb.",
3761 "#aaaaaaaacccccaacccccaaaaaaaa#b.",
3762 "#aaaaaaaaaccccccccccaaaaaaaaa#b.",
3763 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3764 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3765 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3766 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3767 "#aaaaaaaaaccccccccccaaaaaaaaa#bb",
3768 "#aaaaaaaacccccaacccccaaaaaaaa#bb",
3769 ".#aaaaaacccccaaaacccccaaaaaa#bbb",
3770 ".#aaaaacccccaaaaaacccccaaaaa#bbb",
3771 ".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
3772 "..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
3773 "...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
3774 "...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
3775 "....#aaaaaaaaaaaaaaaaaaaa#bbb...",
3776 ".....##aaaaaaaaaaaaaaaa##bbbb...",
3777 "......b#aaaaaaaaaaaaaa#bbbbb....",
3778 ".......b###aaaaaaaa###bbbbb.....",
3779 ".........bb########bbbbbb.......",
3780 "..........bbbbbbbbbbbbbb........",
3781 ".............bbbbbbbb..........."};
3783 static char *info_xpm
[]={
3791 "...........########.............",
3792 "........###abbbbbba###..........",
3793 "......##abbbbbbbbbbbba##........",
3794 ".....#abbbbbbbbbbbbbbbba#.......",
3795 "....#bbbbbbbaccccabbbbbbbd......",
3796 "...#bbbbbbbbccccccbbbbbbbbd.....",
3797 "..#bbbbbbbbbccccccbbbbbbbbbd....",
3798 ".#abbbbbbbbbaccccabbbbbbbbbad...",
3799 ".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
3800 "#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
3801 "#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
3802 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3803 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3804 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3805 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3806 "#abbbbbbbbbbbcccccbbbbbbbbbbad##",
3807 ".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
3808 ".#abbbbbbbbbbcccccbbbbbbbbbad###",
3809 "..#bbbbbbbbcccccccccbbbbbbbd###.",
3810 "...dbbbbbbbbbbbbbbbbbbbbbbd####.",
3811 "....dbbbbbbbbbbbbbbbbbbbbd####..",
3812 ".....dabbbbbbbbbbbbbbbbad####...",
3813 "......ddabbbbbbbbbbbbadd####....",
3814 ".......#dddabbbbbbaddd#####.....",
3815 "........###dddabbbd#######......",
3816 "..........####dbbbd#####........",
3817 ".............#dbbbd##...........",
3818 "...............dbbd##...........",
3819 "................dbd##...........",
3820 ".................dd##...........",
3821 "..................###...........",
3822 "...................##..........."};
3824 static char *question_xpm
[]={
3832 "...........########.............",
3833 "........###abbbbbba###..........",
3834 "......##abbbbbbbbbbbba##........",
3835 ".....#abbbbbbbbbbbbbbbba#.......",
3836 "....#bbbbbbbbbbbbbbbbbbbbc......",
3837 "...#bbbbbbbaddddddabbbbbbbc.....",
3838 "..#bbbbbbbadabbddddabbbbbbbc....",
3839 ".#abbbbbbbddbbbbddddbbbbbbbac...",
3840 ".#bbbbbbbbddddbbddddbbbbbbbbc#..",
3841 "#abbbbbbbbddddbaddddbbbbbbbbac#.",
3842 "#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
3843 "#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
3844 "#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
3845 "#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
3846 "#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
3847 "#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
3848 ".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
3849 ".#abbbbbbbbbbddddbbbbbbbbbbac###",
3850 "..#bbbbbbbbbbddddbbbbbbbbbbc###.",
3851 "...cbbbbbbbbbaddabbbbbbbbbc####.",
3852 "....cbbbbbbbbbbbbbbbbbbbbc####..",
3853 ".....cabbbbbbbbbbbbbbbbac####...",
3854 "......ccabbbbbbbbbbbbacc####....",
3855 ".......#cccabbbbbbaccc#####.....",
3856 "........###cccabbbc#######......",
3857 "..........####cbbbc#####........",
3858 ".............#cbbbc##...........",
3859 "...............cbbc##...........",
3860 "................cbc##...........",
3861 ".................cc##...........",
3862 "..................###...........",
3863 "...................##..........."};
3865 static char *warning_xpm
[]={
3873 ".............###................",
3874 "............#aabc...............",
3875 "...........#aaaabcd.............",
3876 "...........#aaaaacdd............",
3877 "..........#aaaaaabcdd...........",
3878 "..........#aaaaaaacdd...........",
3879 ".........#aaaaaaaabcdd..........",
3880 ".........#aaaaaaaaacdd..........",
3881 "........#aaaaaaaaaabcdd.........",
3882 "........#aaabcccbaaacdd.........",
3883 ".......#aaaacccccaaabcdd........",
3884 ".......#aaaacccccaaaacdd........",
3885 "......#aaaaacccccaaaabcdd.......",
3886 "......#aaaaacccccaaaaacdd.......",
3887 ".....#aaaaaacccccaaaaabcdd......",
3888 ".....#aaaaaa#ccc#aaaaaacdd......",
3889 "....#aaaaaaabcccbaaaaaabcdd.....",
3890 "....#aaaaaaaacccaaaaaaaacdd.....",
3891 "...#aaaaaaaaa#c#aaaaaaaabcdd....",
3892 "...#aaaaaaaaabcbaaaaaaaaacdd....",
3893 "..#aaaaaaaaaaacaaaaaaaaaabcdd...",
3894 "..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
3895 ".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
3896 ".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
3897 "#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
3898 "#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
3899 "#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
3900 "#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
3901 ".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
3902 "..#ccccccccccccccccccccccccddddd",
3903 "....ddddddddddddddddddddddddddd.",
3904 ".....ddddddddddddddddddddddddd.."};
3906 wxBitmap
wxMetalArtProvider::CreateBitmap(const wxArtID
& id
,
3907 const wxArtClient
& WXUNUSED(client
),
3908 const wxSize
& WXUNUSED(size
))
3910 if ( id
== wxART_INFORMATION
)
3911 return wxBitmap(info_xpm
);
3912 if ( id
== wxART_ERROR
)
3913 return wxBitmap(error_xpm
);
3914 if ( id
== wxART_WARNING
)
3915 return wxBitmap(warning_xpm
);
3916 if ( id
== wxART_QUESTION
)
3917 return wxBitmap(question_xpm
);
3918 return wxNullBitmap
;
3922 // ----------------------------------------------------------------------------
3923 // text control geometry
3924 // ----------------------------------------------------------------------------
3926 static inline int GetTextBorderWidth()
3931 wxRect
wxMetalRenderer::GetTextTotalArea(const wxTextCtrl
*text
,
3932 const wxRect
& rect
) const
3934 wxRect rectTotal
= rect
;
3936 wxCoord widthBorder
= GetTextBorderWidth();
3937 rectTotal
.Inflate(widthBorder
);
3939 // this is what Windows does
3945 wxRect
wxMetalRenderer::GetTextClientArea(const wxTextCtrl
*text
,
3947 wxCoord
*extraSpaceBeyond
) const
3949 wxRect rectText
= rect
;
3951 // undo GetTextTotalArea()
3952 if ( rectText
.height
> 0 )
3955 wxCoord widthBorder
= GetTextBorderWidth();
3956 rectText
.Inflate(-widthBorder
);
3958 if ( extraSpaceBeyond
)
3959 *extraSpaceBeyond
= 0;
3964 // ----------------------------------------------------------------------------
3966 // ----------------------------------------------------------------------------
3968 void wxMetalRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
3971 if ( wxDynamicCast(window
, wxScrollBar
) )
3973 // we only set the width of vert scrollbars and height of the
3975 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3976 size
->y
= m_sizeScrollbarArrow
.y
;
3978 size
->x
= m_sizeScrollbarArrow
.x
;
3980 // skip border width adjustments, they don't make sense for us
3983 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3986 if ( wxDynamicCast(window
, wxButton
) )
3988 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
3990 // TODO: don't harcode all this
3991 size
->x
+= 3*window
->GetCharWidth();
3993 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
3994 if ( size
->y
< heightBtn
- 8 )
3995 size
->y
= heightBtn
;
4000 // no border width adjustments for buttons
4003 #endif // wxUSE_BUTTON
4005 // take into account the border width
4006 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
4007 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
4008 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
4011 // ============================================================================
4013 // ============================================================================
4015 // ----------------------------------------------------------------------------
4016 // wxMetalInputHandler
4017 // ----------------------------------------------------------------------------
4019 wxMetalInputHandler::wxMetalInputHandler(wxMetalRenderer
*renderer
)
4021 m_renderer
= renderer
;
4024 bool wxMetalInputHandler::HandleKey(wxInputConsumer
*control
,
4025 const wxKeyEvent
& event
,
4031 bool wxMetalInputHandler::HandleMouse(wxInputConsumer
*control
,
4032 const wxMouseEvent
& event
)
4034 // clicking on the control gives it focus
4035 if ( event
.ButtonDown() )
4037 wxWindow
*win
= control
->GetInputWindow();
4039 if (( wxWindow::FindFocus() != control
->GetInputWindow() ) &&
4040 ( win
->AcceptsFocus() ) )
4051 // ----------------------------------------------------------------------------
4052 // wxMetalScrollBarInputHandler
4053 // ----------------------------------------------------------------------------
4055 wxMetalScrollBarInputHandler::
4056 wxMetalScrollBarInputHandler(wxMetalRenderer
*renderer
,
4057 wxInputHandler
*handler
)
4058 : wxStdScrollBarInputHandler(renderer
, handler
)
4060 m_scrollPaused
= FALSE
;
4064 bool wxMetalScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
4065 const wxControlAction
& action
)
4067 // stop if went beyond the position of the original click (this can only
4068 // happen when we scroll by pages)
4070 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
4072 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4073 != wxHT_SCROLLBAR_BAR_2
;
4075 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
4077 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4078 != wxHT_SCROLLBAR_BAR_1
;
4083 StopScrolling(scrollbar
);
4085 scrollbar
->Refresh();
4090 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
4093 bool wxMetalScrollBarInputHandler::HandleMouse(wxInputConsumer
*control
,
4094 const wxMouseEvent
& event
)
4096 // remember the current state
4097 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
4099 // do process the message
4100 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
4102 // analyse the changes
4103 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
4105 // we just started dragging the thumb, remember its initial position to
4106 // be able to restore it if the drag is cancelled later
4107 m_eventStartDrag
= event
;
4113 bool wxMetalScrollBarInputHandler::HandleMouseMove(wxInputConsumer
*control
,
4114 const wxMouseEvent
& event
)
4116 // we don't highlight scrollbar elements, so there is no need to process
4117 // mouse move events normally - only do it while mouse is captured (i.e.
4118 // when we're dragging the thumb or pressing on something)
4119 if ( !m_winCapture
)
4122 if ( event
.Entering() )
4124 // we're not interested in this at all
4128 wxScrollBar
*scrollbar
= wxStaticCast(control
->GetInputWindow(), wxScrollBar
);
4130 if ( m_scrollPaused
)
4132 // check if the mouse returned to its original location
4134 if ( event
.Leaving() )
4140 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4141 if ( ht
== m_htLast
)
4143 // yes it did, resume scrolling
4144 m_scrollPaused
= FALSE
;
4145 if ( m_timerScroll
)
4147 // we were scrolling by line/page, restart timer
4148 m_timerScroll
->Start(m_interval
);
4150 Press(scrollbar
, TRUE
);
4152 else // we were dragging the thumb
4154 // restore its last location
4155 HandleThumbMove(scrollbar
, m_eventLastDrag
);
4161 else // normal case, scrolling hasn't been paused
4163 // if we're scrolling the scrollbar because the arrow or the shaft was
4164 // pressed, check that the mouse stays on the same scrollbar element
4167 // Always let thumb jump back if we leave the scrollbar
4168 if ( event
.Moving() )
4170 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4172 else // event.Leaving()
4177 // Jump back only if we get far away from it
4178 wxPoint pos
= event
.GetPosition();
4179 if (scrollbar
->HasFlag( wxVERTICAL
))
4181 if (pos
.x
> -40 && pos
.x
< scrollbar
->GetSize().x
+40)
4186 if (pos
.y
> -40 && pos
.y
< scrollbar
->GetSize().y
+40)
4189 ht
= m_renderer
->HitTestScrollbar(scrollbar
, pos
);
4192 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4193 // is still ok - we only want to catch the case when the mouse leaves
4194 // the scrollbar here
4195 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
4197 ht
= wxHT_SCROLLBAR_THUMB
;
4200 if ( ht
!= m_htLast
)
4202 // what were we doing? 2 possibilities: either an arrow/shaft was
4203 // pressed in which case we have a timer and so we just stop it or
4204 // we were dragging the thumb
4205 if ( m_timerScroll
)
4208 m_interval
= m_timerScroll
->GetInterval();
4209 m_timerScroll
->Stop();
4210 m_scrollPaused
= TRUE
;
4212 // unpress the arrow
4213 Press(scrollbar
, FALSE
);
4215 else // we were dragging the thumb
4217 // remember the current thumb position to be able to restore it
4218 // if the mouse returns to it later
4219 m_eventLastDrag
= event
;
4221 // and restore the original position (before dragging) of the
4223 HandleThumbMove(scrollbar
, m_eventStartDrag
);
4230 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
4233 // ----------------------------------------------------------------------------
4234 // wxMetalCheckboxInputHandler
4235 // ----------------------------------------------------------------------------
4237 bool wxMetalCheckboxInputHandler::HandleKey(wxInputConsumer
*control
,
4238 const wxKeyEvent
& event
,
4243 wxControlAction action
;
4244 int keycode
= event
.GetKeyCode();
4248 action
= wxACTION_CHECKBOX_TOGGLE
;
4252 case WXK_NUMPAD_SUBTRACT
:
4253 action
= wxACTION_CHECKBOX_CHECK
;
4257 case WXK_NUMPAD_ADD
:
4258 case WXK_NUMPAD_EQUAL
:
4259 action
= wxACTION_CHECKBOX_CLEAR
;
4265 control
->PerformAction(action
);
4274 // ----------------------------------------------------------------------------
4275 // wxMetalTextCtrlInputHandler
4276 // ----------------------------------------------------------------------------
4278 bool wxMetalTextCtrlInputHandler::HandleKey(wxInputConsumer
*control
,
4279 const wxKeyEvent
& event
,
4282 // handle only MSW-specific text bindings here, the others are handled in
4286 int keycode
= event
.GetKeyCode();
4288 wxControlAction action
;
4289 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
4291 action
= wxACTION_TEXT_CUT
;
4293 else if ( keycode
== WXK_INSERT
)
4295 if ( event
.ControlDown() )
4296 action
= wxACTION_TEXT_COPY
;
4297 else if ( event
.ShiftDown() )
4298 action
= wxACTION_TEXT_PASTE
;
4301 if ( action
!= wxACTION_NONE
)
4303 control
->PerformAction(action
);
4309 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);
4312 // ----------------------------------------------------------------------------
4313 // wxMetalStatusBarInputHandler
4314 // ----------------------------------------------------------------------------
4316 wxMetalStatusBarInputHandler::
4317 wxMetalStatusBarInputHandler(wxInputHandler
*handler
)
4318 : wxStdInputHandler(handler
)
4323 bool wxMetalStatusBarInputHandler::IsOnGrip(wxWindow
*statbar
,
4324 const wxPoint
& pt
) const
4326 if ( statbar
->HasFlag(wxST_SIZEGRIP
) &&
4327 statbar
->GetParent()->HasFlag(wxRESIZE_BORDER
) )
4330 parentTLW
= wxDynamicCast(statbar
->GetParent(), wxTopLevelWindow
);
4332 wxCHECK_MSG( parentTLW
, FALSE
,
4333 _T("the status bar should be a child of a TLW") );
4335 // a maximized window can't be resized anyhow
4336 if ( !parentTLW
->IsMaximized() )
4338 // VZ: I think that the standard Windows behaviour is to only
4339 // show the resizing cursor when the mouse is on top of the
4340 // grip itself but apparently different Windows versions behave
4341 // differently (?) and it seems a better UI to allow resizing
4342 // the status bar even when the mouse is above the grip
4343 wxSize sizeSbar
= statbar
->GetSize();
4345 int diff
= sizeSbar
.x
- pt
.x
;
4346 return diff
>= 0 && diff
< (wxCoord
)STATUSBAR_GRIP_SIZE
;
4353 bool wxMetalStatusBarInputHandler::HandleMouse(wxInputConsumer
*consumer
,
4354 const wxMouseEvent
& event
)
4356 if ( event
.Button(1) )
4358 if ( event
.ButtonDown(1) )
4360 wxWindow
*statbar
= consumer
->GetInputWindow();
4362 if ( IsOnGrip(statbar
, event
.GetPosition()) )
4364 wxTopLevelWindow
*tlw
= wxDynamicCast(statbar
->GetParent(),
4368 tlw
->PerformAction(wxACTION_TOPLEVEL_RESIZE
,
4369 wxHT_TOPLEVEL_BORDER_SE
);
4371 statbar
->SetCursor(m_cursorOld
);
4379 return wxStdInputHandler::HandleMouse(consumer
, event
);
4382 bool wxMetalStatusBarInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
4383 const wxMouseEvent
& event
)
4385 wxWindow
*statbar
= consumer
->GetInputWindow();
4387 bool isOnGrip
= IsOnGrip(statbar
, event
.GetPosition());
4388 if ( isOnGrip
!= m_isOnGrip
)
4390 m_isOnGrip
= isOnGrip
;
4393 m_cursorOld
= statbar
->GetCursor();
4394 statbar
->SetCursor(wxCURSOR_SIZENWSE
);
4398 statbar
->SetCursor(m_cursorOld
);
4402 return wxStdInputHandler::HandleMouseMove(consumer
, event
);
4405 // ----------------------------------------------------------------------------
4406 // wxMetalFrameInputHandler
4407 // ----------------------------------------------------------------------------
4409 class wxMetalSystemMenuEvtHandler
: public wxEvtHandler
4412 wxMetalSystemMenuEvtHandler(wxMetalFrameInputHandler
*handler
);
4414 void Attach(wxInputConsumer
*consumer
);
4418 DECLARE_EVENT_TABLE()
4419 void OnSystemMenu(wxCommandEvent
&event
);
4420 void OnCloseFrame(wxCommandEvent
&event
);
4421 void OnClose(wxCloseEvent
&event
);
4423 wxMetalFrameInputHandler
*m_inputHnd
;
4424 wxTopLevelWindow
*m_wnd
;
4425 wxAcceleratorTable m_oldAccelTable
;
4428 wxMetalSystemMenuEvtHandler::wxMetalSystemMenuEvtHandler(
4429 wxMetalFrameInputHandler
*handler
)
4431 m_inputHnd
= handler
;
4435 void wxMetalSystemMenuEvtHandler::Attach(wxInputConsumer
*consumer
)
4437 wxASSERT_MSG( m_wnd
== NULL
, _T("can't attach the handler twice!") );
4439 m_wnd
= wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4440 m_wnd
->PushEventHandler(this);
4442 // VS: This code relies on using generic implementation of
4443 // wxAcceleratorTable in wxUniv!
4444 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4445 m_oldAccelTable
= table
;
4446 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_SPACE
, wxID_SYSTEM_MENU
));
4447 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_F4
, wxID_CLOSE_FRAME
));
4448 m_wnd
->SetAcceleratorTable(table
);
4451 void wxMetalSystemMenuEvtHandler::Detach()
4455 m_wnd
->SetAcceleratorTable(m_oldAccelTable
);
4456 m_wnd
->RemoveEventHandler(this);
4461 BEGIN_EVENT_TABLE(wxMetalSystemMenuEvtHandler
, wxEvtHandler
)
4462 EVT_MENU(wxID_SYSTEM_MENU
, wxMetalSystemMenuEvtHandler::OnSystemMenu
)
4463 EVT_MENU(wxID_CLOSE_FRAME
, wxMetalSystemMenuEvtHandler::OnCloseFrame
)
4464 EVT_CLOSE(wxMetalSystemMenuEvtHandler::OnClose
)
4467 void wxMetalSystemMenuEvtHandler::OnSystemMenu(wxCommandEvent
&WXUNUSED(event
))
4469 int border
= ((m_wnd
->GetWindowStyle() & wxRESIZE_BORDER
) &&
4470 !m_wnd
->IsMaximized()) ?
4471 RESIZEABLE_FRAME_BORDER_THICKNESS
:
4472 FRAME_BORDER_THICKNESS
;
4473 wxPoint pt
= m_wnd
->GetClientAreaOrigin();
4474 pt
.x
= -pt
.x
+ border
;
4475 pt
.y
= -pt
.y
+ border
+ FRAME_TITLEBAR_HEIGHT
;
4477 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4478 m_wnd
->SetAcceleratorTable(wxNullAcceleratorTable
);
4479 m_inputHnd
->PopupSystemMenu(m_wnd
, pt
);
4480 m_wnd
->SetAcceleratorTable(table
);
4483 void wxMetalSystemMenuEvtHandler::OnCloseFrame(wxCommandEvent
&WXUNUSED(event
))
4485 m_wnd
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4486 wxTOPLEVEL_BUTTON_CLOSE
);
4489 void wxMetalSystemMenuEvtHandler::OnClose(wxCloseEvent
&event
)
4496 wxMetalFrameInputHandler::wxMetalFrameInputHandler(wxInputHandler
*handler
)
4497 : wxStdFrameInputHandler(handler
)
4499 m_menuHandler
= new wxMetalSystemMenuEvtHandler(this);
4502 wxMetalFrameInputHandler::~wxMetalFrameInputHandler()
4504 if ( m_menuHandler
)
4506 m_menuHandler
->Detach();
4507 delete m_menuHandler
;
4511 bool wxMetalFrameInputHandler::HandleMouse(wxInputConsumer
*consumer
,
4512 const wxMouseEvent
& event
)
4514 if ( event
.LeftDClick() || event
.LeftDown() || event
.RightDown() )
4516 wxTopLevelWindow
*tlw
=
4517 wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4519 long hit
= tlw
->HitTest(event
.GetPosition());
4521 if ( event
.LeftDClick() && hit
== wxHT_TOPLEVEL_TITLEBAR
)
4523 tlw
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4524 tlw
->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4525 : wxTOPLEVEL_BUTTON_MAXIMIZE
);
4528 else if ( tlw
->GetWindowStyle() & wxSYSTEM_MENU
)
4530 if ( (event
.LeftDown() && hit
== wxHT_TOPLEVEL_ICON
) ||
4531 (event
.RightDown() &&
4532 (hit
== wxHT_TOPLEVEL_TITLEBAR
||
4533 hit
== wxHT_TOPLEVEL_ICON
)) )
4535 PopupSystemMenu(tlw
, event
.GetPosition());
4541 return wxStdFrameInputHandler::HandleMouse(consumer
, event
);
4544 void wxMetalFrameInputHandler::PopupSystemMenu(wxTopLevelWindow
*window
,
4545 const wxPoint
& pos
) const
4547 wxMenu
*menu
= new wxMenu
;
4549 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4550 menu
->Append(wxID_RESTORE_FRAME
, _("&Restore"));
4551 menu
->Append(wxID_MOVE_FRAME
, _("&Move"));
4552 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4553 menu
->Append(wxID_RESIZE_FRAME
, _("&Size"));
4554 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME
) )
4555 menu
->Append(wxID_ICONIZE_FRAME
, _("Mi&nimize"));
4556 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4557 menu
->Append(wxID_MAXIMIZE_FRAME
, _("Ma&ximize"));
4558 menu
->AppendSeparator();
4559 menu
->Append(wxID_CLOSE_FRAME
, _("Close\tAlt-F4"));
4561 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4563 if ( window
->IsMaximized() )
4565 menu
->Enable(wxID_MAXIMIZE_FRAME
, FALSE
);
4566 menu
->Enable(wxID_MOVE_FRAME
, FALSE
);
4567 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4568 menu
->Enable(wxID_RESIZE_FRAME
, FALSE
);
4571 menu
->Enable(wxID_RESTORE_FRAME
, FALSE
);
4574 window
->PopupMenu(menu
, pos
);
4578 bool wxMetalFrameInputHandler::HandleActivation(wxInputConsumer
*consumer
,
4581 if ( consumer
->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU
)
4583 // always detach if active frame changed:
4584 m_menuHandler
->Detach();
4588 m_menuHandler
->Attach(consumer
);
4592 return wxStdFrameInputHandler::HandleActivation(consumer
, activated
);