1 // Name: univ/themes/metal.cpp
2 // Purpose: wxUniversal theme implementing Win32-like LNF
3 // Author: Vadim Zeitlin, Robert Roebling
7 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows license
9 ///////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
30 #include "wx/window.h"
32 #include "wx/dcmemory.h"
34 #include "wx/button.h"
35 #include "wx/listbox.h"
36 #include "wx/checklst.h"
37 #include "wx/combobox.h"
38 #include "wx/scrolbar.h"
39 #include "wx/slider.h"
40 #include "wx/textctrl.h"
41 #include "wx/toolbar.h"
44 // for COLOR_* constants
45 #include "wx/msw/private.h"
49 #include "wx/notebook.h"
50 #include "wx/spinbutt.h"
51 #include "wx/settings.h"
53 #include "wx/artprov.h"
54 #include "wx/toplevel.h"
56 #include "wx/univ/scrtimer.h"
57 #include "wx/univ/renderer.h"
58 #include "wx/univ/inphand.h"
59 #include "wx/univ/colschem.h"
60 #include "wx/univ/theme.h"
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 static const int BORDER_THICKNESS
= 2;
68 // the offset between the label and focus rect around it
69 static const int FOCUS_RECT_OFFSET_X
= 1;
70 static const int FOCUS_RECT_OFFSET_Y
= 1;
72 static const int FRAME_BORDER_THICKNESS
= 3;
73 static const int RESIZEABLE_FRAME_BORDER_THICKNESS
= 4;
74 static const int FRAME_TITLEBAR_HEIGHT
= 18;
75 static const int FRAME_BUTTON_WIDTH
= 16;
76 static const int FRAME_BUTTON_HEIGHT
= 14;
78 static const size_t NUM_STATUSBAR_GRIP_BANDS
= 3;
79 static const size_t WIDTH_STATUSBAR_GRIP_BAND
= 4;
80 static const size_t STATUSBAR_GRIP_SIZE
=
81 WIDTH_STATUSBAR_GRIP_BAND
*NUM_STATUSBAR_GRIP_BANDS
;
93 IndicatorState_Normal
,
94 IndicatorState_Pressed
, // this one is for check/radioboxes
95 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
96 IndicatorState_Disabled
,
97 IndicatorState_SelectedDisabled
, // only for the menus
103 IndicatorStatus_Checked
,
104 IndicatorStatus_Unchecked
,
108 // wxMetalRenderer: draw the GUI elements in Metal style
109 // ----------------------------------------------------------------------------
111 class wxMetalRenderer
: public wxRenderer
115 enum wxArrowDirection
130 Arrow_InversedDisabled
,
134 enum wxFrameButtonType
137 FrameButton_Minimize
,
138 FrameButton_Maximize
,
145 wxMetalRenderer(const wxColourScheme
*scheme
);
148 void DrawMetal(wxDC
&dc
, const wxRect
&rect
);
150 // implement the base class pure virtuals
151 virtual void DrawBackground(wxDC
& dc
,
155 wxWindow
*window
= NULL
);
156 virtual void DrawButtonSurface(wxDC
& dc
,
160 virtual void DrawLabel(wxDC
& dc
,
161 const wxString
& label
,
164 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
166 wxRect
*rectBounds
= NULL
);
167 virtual void DrawButtonLabel(wxDC
& dc
,
168 const wxString
& label
,
169 const wxBitmap
& image
,
172 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
174 wxRect
*rectBounds
= NULL
);
175 virtual void DrawBorder(wxDC
& dc
,
179 wxRect
*rectIn
= (wxRect
*)NULL
);
180 virtual void DrawHorizontalLine(wxDC
& dc
,
181 wxCoord y
, wxCoord x1
, wxCoord x2
);
182 virtual void DrawVerticalLine(wxDC
& dc
,
183 wxCoord x
, wxCoord y1
, wxCoord y2
);
184 virtual void DrawFrame(wxDC
& dc
,
185 const wxString
& label
,
188 int alignment
= wxALIGN_LEFT
,
189 int indexAccel
= -1);
190 virtual void DrawTextBorder(wxDC
& dc
,
194 wxRect
*rectIn
= (wxRect
*)NULL
);
195 virtual void DrawButtonBorder(wxDC
& dc
,
198 wxRect
*rectIn
= (wxRect
*)NULL
);
199 virtual void DrawArrow(wxDC
& dc
,
203 virtual void DrawScrollbarArrow(wxDC
& dc
,
207 { DrawArrow(dc
, dir
, rect
, flags
); }
208 virtual void DrawScrollbarThumb(wxDC
& dc
,
209 wxOrientation orient
,
212 virtual void DrawScrollbarShaft(wxDC
& dc
,
213 wxOrientation orient
,
216 virtual void DrawScrollCorner(wxDC
& dc
,
218 virtual void DrawItem(wxDC
& dc
,
219 const wxString
& label
,
222 virtual void DrawCheckItem(wxDC
& dc
,
223 const wxString
& label
,
224 const wxBitmap
& bitmap
,
227 virtual void DrawCheckButton(wxDC
& dc
,
228 const wxString
& label
,
229 const wxBitmap
& bitmap
,
232 wxAlignment align
= wxALIGN_LEFT
,
233 int indexAccel
= -1);
234 virtual void DrawRadioButton(wxDC
& dc
,
235 const wxString
& label
,
236 const wxBitmap
& bitmap
,
239 wxAlignment align
= wxALIGN_LEFT
,
240 int indexAccel
= -1);
241 virtual void DrawToolBarButton(wxDC
& dc
,
242 const wxString
& label
,
243 const wxBitmap
& bitmap
,
246 virtual void DrawTextLine(wxDC
& dc
,
247 const wxString
& text
,
252 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
253 virtual void DrawTab(wxDC
& dc
,
256 const wxString
& label
,
257 const wxBitmap
& bitmap
= wxNullBitmap
,
259 int indexAccel
= -1);
261 virtual void DrawSliderShaft(wxDC
& dc
,
263 wxOrientation orient
,
265 wxRect
*rectShaft
= NULL
);
266 virtual void DrawSliderThumb(wxDC
& dc
,
268 wxOrientation orient
,
270 virtual void DrawSliderTicks(wxDC
& dc
,
272 const wxSize
& sizeThumb
,
273 wxOrientation orient
,
279 virtual void DrawMenuBarItem(wxDC
& dc
,
281 const wxString
& label
,
283 int indexAccel
= -1);
284 virtual void DrawMenuItem(wxDC
& dc
,
286 const wxMenuGeometryInfo
& geometryInfo
,
287 const wxString
& label
,
288 const wxString
& accel
,
289 const wxBitmap
& bitmap
= wxNullBitmap
,
291 int indexAccel
= -1);
292 virtual void DrawMenuSeparator(wxDC
& dc
,
294 const wxMenuGeometryInfo
& geomInfo
);
296 virtual void DrawStatusField(wxDC
& dc
,
298 const wxString
& label
,
302 virtual void DrawFrameTitleBar(wxDC
& dc
,
304 const wxString
& title
,
307 int specialButton
= 0,
308 int specialButtonFlags
= 0);
309 virtual void DrawFrameBorder(wxDC
& dc
,
312 virtual void DrawFrameBackground(wxDC
& dc
,
315 virtual void DrawFrameTitle(wxDC
& dc
,
317 const wxString
& title
,
319 virtual void DrawFrameIcon(wxDC
& dc
,
323 virtual void DrawFrameButton(wxDC
& dc
,
324 wxCoord x
, wxCoord y
,
327 virtual wxRect
GetFrameClientArea(const wxRect
& rect
, int flags
) const;
328 virtual wxSize
GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const;
329 virtual wxSize
GetFrameMinSize(int flags
) const;
330 virtual wxSize
GetFrameIconSize() const;
331 virtual int HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const;
333 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
335 wxBitmap
*bmpPressed
,
336 wxBitmap
*bmpDisabled
);
338 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
339 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
340 virtual bool AreScrollbarsInsideBorder() const;
342 virtual wxSize
GetScrollbarArrowSize() const
343 { return m_sizeScrollbarArrow
; }
344 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
345 wxScrollBar::Element elem
,
346 int thumbPos
= -1) const;
347 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
348 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
349 const wxPoint
& pt
) const;
350 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
352 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
353 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
354 { return fontHeight
+ 2; }
355 virtual wxSize
GetCheckBitmapSize() const
356 { return wxSize(13, 13); }
357 virtual wxSize
GetRadioBitmapSize() const
358 { return wxSize(12, 12); }
359 virtual wxCoord
GetCheckItemMargin() const
362 virtual wxSize
GetToolBarButtonSize(wxCoord
*separator
) const
363 { if ( separator
) *separator
= 5; return wxSize(16, 15); }
364 virtual wxSize
GetToolBarMargin() const
365 { return wxSize(4, 4); }
367 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
368 const wxRect
& rect
) const;
369 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
371 wxCoord
*extraSpaceBeyond
) const;
373 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
374 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
376 virtual wxCoord
GetSliderDim() const { return 20; }
377 virtual wxCoord
GetSliderTickLen() const { return 4; }
378 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
379 wxOrientation orient
) const;
380 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
381 wxOrientation orient
) const;
382 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
384 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
385 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
386 const wxMenu
& menu
) const;
388 virtual wxSize
GetStatusBarBorders(wxCoord
*borderBetweenFields
) const;
391 // helper of DrawLabel() and DrawCheckOrRadioButton()
392 void DoDrawLabel(wxDC
& dc
,
393 const wxString
& label
,
396 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
398 wxRect
*rectBounds
= NULL
,
399 const wxPoint
& focusOffset
400 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
402 // common part of DrawLabel() and DrawItem()
403 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
405 // DrawLabel() and DrawButtonLabel() helper
406 void DrawLabelShadow(wxDC
& dc
,
407 const wxString
& label
,
412 // DrawButtonBorder() helper
413 void DoDrawBackground(wxDC
& dc
,
416 wxWindow
*window
= NULL
);
418 // DrawBorder() helpers: all of them shift and clip the DC after drawing
421 // just draw a rectangle with the given pen
422 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
424 // draw the lower left part of rectangle
425 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
427 // draw the rectange using the first brush for the left and top sides and
428 // the second one for the bottom and right ones
429 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
430 const wxPen
& pen1
, const wxPen
& pen2
);
432 // draw the normal 3D border
433 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
435 // draw the sunken 3D border
436 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
438 // draw the border used for scrollbar arrows
439 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
441 // public DrawArrow()s helper
442 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
443 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
445 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
446 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
447 wxArrowDirection arrowDir
,
448 wxArrowStyle arrowStyle
);
450 // DrawCheckButton/DrawRadioButton helper
451 void DrawCheckOrRadioButton(wxDC
& dc
,
452 const wxString
& label
,
453 const wxBitmap
& bitmap
,
458 wxCoord focusOffsetY
);
460 // draw a normal or transposed line (useful for using the same code fo both
461 // horizontal and vertical widgets)
462 void DrawLine(wxDC
& dc
,
463 wxCoord x1
, wxCoord y1
,
464 wxCoord x2
, wxCoord y2
,
465 bool transpose
= FALSE
)
468 dc
.DrawLine(y1
, x1
, y2
, x2
);
470 dc
.DrawLine(x1
, y1
, x2
, y2
);
473 // get the standard check/radio button bitmap
474 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
475 wxBitmap
GetCheckBitmap(int flags
)
476 { return GetIndicator(IndicatorType_Check
, flags
); }
477 wxBitmap
GetRadioBitmap(int flags
)
478 { return GetIndicator(IndicatorType_Radio
, flags
); }
481 const wxColourScheme
*m_scheme
;
483 // the sizing parameters (TODO make them changeable)
484 wxSize m_sizeScrollbarArrow
;
486 // GDI objects we use for drawing
487 wxColour m_colDarkGrey
,
495 wxFont m_titlebarFont
;
497 // the checked and unchecked bitmaps for DrawCheckItem()
498 wxBitmap m_bmpCheckBitmaps
[IndicatorStatus_Max
];
500 // the bitmaps returned by GetIndicator()
501 wxBitmap m_bmpIndicators
[IndicatorType_Max
]
503 [IndicatorStatus_Max
];
506 wxBitmap m_bmpFrameButtons
[FrameButton_Max
];
508 // first row is for the normal state, second - for the disabled
509 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
512 // ----------------------------------------------------------------------------
513 // wxMetalInputHandler and derived classes: process the keyboard and mouse
514 // messages according to Windows standards
515 // ----------------------------------------------------------------------------
517 class wxMetalInputHandler
: public wxInputHandler
520 wxMetalInputHandler(wxMetalRenderer
*renderer
);
522 virtual bool HandleKey(wxInputConsumer
*control
,
523 const wxKeyEvent
& event
,
525 virtual bool HandleMouse(wxInputConsumer
*control
,
526 const wxMouseEvent
& event
);
529 wxMetalRenderer
*m_renderer
;
532 class wxMetalScrollBarInputHandler
: public wxStdScrollBarInputHandler
535 wxMetalScrollBarInputHandler(wxMetalRenderer
*renderer
,
536 wxInputHandler
*handler
);
538 virtual bool HandleMouse(wxInputConsumer
*control
, const wxMouseEvent
& event
);
539 virtual bool HandleMouseMove(wxInputConsumer
*control
, const wxMouseEvent
& event
);
541 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
542 const wxControlAction
& action
);
545 virtual bool IsAllowedButton(int button
) { return button
== 1; }
547 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
549 // we don't highlight anything
552 // the first and last event which caused the thumb to move
553 wxMouseEvent m_eventStartDrag
,
556 // have we paused the scrolling because the mouse moved?
559 // we remember the interval of the timer to be able to restart it
563 class wxMetalCheckboxInputHandler
: public wxStdCheckboxInputHandler
566 wxMetalCheckboxInputHandler(wxInputHandler
*handler
)
567 : wxStdCheckboxInputHandler(handler
) { }
569 virtual bool HandleKey(wxInputConsumer
*control
,
570 const wxKeyEvent
& event
,
574 class wxMetalTextCtrlInputHandler
: public wxStdTextCtrlInputHandler
577 wxMetalTextCtrlInputHandler(wxInputHandler
*handler
)
578 : wxStdTextCtrlInputHandler(handler
) { }
580 virtual bool HandleKey(wxInputConsumer
*control
,
581 const wxKeyEvent
& event
,
585 class wxMetalStatusBarInputHandler
: public wxStdInputHandler
588 wxMetalStatusBarInputHandler(wxInputHandler
*handler
);
590 virtual bool HandleMouse(wxInputConsumer
*consumer
,
591 const wxMouseEvent
& event
);
593 virtual bool HandleMouseMove(wxInputConsumer
*consumer
,
594 const wxMouseEvent
& event
);
597 // is the given point over the statusbar grip?
598 bool IsOnGrip(wxWindow
*statbar
, const wxPoint
& pt
) const;
601 // the cursor we had replaced with the resize one
602 wxCursor m_cursorOld
;
604 // was the mouse over the grip last time we checked?
608 class wxMetalSystemMenuEvtHandler
;
610 class wxMetalFrameInputHandler
: public wxStdFrameInputHandler
613 wxMetalFrameInputHandler(wxInputHandler
*handler
);
614 ~wxMetalFrameInputHandler();
616 virtual bool HandleMouse(wxInputConsumer
*control
,
617 const wxMouseEvent
& event
);
619 virtual bool HandleActivation(wxInputConsumer
*consumer
, bool activated
);
621 void PopupSystemMenu(wxTopLevelWindow
*window
, const wxPoint
& pos
) const;
624 // was the mouse over the grip last time we checked?
625 wxMetalSystemMenuEvtHandler
*m_menuHandler
;
628 // ----------------------------------------------------------------------------
629 // wxMetalColourScheme: uses (default) Metal colours
630 // ----------------------------------------------------------------------------
632 class wxMetalColourScheme
: public wxColourScheme
635 virtual wxColour
Get(StdColour col
) const;
636 virtual wxColour
GetBackground(wxWindow
*win
) const;
639 // ----------------------------------------------------------------------------
640 // wxMetalArtProvider
641 // ----------------------------------------------------------------------------
643 class wxMetalArtProvider
: public wxArtProvider
646 virtual wxBitmap
CreateBitmap(const wxArtID
& id
,
647 const wxArtClient
& client
,
651 // ----------------------------------------------------------------------------
653 // ----------------------------------------------------------------------------
655 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
657 class wxMetalTheme
: public wxTheme
661 virtual ~wxMetalTheme();
663 virtual wxRenderer
*GetRenderer();
664 virtual wxArtProvider
*GetArtProvider();
665 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
666 virtual wxColourScheme
*GetColourScheme();
669 // get the default input handler
670 wxInputHandler
*GetDefaultInputHandler();
672 wxMetalRenderer
*m_renderer
;
674 wxMetalArtProvider
*m_artProvider
;
676 // the names of the already created handlers and the handlers themselves
677 // (these arrays are synchronized)
678 wxSortedArrayString m_handlerNames
;
679 wxArrayHandlers m_handlers
;
681 wxMetalInputHandler
*m_handlerDefault
;
683 wxMetalColourScheme
*m_scheme
;
685 WX_DECLARE_THEME(Metal
)
688 // ----------------------------------------------------------------------------
690 // ----------------------------------------------------------------------------
692 // frame buttons bitmaps
694 static const char *frame_button_close_xpm
[] = {
709 static const char *frame_button_help_xpm
[] = {
724 static const char *frame_button_maximize_xpm
[] = {
739 static const char *frame_button_minimize_xpm
[] = {
754 static const char *frame_button_restore_xpm
[] = {
771 static const char *checked_menu_xpm
[] = {
772 /* columns rows colors chars-per-pixel */
788 static const char *selected_checked_menu_xpm
[] = {
789 /* columns rows colors chars-per-pixel */
805 static const char *disabled_checked_menu_xpm
[] = {
806 /* columns rows colors chars-per-pixel */
823 static const char *selected_disabled_checked_menu_xpm
[] = {
824 /* columns rows colors chars-per-pixel */
840 // checkbox and radiobox bitmaps below
842 static const char *checked_xpm
[] = {
843 /* columns rows colors chars-per-pixel */
866 static const char *pressed_checked_xpm
[] = {
867 /* columns rows colors chars-per-pixel */
889 static const char *pressed_disabled_checked_xpm
[] = {
890 /* columns rows colors chars-per-pixel */
912 static const char *checked_item_xpm
[] = {
913 /* columns rows colors chars-per-pixel */
934 static const char *unchecked_xpm
[] = {
935 /* columns rows colors chars-per-pixel */
958 static const char *pressed_unchecked_xpm
[] = {
959 /* columns rows colors chars-per-pixel */
981 static const char *unchecked_item_xpm
[] = {
982 /* columns rows colors chars-per-pixel */
1002 static const char *checked_radio_xpm
[] = {
1003 /* columns rows colors chars-per-pixel */
1026 static const char *pressed_checked_radio_xpm
[] = {
1027 /* columns rows colors chars-per-pixel */
1050 static const char *pressed_disabled_checked_radio_xpm
[] = {
1051 /* columns rows colors chars-per-pixel */
1074 static const char *unchecked_radio_xpm
[] = {
1075 /* columns rows colors chars-per-pixel */
1098 static const char *pressed_unchecked_radio_xpm
[] = {
1099 /* columns rows colors chars-per-pixel */
1122 static const char **
1123 xpmIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
1128 { checked_xpm
, unchecked_xpm
},
1131 { pressed_checked_xpm
, pressed_unchecked_xpm
},
1134 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
1140 { checked_radio_xpm
, unchecked_radio_xpm
},
1143 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1146 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1152 { checked_menu_xpm
, NULL
},
1155 { selected_checked_menu_xpm
, NULL
},
1158 { disabled_checked_menu_xpm
, NULL
},
1160 // disabled selected state
1161 { selected_disabled_checked_menu_xpm
, NULL
},
1165 static const char **xpmChecked
[IndicatorStatus_Max
] =
1171 // ============================================================================
1173 // ============================================================================
1175 WX_IMPLEMENT_THEME(wxMetalTheme
, Metal
, wxTRANSLATE("Metal theme"));
1177 // ----------------------------------------------------------------------------
1179 // ----------------------------------------------------------------------------
1181 wxMetalTheme::wxMetalTheme()
1185 m_handlerDefault
= NULL
;
1188 wxMetalTheme::~wxMetalTheme()
1190 size_t count
= m_handlers
.GetCount();
1191 for ( size_t n
= 0; n
< count
; n
++ )
1193 if ( m_handlers
[n
] != m_handlerDefault
)
1194 delete m_handlers
[n
];
1197 delete m_handlerDefault
;
1203 wxRenderer
*wxMetalTheme::GetRenderer()
1207 m_renderer
= new wxMetalRenderer(GetColourScheme());
1213 wxArtProvider
*wxMetalTheme::GetArtProvider()
1215 if ( !m_artProvider
)
1217 m_artProvider
= new wxMetalArtProvider
;
1220 return m_artProvider
;
1223 wxInputHandler
*wxMetalTheme::GetDefaultInputHandler()
1225 if ( !m_handlerDefault
)
1227 m_handlerDefault
= new wxMetalInputHandler(m_renderer
);
1230 return m_handlerDefault
;
1233 wxInputHandler
*wxMetalTheme::GetInputHandler(const wxString
& control
)
1235 wxInputHandler
*handler
;
1236 int n
= m_handlerNames
.Index(control
);
1237 if ( n
== wxNOT_FOUND
)
1239 // create a new handler
1240 if ( control
== wxINP_HANDLER_SCROLLBAR
)
1241 handler
= new wxMetalScrollBarInputHandler(m_renderer
,
1242 GetDefaultInputHandler());
1244 else if ( control
== wxINP_HANDLER_BUTTON
)
1245 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
1246 #endif // wxUSE_BUTTON
1248 else if ( control
== wxINP_HANDLER_CHECKBOX
)
1249 handler
= new wxMetalCheckboxInputHandler(GetDefaultInputHandler());
1250 #endif // wxUSE_CHECKBOX
1252 else if ( control
== wxINP_HANDLER_COMBOBOX
)
1253 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1254 #endif // wxUSE_COMBOBOX
1256 else if ( control
== wxINP_HANDLER_LISTBOX
)
1257 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1258 #endif // wxUSE_LISTBOX
1259 #if wxUSE_CHECKLISTBOX
1260 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1261 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1262 #endif // wxUSE_CHECKLISTBOX
1264 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1265 handler
= new wxMetalTextCtrlInputHandler(GetDefaultInputHandler());
1266 #endif // wxUSE_TEXTCTRL
1268 else if ( control
== wxINP_HANDLER_SLIDER
)
1269 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1270 #endif // wxUSE_SLIDER
1272 else if ( control
== wxINP_HANDLER_SPINBTN
)
1273 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1274 #endif // wxUSE_SPINBTN
1276 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1277 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1278 #endif // wxUSE_NOTEBOOK
1280 else if ( control
== wxINP_HANDLER_STATUSBAR
)
1281 handler
= new wxMetalStatusBarInputHandler(GetDefaultInputHandler());
1282 #endif // wxUSE_STATUSBAR
1284 else if ( control
== wxINP_HANDLER_TOOLBAR
)
1285 handler
= new wxStdToolbarInputHandler(GetDefaultInputHandler());
1286 #endif // wxUSE_TOOLBAR
1287 else if ( control
== wxINP_HANDLER_TOPLEVEL
)
1288 handler
= new wxMetalFrameInputHandler(GetDefaultInputHandler());
1290 handler
= GetDefaultInputHandler();
1292 n
= m_handlerNames
.Add(control
);
1293 m_handlers
.Insert(handler
, n
);
1295 else // we already have it
1297 handler
= m_handlers
[n
];
1303 wxColourScheme
*wxMetalTheme::GetColourScheme()
1307 m_scheme
= new wxMetalColourScheme
;
1312 // ============================================================================
1313 // wxMetalColourScheme
1314 // ============================================================================
1316 wxColour
wxMetalColourScheme::GetBackground(wxWindow
*win
) const
1319 if ( win
->UseBgCol() )
1321 // use the user specified colour
1322 col
= win
->GetBackgroundColour();
1325 if ( win
->IsContainerWindow() )
1327 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1330 if ( !text
->IsEnabled() ) // not IsEditable()
1332 //else: execute code below
1337 // doesn't depend on the state
1343 int flags
= win
->GetStateFlags();
1345 // the colour set by the user should be used for the normal state
1346 // and for the states for which we don't have any specific colours
1347 if ( !col
.Ok() || (flags
& wxCONTROL_PRESSED
) != 0 )
1349 if ( wxDynamicCast(win
, wxScrollBar
) )
1350 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1360 wxColour
wxMetalColourScheme::Get(wxMetalColourScheme::StdColour col
) const
1364 // use the system colours under Windows
1365 #if defined(__WXMSW__)
1366 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1368 case CONTROL_PRESSED
:
1369 case CONTROL_CURRENT
:
1370 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1372 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1374 #if defined(COLOR_3DLIGHT)
1375 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_3DLIGHT
));
1377 case SCROLLBAR
: return wxColour(0xe0e0e0);
1379 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1381 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1382 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1384 #if defined(COLOR_3DDKSHADOW)
1385 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1387 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DHADOW
));
1390 case CONTROL_TEXT_DISABLED
:
1391 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1393 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1395 case CONTROL_TEXT_DISABLED_SHADOW
:
1396 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1398 case TITLEBAR
: return wxColour(GetSysColor(COLOR_INACTIVECAPTION
));
1399 case TITLEBAR_ACTIVE
: return wxColour(GetSysColor(COLOR_ACTIVECAPTION
));
1400 case TITLEBAR_TEXT
: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT
));
1401 case TITLEBAR_ACTIVE_TEXT
: return wxColour(GetSysColor(COLOR_CAPTIONTEXT
));
1403 case DESKTOP
: return wxColour(0x808000);
1405 // use the standard Windows colours elsewhere
1406 case WINDOW
: return *wxWHITE
;
1408 case CONTROL_PRESSED
:
1409 case CONTROL_CURRENT
:
1410 case CONTROL
: return wxColour(0xc0c0c0);
1412 case CONTROL_TEXT
: return *wxBLACK
;
1414 case SCROLLBAR
: return wxColour(0xe0e0e0);
1415 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1417 case HIGHLIGHT
: return wxColour(0x800000);
1418 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1420 case SHADOW_DARK
: return *wxBLACK
;
1422 case CONTROL_TEXT_DISABLED
:return wxColour(0xe0e0e0);
1423 case SHADOW_HIGHLIGHT
: return wxColour(0xffffff);
1425 case SHADOW_IN
: return wxColour(0xc0c0c0);
1427 case CONTROL_TEXT_DISABLED_SHADOW
:
1428 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1430 case TITLEBAR
: return wxColour(0xaeaaae);
1431 case TITLEBAR_ACTIVE
: return wxColour(0x820300);
1432 case TITLEBAR_TEXT
: return wxColour(0xc0c0c0);
1433 case TITLEBAR_ACTIVE_TEXT
:return *wxWHITE
;
1435 case DESKTOP
: return wxColour(0x808000);
1438 case GAUGE
: return Get(HIGHLIGHT
);
1442 wxFAIL_MSG(_T("invalid standard colour"));
1447 // ============================================================================
1449 // ============================================================================
1451 // ----------------------------------------------------------------------------
1453 // ----------------------------------------------------------------------------
1455 wxMetalRenderer::wxMetalRenderer(const wxColourScheme
*scheme
)
1459 m_sizeScrollbarArrow
= wxSize(16, 16);
1461 // init colours and pens
1462 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1464 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1465 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1467 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1469 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1470 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1472 m_titlebarFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
1473 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
1475 // init the arrow bitmaps
1476 static const size_t ARROW_WIDTH
= 7;
1477 static const size_t ARROW_LENGTH
= 4;
1480 wxMemoryDC dcNormal
,
1483 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1485 bool isVertical
= n
> Arrow_Right
;
1498 // disabled arrow is larger because of the shadow
1499 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1500 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1502 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1503 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1505 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1506 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1510 dcNormal
.SetPen(m_penBlack
);
1511 dcDisabled
.SetPen(m_penDarkGrey
);
1513 // calculate the position of the point of the arrow
1517 x1
= (ARROW_WIDTH
- 1)/2;
1518 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1522 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1523 y1
= (ARROW_WIDTH
- 1)/2;
1534 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1536 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1537 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1544 if ( n
== Arrow_Up
)
1555 else // left or right arrow
1560 if ( n
== Arrow_Left
)
1573 // draw the shadow for the disabled one
1574 dcDisabled
.SetPen(m_penHighlight
);
1579 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1583 x1
= ARROW_LENGTH
- 1;
1584 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1587 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1588 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1593 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1597 x1
= ARROW_WIDTH
- 1;
1599 x2
= (ARROW_WIDTH
- 1)/2;
1601 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1602 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1607 // create the inversed bitmap but only for the right arrow as we only
1608 // use it for the menus
1609 if ( n
== Arrow_Right
)
1611 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1612 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1614 dcInverse
.Blit(0, 0, w
, h
,
1617 dcInverse
.SelectObject(wxNullBitmap
);
1619 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1620 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1622 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1623 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1625 dcInverse
.Blit(0, 0, w
, h
,
1628 dcInverse
.SelectObject(wxNullBitmap
);
1630 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1631 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1634 dcNormal
.SelectObject(wxNullBitmap
);
1635 dcDisabled
.SelectObject(wxNullBitmap
);
1637 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1638 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1639 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1640 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1642 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1645 // init the frame buttons bitmaps
1646 m_bmpFrameButtons
[FrameButton_Close
] = wxBitmap(frame_button_close_xpm
);
1647 m_bmpFrameButtons
[FrameButton_Minimize
] = wxBitmap(frame_button_minimize_xpm
);
1648 m_bmpFrameButtons
[FrameButton_Maximize
] = wxBitmap(frame_button_maximize_xpm
);
1649 m_bmpFrameButtons
[FrameButton_Restore
] = wxBitmap(frame_button_restore_xpm
);
1650 m_bmpFrameButtons
[FrameButton_Help
] = wxBitmap(frame_button_help_xpm
);
1653 // ----------------------------------------------------------------------------
1655 // ----------------------------------------------------------------------------
1658 The raised border in Metal looks like this:
1660 IIIIIIIIIIIIIIIIIIIIIIB
1662 I GB I = white (HILIGHT)
1663 I GB H = light grey (LIGHT)
1664 I GB G = dark grey (SHADOI)
1665 I GB B = black (DKSHADOI)
1666 I GB I = hIghlight (COLOR_3DHILIGHT)
1668 IGGGGGGGGGGGGGGGGGGGGGB
1669 BBBBBBBBBBBBBBBBBBBBBBB
1671 The sunken border looks like this:
1673 GGGGGGGGGGGGGGGGGGGGGGI
1674 GBBBBBBBBBBBBBBBBBBBBHI
1681 GHHHHHHHHHHHHHHHHHHHHHI
1682 IIIIIIIIIIIIIIIIIIIIIII
1684 The static border (used for the controls which don't get focus) is like
1687 GGGGGGGGGGGGGGGGGGGGGGW
1695 WWWWWWWWWWWWWWWWWWWWWWW
1697 The most complicated is the double border:
1699 HHHHHHHHHHHHHHHHHHHHHHB
1700 HWWWWWWWWWWWWWWWWWWWWGB
1701 HWHHHHHHHHHHHHHHHHHHHGB
1706 HWHHHHHHHHHHHHHHHHHHHGB
1707 HGGGGGGGGGGGGGGGGGGGGGB
1708 BBBBBBBBBBBBBBBBBBBBBBB
1710 And the simple border is, well, simple:
1712 BBBBBBBBBBBBBBBBBBBBBBB
1721 BBBBBBBBBBBBBBBBBBBBBBB
1724 void wxMetalRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1728 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1729 dc
.DrawRectangle(*rect
);
1735 void wxMetalRenderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1737 // draw the bottom and right sides
1739 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1740 rect
->GetRight() + 1, rect
->GetBottom());
1741 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1742 rect
->GetRight(), rect
->GetBottom());
1749 void wxMetalRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1750 const wxPen
& pen1
, const wxPen
& pen2
)
1752 // draw the rectangle
1754 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1755 rect
->GetLeft(), rect
->GetBottom());
1756 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1757 rect
->GetRight(), rect
->GetTop());
1759 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1760 rect
->GetRight(), rect
->GetBottom());
1761 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1762 rect
->GetRight() + 1, rect
->GetBottom());
1768 void wxMetalRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1770 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1771 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1774 void wxMetalRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1776 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1777 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1780 void wxMetalRenderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1784 DrawRect(dc
, rect
, m_penDarkGrey
);
1786 // the arrow is usually drawn inside border of width 2 and is offset by
1787 // another pixel in both directions when it's pressed - as the border
1788 // in this case is more narrow as well, we have to adjust rect like
1796 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1797 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1801 void wxMetalRenderer::DrawBorder(wxDC
& dc
,
1803 const wxRect
& rectTotal
,
1804 int WXUNUSED(flags
),
1809 wxRect rect
= rectTotal
;
1813 case wxBORDER_SUNKEN
:
1814 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1816 DrawSunkenBorder(dc
, &rect
);
1820 case wxBORDER_STATIC
:
1821 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1824 case wxBORDER_RAISED
:
1825 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1827 DrawRaisedBorder(dc
, &rect
);
1831 case wxBORDER_DOUBLE
:
1832 DrawArrowBorder(dc
, &rect
);
1833 DrawRect(dc
, &rect
, m_penLightGrey
);
1836 case wxBORDER_SIMPLE
:
1837 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1839 DrawRect(dc
, &rect
, m_penBlack
);
1844 wxFAIL_MSG(_T("unknown border type"));
1847 case wxBORDER_DEFAULT
:
1856 wxRect
wxMetalRenderer::GetBorderDimensions(wxBorder border
) const
1861 case wxBORDER_RAISED
:
1862 case wxBORDER_SUNKEN
:
1863 width
= BORDER_THICKNESS
;
1866 case wxBORDER_SIMPLE
:
1867 case wxBORDER_STATIC
:
1871 case wxBORDER_DOUBLE
:
1877 // char *crash = NULL;
1879 wxFAIL_MSG(_T("unknown border type"));
1883 case wxBORDER_DEFAULT
:
1893 rect
.height
= width
;
1898 bool wxMetalRenderer::AreScrollbarsInsideBorder() const
1903 // ----------------------------------------------------------------------------
1905 // ----------------------------------------------------------------------------
1907 void wxMetalRenderer::DrawTextBorder(wxDC
& dc
,
1913 // text controls are not special under windows
1914 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1917 void wxMetalRenderer::DrawButtonBorder(wxDC
& dc
,
1918 const wxRect
& rectTotal
,
1922 wxRect rect
= rectTotal
;
1924 if ( flags
& wxCONTROL_PRESSED
)
1926 // button pressed: draw a double border around it
1927 DrawRect(dc
, &rect
, m_penBlack
);
1928 DrawRect(dc
, &rect
, m_penDarkGrey
);
1932 // button not pressed
1934 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1936 // button either default or focused (or both): add an extra border around it
1937 DrawRect(dc
, &rect
, m_penBlack
);
1940 // now draw a normal button
1941 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1942 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1951 // ----------------------------------------------------------------------------
1953 // ----------------------------------------------------------------------------
1955 void wxMetalRenderer::DrawHorizontalLine(wxDC
& dc
,
1956 wxCoord y
, wxCoord x1
, wxCoord x2
)
1958 dc
.SetPen(m_penDarkGrey
);
1959 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1960 dc
.SetPen(m_penHighlight
);
1962 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1965 void wxMetalRenderer::DrawVerticalLine(wxDC
& dc
,
1966 wxCoord x
, wxCoord y1
, wxCoord y2
)
1968 dc
.SetPen(m_penDarkGrey
);
1969 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1970 dc
.SetPen(m_penHighlight
);
1972 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1975 void wxMetalRenderer::DrawFrame(wxDC
& dc
,
1976 const wxString
& label
,
1982 wxCoord height
= 0; // of the label
1983 wxRect rectFrame
= rect
;
1984 if ( !label
.empty() )
1986 // the text should touch the top border of the rect, so the frame
1987 // itself should be lower
1988 dc
.GetTextExtent(label
, NULL
, &height
);
1989 rectFrame
.y
+= height
/ 2;
1990 rectFrame
.height
-= height
/ 2;
1992 // we have to draw each part of the frame individually as we can't
1993 // erase the background beyond the label as it might contain some
1994 // pixmap already, so drawing everything and then overwriting part of
1995 // the frame with label doesn't work
1997 // TODO: the +5 and space insertion should be customizable
2000 rectText
.x
= rectFrame
.x
+ 5;
2001 rectText
.y
= rect
.y
;
2002 rectText
.width
= rectFrame
.width
- 7; // +2 border width
2003 rectText
.height
= height
;
2006 label2
<< _T(' ') << label
<< _T(' ');
2007 if ( indexAccel
!= -1 )
2009 // adjust it as we prepended a space
2014 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
2016 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
2020 // just draw the complete frame
2021 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
2022 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
2026 // ----------------------------------------------------------------------------
2028 // ----------------------------------------------------------------------------
2030 void wxMetalRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
2032 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
2033 // pixels each while we really need dots here... PS_ALTERNATE might
2034 // work, but it is for NT 5 only
2036 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
2038 // draw the pixels manually: note that to behave in the same manner as
2039 // DrawRect(), we must exclude the bottom and right borders from the
2041 wxCoord x1
= rect
.GetLeft(),
2043 x2
= rect
.GetRight(),
2044 y2
= rect
.GetBottom();
2046 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
2048 // this seems to be closer than what Windows does than wxINVERT although
2049 // I'm still not sure if it's correct
2050 dc
.SetLogicalFunction(wxAND_REVERSE
);
2053 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
2054 dc
.DrawPoint(z
, rect
.GetTop());
2056 wxCoord shift
= z
== x2
? 0 : 1;
2057 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
2058 dc
.DrawPoint(x2
, z
);
2060 shift
= z
== y2
? 0 : 1;
2061 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
2062 dc
.DrawPoint(z
, y2
);
2064 shift
= z
== x1
? 0 : 1;
2065 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
2066 dc
.DrawPoint(x1
, z
);
2068 dc
.SetLogicalFunction(wxCOPY
);
2072 void wxMetalRenderer::DrawLabelShadow(wxDC
& dc
,
2073 const wxString
& label
,
2078 // draw shadow of the text
2079 dc
.SetTextForeground(m_colHighlight
);
2080 wxRect rectShadow
= rect
;
2083 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
2085 // make the text grey
2086 dc
.SetTextForeground(m_colDarkGrey
);
2089 void wxMetalRenderer::DrawLabel(wxDC
& dc
,
2090 const wxString
& label
,
2097 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
2100 void wxMetalRenderer::DoDrawLabel(wxDC
& dc
,
2101 const wxString
& label
,
2107 const wxPoint
& focusOffset
)
2109 // the underscores are not drawn for focused controls in wxMSW
2110 if ( flags
& wxCONTROL_FOCUSED
)
2115 if ( flags
& wxCONTROL_DISABLED
)
2117 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2118 // currently only can happen for a menu item and it seems that Windows
2119 // doesn't draw the shadow in this case, so we don't do it neither
2120 if ( flags
& wxCONTROL_SELECTED
)
2122 // just make the label text greyed out
2123 dc
.SetTextForeground(m_colDarkGrey
);
2125 else // draw normal disabled label
2127 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
2132 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
2134 if ( flags
& wxCONTROL_DISABLED
)
2136 // restore the fg colour
2137 dc
.SetTextForeground(*wxBLACK
);
2140 if ( flags
& wxCONTROL_FOCUSED
)
2142 if ( focusOffset
.x
|| focusOffset
.y
)
2144 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
2147 DrawFocusRect(dc
, rectLabel
);
2151 *rectBounds
= rectLabel
;
2154 void wxMetalRenderer::DrawButtonLabel(wxDC
& dc
,
2155 const wxString
& label
,
2156 const wxBitmap
& image
,
2163 // the underscores are not drawn for focused controls in wxMSW
2164 if ( flags
& wxCONTROL_PRESSED
)
2169 wxRect rectLabel
= rect
;
2170 if ( !label
.empty() )
2172 // shift the label if a button is pressed
2173 if ( flags
& wxCONTROL_PRESSED
)
2179 if ( flags
& wxCONTROL_DISABLED
)
2181 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
2184 // leave enough space for the focus rectangle
2185 if ( flags
& wxCONTROL_FOCUSED
)
2187 rectLabel
.Inflate(-2);
2191 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
2193 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
2195 if ( flags
& wxCONTROL_PRESSED
)
2197 // the focus rectangle is never pressed, so undo the shift done
2205 DrawFocusRect(dc
, rectLabel
);
2209 // ----------------------------------------------------------------------------
2210 // (check)listbox items
2211 // ----------------------------------------------------------------------------
2213 void wxMetalRenderer::DrawItem(wxDC
& dc
,
2214 const wxString
& label
,
2218 wxDCTextColourChanger
colChanger(dc
);
2220 if ( flags
& wxCONTROL_SELECTED
)
2222 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2224 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2225 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2226 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2227 dc
.DrawRectangle(rect
);
2230 wxRect rectText
= rect
;
2232 rectText
.width
-= 2;
2233 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
2235 if ( flags
& wxCONTROL_FOCUSED
)
2237 DrawFocusRect(dc
, rect
);
2241 void wxMetalRenderer::DrawCheckItem(wxDC
& dc
,
2242 const wxString
& label
,
2243 const wxBitmap
& bitmap
,
2252 else // use default bitmap
2254 IndicatorStatus i
= flags
& wxCONTROL_CHECKED
2255 ? IndicatorStatus_Checked
2256 : IndicatorStatus_Unchecked
;
2258 if ( !m_bmpCheckBitmaps
[i
].Ok() )
2260 m_bmpCheckBitmaps
[i
] = wxBitmap(xpmChecked
[i
]);
2263 bmp
= m_bmpCheckBitmaps
[i
];
2266 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
2267 TRUE
/* use mask */);
2269 wxRect rectLabel
= rect
;
2270 int bmpWidth
= bmp
.GetWidth();
2271 rectLabel
.x
+= bmpWidth
;
2272 rectLabel
.width
-= bmpWidth
;
2274 DrawItem(dc
, label
, rectLabel
, flags
);
2277 // ----------------------------------------------------------------------------
2278 // check/radio buttons
2279 // ----------------------------------------------------------------------------
2281 wxBitmap
wxMetalRenderer::GetIndicator(IndicatorType indType
, int flags
)
2283 IndicatorState indState
;
2284 if ( flags
& wxCONTROL_SELECTED
)
2285 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
2286 : IndicatorState_Selected
;
2287 else if ( flags
& wxCONTROL_DISABLED
)
2288 indState
= IndicatorState_Disabled
;
2289 else if ( flags
& wxCONTROL_PRESSED
)
2290 indState
= IndicatorState_Pressed
;
2292 indState
= IndicatorState_Normal
;
2294 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
2295 ? IndicatorStatus_Checked
2296 : IndicatorStatus_Unchecked
;
2298 wxBitmap bmp
= m_bmpIndicators
[indType
][indState
][indStatus
];
2301 const char **xpm
= xpmIndicators
[indType
][indState
][indStatus
];
2304 // create and cache it
2305 bmp
= wxBitmap(xpm
);
2306 m_bmpIndicators
[indType
][indState
][indStatus
] = bmp
;
2313 void wxMetalRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
2314 const wxString
& label
,
2315 const wxBitmap
& bitmap
,
2320 wxCoord focusOffsetY
)
2322 // calculate the position of the bitmap and of the label
2323 wxCoord heightBmp
= bitmap
.GetHeight();
2325 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2328 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2329 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2331 // align label vertically with the bitmap - looks nicer like this
2332 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2334 // calc horz position
2335 if ( align
== wxALIGN_RIGHT
)
2337 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2338 rectLabel
.x
= rect
.x
+ 3;
2339 rectLabel
.SetRight(xBmp
);
2341 else // normal (checkbox to the left of the text) case
2344 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2345 rectLabel
.SetRight(rect
.GetRight());
2348 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2351 dc
, label
, rectLabel
,
2353 wxALIGN_LEFT
| wxALIGN_TOP
,
2355 NULL
, // we don't need bounding rect
2356 // use custom vert focus rect offset
2357 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2361 void wxMetalRenderer::DrawRadioButton(wxDC
& dc
,
2362 const wxString
& label
,
2363 const wxBitmap
& bitmap
,
2373 bmp
= GetRadioBitmap(flags
);
2375 DrawCheckOrRadioButton(dc
, label
,
2377 rect
, flags
, align
, indexAccel
,
2378 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2381 void wxMetalRenderer::DrawCheckButton(wxDC
& dc
,
2382 const wxString
& label
,
2383 const wxBitmap
& bitmap
,
2393 bmp
= GetCheckBitmap(flags
);
2395 DrawCheckOrRadioButton(dc
, label
,
2397 rect
, flags
, align
, indexAccel
,
2398 0); // no focus rect offset for checkboxes
2401 void wxMetalRenderer::DrawToolBarButton(wxDC
& dc
,
2402 const wxString
& label
,
2403 const wxBitmap
& bitmap
,
2404 const wxRect
& rectOrig
,
2407 if ( !label
.empty() || bitmap
.Ok() )
2409 wxRect rect
= rectOrig
;
2410 rect
.Deflate(BORDER_THICKNESS
);
2412 if ( flags
& wxCONTROL_PRESSED
)
2414 DrawBorder(dc
, wxBORDER_SUNKEN
, rect
, flags
);
2416 else if ( flags
& wxCONTROL_CURRENT
)
2418 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
);
2421 dc
.DrawLabel(label
, bitmap
, rect
, wxALIGN_CENTRE
);
2425 // leave a small gap aroudn the line, also account for the toolbar
2427 DrawVerticalLine(dc
, rectOrig
.x
+ rectOrig
.width
/2,
2428 rectOrig
.y
+ 2*BORDER_THICKNESS
,
2429 rectOrig
.GetBottom() - BORDER_THICKNESS
);
2433 // ----------------------------------------------------------------------------
2435 // ----------------------------------------------------------------------------
2437 void wxMetalRenderer::DrawTextLine(wxDC
& dc
,
2438 const wxString
& text
,
2444 // nothing special to do here
2445 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2448 void wxMetalRenderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2450 // we don't draw them
2453 // ----------------------------------------------------------------------------
2455 // ----------------------------------------------------------------------------
2457 void wxMetalRenderer::DrawTab(wxDC
& dc
,
2458 const wxRect
& rectOrig
,
2460 const wxString
& label
,
2461 const wxBitmap
& bitmap
,
2465 wxRect rect
= rectOrig
;
2467 // the current tab is drawn indented (to the top for default case) and
2468 // bigger than the other ones
2469 const wxSize indent
= GetTabIndent();
2470 if ( flags
& wxCONTROL_SELECTED
)
2475 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2479 rect
.Inflate(indent
.x
, 0);
2481 rect
.height
+= indent
.y
;
2485 rect
.Inflate(indent
.x
, 0);
2486 rect
.height
+= indent
.y
;
2491 wxFAIL_MSG(_T("TODO"));
2496 // draw the text, image and the focus around them (if necessary)
2497 wxRect rectLabel
= rect
;
2498 rectLabel
.Deflate(1, 1);
2499 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2500 flags
, wxALIGN_CENTRE
, indexAccel
);
2502 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2503 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2506 x2
= rect
.GetRight(),
2507 y2
= rect
.GetBottom();
2509 // FIXME: all this code will break if the tab indent or the border width,
2510 // it is tied to the fact that both of them are equal to 2
2515 dc
.SetPen(m_penHighlight
);
2516 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2517 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2518 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2520 dc
.SetPen(m_penBlack
);
2521 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2522 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2524 dc
.SetPen(m_penDarkGrey
);
2525 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2527 if ( flags
& wxCONTROL_SELECTED
)
2529 dc
.SetPen(m_penLightGrey
);
2531 // overwrite the part of the border below this tab
2532 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2534 // and the shadow of the tab to the left of us
2535 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2540 dc
.SetPen(m_penHighlight
);
2541 // we need to continue one pixel further to overwrite the corner of
2542 // the border for the selected tab
2543 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2545 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2547 dc
.SetPen(m_penBlack
);
2548 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2549 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2550 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2552 dc
.SetPen(m_penDarkGrey
);
2553 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2554 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2556 if ( flags
& wxCONTROL_SELECTED
)
2558 dc
.SetPen(m_penLightGrey
);
2560 // overwrite the part of the (double!) border above this tab
2561 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2562 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2564 // and the shadow of the tab to the left of us
2565 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2571 wxFAIL_MSG(_T("TODO"));
2575 // ----------------------------------------------------------------------------
2577 // ----------------------------------------------------------------------------
2579 wxSize
wxMetalRenderer::GetSliderThumbSize(const wxRect
& rect
,
2580 wxOrientation orient
) const
2584 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2585 if ( orient
== wxHORIZONTAL
)
2587 size
.y
= rect
.height
- 6;
2588 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2592 size
.x
= rect
.width
- 6;
2593 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2599 wxRect
wxMetalRenderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2600 wxOrientation orient
) const
2602 static const wxCoord SLIDER_MARGIN
= 6;
2604 wxRect rect
= rectOrig
;
2606 if ( orient
== wxHORIZONTAL
)
2608 // make the rect of minimal width and centre it
2609 rect
.height
= 2*BORDER_THICKNESS
;
2610 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2614 // leave margins on the sides
2615 rect
.Deflate(SLIDER_MARGIN
, 0);
2619 // same as above but in other direction
2620 rect
.width
= 2*BORDER_THICKNESS
;
2621 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2625 rect
.Deflate(0, SLIDER_MARGIN
);
2631 void wxMetalRenderer::DrawSliderShaft(wxDC
& dc
,
2632 const wxRect
& rectOrig
,
2633 wxOrientation orient
,
2637 if ( flags
& wxCONTROL_FOCUSED
)
2639 DrawFocusRect(dc
, rectOrig
);
2642 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2647 DrawSunkenBorder(dc
, &rect
);
2650 void wxMetalRenderer::DrawSliderThumb(wxDC
& dc
,
2652 wxOrientation orient
,
2656 we are drawing a shape of this form
2661 H DB where H is hightlight colour
2674 The interior of this shape is filled with the hatched brush if the thumb
2678 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2680 bool transpose
= orient
== wxVERTICAL
;
2682 wxCoord x
, y
, x2
, y2
;
2687 x2
= rect
.GetBottom();
2688 y2
= rect
.GetRight();
2694 x2
= rect
.GetRight();
2695 y2
= rect
.GetBottom();
2698 // the size of the pointed part of the thumb
2699 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2701 wxCoord x3
= x
+ sizeArrow
,
2702 y3
= y2
- sizeArrow
;
2704 dc
.SetPen(m_penHighlight
);
2705 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2706 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2707 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2709 dc
.SetPen(m_penBlack
);
2710 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2711 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2713 dc
.SetPen(m_penDarkGrey
);
2714 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2715 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2717 if ( flags
& wxCONTROL_PRESSED
)
2719 // TODO: MSW fills the entire area inside, not just the rect
2720 wxRect rectInt
= rect
;
2722 rectInt
.SetRight(y3
);
2724 rectInt
.SetBottom(y3
);
2727 #if !defined(__WXMGL__)
2728 static const char *stipple_xpm
[] = {
2729 /* columns rows colors chars-per-pixel */
2738 // VS: MGL can only do 8x8 stipple brushes
2739 static const char *stipple_xpm
[] = {
2740 /* columns rows colors chars-per-pixel */
2755 dc
.SetBrush(wxBrush(stipple_xpm
));
2757 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2758 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2759 dc
.SetPen(*wxTRANSPARENT_PEN
);
2760 dc
.DrawRectangle(rectInt
);
2764 void wxMetalRenderer::DrawSliderTicks(wxDC
& dc
,
2766 const wxSize
& sizeThumb
,
2767 wxOrientation orient
,
2779 // the variable names correspond to horizontal case, but they can be used
2780 // for both orientations
2781 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2782 if ( orient
== wxHORIZONTAL
)
2784 x1
= rect
.GetLeft();
2785 x2
= rect
.GetRight();
2787 // draw from bottom to top to leave one pixel space between the ticks
2788 // and the slider as Windows do
2789 y1
= rect
.GetBottom();
2794 widthThumb
= sizeThumb
.x
;
2799 x2
= rect
.GetBottom();
2801 y1
= rect
.GetRight();
2802 y2
= rect
.GetLeft();
2806 widthThumb
= sizeThumb
.y
;
2809 // the first tick should be positioned in such way that a thumb drawn in
2810 // the first position points down directly to it
2811 x1
+= widthThumb
/ 2;
2812 x2
-= widthThumb
/ 2;
2814 // this also means that we have slightly less space for the ticks in
2815 // between the first and the last
2818 dc
.SetPen(m_penBlack
);
2820 int range
= end
- start
;
2821 for ( int n
= 0; n
< range
; n
+= step
)
2823 wxCoord x
= x1
+ (len
*n
) / range
;
2825 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2828 // always draw the line at the end position
2829 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2832 // ----------------------------------------------------------------------------
2834 // ----------------------------------------------------------------------------
2836 // wxMetalMenuGeometryInfo: the wxMenuGeometryInfo used by wxMetalRenderer
2837 class WXDLLEXPORT wxMetalMenuGeometryInfo
: public wxMenuGeometryInfo
2840 virtual wxSize
GetSize() const { return m_size
; }
2842 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2843 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2845 wxCoord
GetItemHeight() const { return m_heightItem
; }
2848 // the total size of the menu
2851 // the offset of the start of the menu item label
2854 // the offset of the start of the accel label
2857 // the height of a normal (not separator) item
2858 wxCoord m_heightItem
;
2860 friend wxMenuGeometryInfo
*
2861 wxMetalRenderer::GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2864 // FIXME: all constants are hardcoded but shouldn't be
2865 static const wxCoord MENU_LEFT_MARGIN
= 9;
2866 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2867 static const wxCoord MENU_VERT_MARGIN
= 3;
2869 // the margin around bitmap/check marks (on each side)
2870 static const wxCoord MENU_BMP_MARGIN
= 2;
2872 // the margin between the labels and accel strings
2873 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2875 // the separator height in pixels: in fact, strangely enough, the real height
2876 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2878 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2880 // the size of the standard checkmark bitmap
2881 static const wxCoord MENU_CHECK_SIZE
= 9;
2883 void wxMetalRenderer::DrawMenuBarItem(wxDC
& dc
,
2884 const wxRect
& rectOrig
,
2885 const wxString
& label
,
2889 wxRect rect
= rectOrig
;
2892 wxDCTextColourChanger
colChanger(dc
);
2894 if ( flags
& wxCONTROL_SELECTED
)
2896 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2898 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2899 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2900 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2901 dc
.DrawRectangle(rect
);
2904 // don't draw the focus rect around menu bar items
2905 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2906 wxALIGN_CENTRE
, indexAccel
);
2909 void wxMetalRenderer::DrawMenuItem(wxDC
& dc
,
2911 const wxMenuGeometryInfo
& gi
,
2912 const wxString
& label
,
2913 const wxString
& accel
,
2914 const wxBitmap
& bitmap
,
2918 const wxMetalMenuGeometryInfo
& geometryInfo
=
2919 (const wxMetalMenuGeometryInfo
&)gi
;
2924 rect
.width
= geometryInfo
.GetSize().x
;
2925 rect
.height
= geometryInfo
.GetItemHeight();
2927 // draw the selected item specially
2928 wxDCTextColourChanger
colChanger(dc
);
2929 if ( flags
& wxCONTROL_SELECTED
)
2931 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2933 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2934 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2935 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2936 dc
.DrawRectangle(rect
);
2939 // draw the bitmap: use the bitmap provided or the standard checkmark for
2940 // the checkable items
2941 wxBitmap bmp
= bitmap
;
2942 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2944 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2949 rect
.SetRight(geometryInfo
.GetLabelOffset());
2950 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2954 rect
.x
= geometryInfo
.GetLabelOffset();
2955 rect
.SetRight(geometryInfo
.GetAccelOffset());
2957 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2959 // draw the accel string
2960 rect
.x
= geometryInfo
.GetAccelOffset();
2961 rect
.SetRight(geometryInfo
.GetSize().x
);
2963 // NB: no accel index here
2964 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2966 // draw the submenu indicator
2967 if ( flags
& wxCONTROL_ISSUBMENU
)
2969 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2970 rect
.width
= MENU_RIGHT_MARGIN
;
2972 wxArrowStyle arrowStyle
;
2973 if ( flags
& wxCONTROL_DISABLED
)
2974 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2976 else if ( flags
& wxCONTROL_SELECTED
)
2977 arrowStyle
= Arrow_Inversed
;
2979 arrowStyle
= Arrow_Normal
;
2981 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2985 void wxMetalRenderer::DrawMenuSeparator(wxDC
& dc
,
2987 const wxMenuGeometryInfo
& geomInfo
)
2989 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2992 wxSize
wxMetalRenderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2994 wxSize size
= sizeText
;
2996 // FIXME: menubar height is configurable under Windows
3003 wxMenuGeometryInfo
*wxMetalRenderer::GetMenuGeometry(wxWindow
*win
,
3004 const wxMenu
& menu
) const
3006 // prepare the dc: for now we draw all the items with the system font
3008 dc
.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
3010 // the height of a normal item
3011 wxCoord heightText
= dc
.GetCharHeight();
3016 // the max length of label and accel strings: the menu width is the sum of
3017 // them, even if they're for different items (as the accels should be
3020 // the max length of the bitmap is never 0 as Windows always leaves enough
3021 // space for a check mark indicator
3022 wxCoord widthLabelMax
= 0,
3024 widthBmpMax
= MENU_LEFT_MARGIN
;
3026 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
3028 node
= node
->GetNext() )
3030 // height of this item
3033 wxMenuItem
*item
= node
->GetData();
3034 if ( item
->IsSeparator() )
3036 h
= MENU_SEPARATOR_HEIGHT
;
3038 else // not separator
3043 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
3044 if ( widthLabel
> widthLabelMax
)
3046 widthLabelMax
= widthLabel
;
3050 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
3051 if ( widthAccel
> widthAccelMax
)
3053 widthAccelMax
= widthAccel
;
3056 const wxBitmap
& bmp
= item
->GetBitmap();
3059 wxCoord widthBmp
= bmp
.GetWidth();
3060 if ( widthBmp
> widthBmpMax
)
3061 widthBmpMax
= widthBmp
;
3063 //else if ( item->IsCheckable() ): no need to check for this as
3064 // MENU_LEFT_MARGIN is big enough to show the check mark
3067 h
+= 2*MENU_VERT_MARGIN
;
3069 // remember the item position and height
3070 item
->SetGeometry(height
, h
);
3075 // bundle the metrics into a struct and return it
3076 wxMetalMenuGeometryInfo
*gi
= new wxMetalMenuGeometryInfo
;
3078 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
3079 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
3080 if ( widthAccelMax
> 0 )
3082 // if we actually have any accesl, add a margin
3083 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
3086 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
3088 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
3089 gi
->m_size
.y
= height
;
3094 // ----------------------------------------------------------------------------
3096 // ----------------------------------------------------------------------------
3098 static const wxCoord STATBAR_BORDER_X
= 2;
3099 static const wxCoord STATBAR_BORDER_Y
= 2;
3101 wxSize
wxMetalRenderer::GetStatusBarBorders(wxCoord
*borderBetweenFields
) const
3103 if ( borderBetweenFields
)
3104 *borderBetweenFields
= 2;
3106 return wxSize(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3109 void wxMetalRenderer::DrawStatusField(wxDC
& dc
,
3111 const wxString
& label
,
3116 if ( flags
& wxCONTROL_ISDEFAULT
)
3118 // draw the size grip: it is a normal rect except that in the lower
3119 // right corner we have several bands which may be used for dragging
3120 // the status bar corner
3122 // each band consists of 4 stripes: m_penHighlight, double
3123 // m_penDarkGrey and transparent one
3124 wxCoord x2
= rect
.GetRight(),
3125 y2
= rect
.GetBottom();
3127 // draw the upper left part of the rect normally
3128 dc
.SetPen(m_penDarkGrey
);
3129 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(), rect
.GetLeft(), y2
);
3130 dc
.DrawLine(rect
.GetLeft() + 1, rect
.GetTop(), x2
, rect
.GetTop());
3132 // draw the grey stripes of the grip
3134 wxCoord ofs
= WIDTH_STATUSBAR_GRIP_BAND
- 1;
3135 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3137 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3138 dc
.DrawLine(x2
- ofs
, y2
- 1, x2
, y2
- ofs
- 1);
3141 // draw the white stripes
3142 dc
.SetPen(m_penHighlight
);
3143 ofs
= WIDTH_STATUSBAR_GRIP_BAND
+ 1;
3144 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3146 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3149 // draw the remaining rect boundaries
3150 ofs
-= WIDTH_STATUSBAR_GRIP_BAND
;
3151 dc
.DrawLine(x2
, rect
.GetTop(), x2
, y2
- ofs
+ 1);
3152 dc
.DrawLine(rect
.GetLeft(), y2
, x2
- ofs
+ 1, y2
);
3157 rectIn
.width
-= STATUSBAR_GRIP_SIZE
;
3161 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
3164 rectIn
.Deflate(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3166 wxDCClipper
clipper(dc
, rectIn
);
3167 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3170 // ----------------------------------------------------------------------------
3172 // ----------------------------------------------------------------------------
3174 void wxMetalRenderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
3176 wxBitmap
*bmpPressed
,
3177 wxBitmap
*bmpDisabled
)
3179 static const wxCoord widthCombo
= 16;
3180 static const wxCoord heightCombo
= 17;
3186 bmpNormal
->Create(widthCombo
, heightCombo
);
3187 dcMem
.SelectObject(*bmpNormal
);
3188 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3189 Arrow_Down
, Arrow_Normal
);
3194 bmpPressed
->Create(widthCombo
, heightCombo
);
3195 dcMem
.SelectObject(*bmpPressed
);
3196 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3197 Arrow_Down
, Arrow_Pressed
);
3202 bmpDisabled
->Create(widthCombo
, heightCombo
);
3203 dcMem
.SelectObject(*bmpDisabled
);
3204 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3205 Arrow_Down
, Arrow_Disabled
);
3209 // ----------------------------------------------------------------------------
3211 // ----------------------------------------------------------------------------
3213 void wxMetalRenderer::DrawMetal(wxDC
&dc
, const wxRect
&rect
)
3215 dc
.SetPen(*wxTRANSPARENT_PEN
);
3216 for (int y
= rect
.y
; y
< rect
.height
+rect
.y
; y
++)
3218 int intens
= 230 + 80 * (rect
.y
-y
) / rect
.height
;
3219 dc
.SetBrush( wxBrush( wxColour(intens
,intens
,intens
), wxSOLID
) );
3220 dc
.DrawRectangle( rect
.x
, y
, rect
.width
, 1 );
3224 // ----------------------------------------------------------------------------
3226 // ----------------------------------------------------------------------------
3228 void wxMetalRenderer::DrawButtonSurface(wxDC
& dc
,
3229 const wxColour
& col
,
3233 DrawMetal( dc
, rect
);
3236 void wxMetalRenderer::DoDrawBackground(wxDC
& dc
,
3237 const wxColour
& col
,
3241 dc
.SetPen(*wxTRANSPARENT_PEN
);
3242 wxBrush
brush(col
, wxSOLID
);
3244 dc
.DrawRectangle(rect
);
3247 void wxMetalRenderer::DrawBackground(wxDC
& dc
,
3248 const wxColour
& col
,
3253 // just fill it with the given or default bg colour
3254 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
3255 DoDrawBackground(dc
, colBg
, rect
, window
);
3258 // ----------------------------------------------------------------------------
3260 // ----------------------------------------------------------------------------
3262 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
3267 // get the bitmap for this arrow
3268 wxArrowDirection arrowDir
;
3271 case wxLEFT
: arrowDir
= Arrow_Left
; break;
3272 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
3273 case wxUP
: arrowDir
= Arrow_Up
; break;
3274 case wxDOWN
: arrowDir
= Arrow_Down
; break;
3277 wxFAIL_MSG(_T("unknown arrow direction"));
3281 wxArrowStyle arrowStyle
;
3282 if ( flags
& wxCONTROL_PRESSED
)
3284 // can't be pressed and disabled
3285 arrowStyle
= Arrow_Pressed
;
3289 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
3292 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
3295 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
3297 wxArrowDirection arrowDir
,
3298 wxArrowStyle arrowStyle
)
3300 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
3302 // under Windows the arrows always have the same size so just centre it in
3303 // the provided rectangle
3304 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
3305 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
3307 // Windows does it like this...
3308 if ( arrowDir
== Arrow_Left
)
3312 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
3315 void wxMetalRenderer::DrawArrowButton(wxDC
& dc
,
3316 const wxRect
& rectAll
,
3317 wxArrowDirection arrowDir
,
3318 wxArrowStyle arrowStyle
)
3320 wxRect rect
= rectAll
;
3321 DrawMetal( dc
, rect
);
3322 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
3323 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
3326 void wxMetalRenderer::DrawScrollbarThumb(wxDC
& dc
,
3327 wxOrientation orient
,
3331 // we don't use the flags, the thumb never changes appearance
3332 wxRect rectThumb
= rect
;
3333 DrawArrowBorder(dc
, &rectThumb
);
3334 DrawMetal( dc
, rectThumb
);
3337 void wxMetalRenderer::DrawScrollbarShaft(wxDC
& dc
,
3338 wxOrientation orient
,
3339 const wxRect
& rectBar
,
3342 DrawMetal( dc
, rectBar
);
3345 void wxMetalRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
3347 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3350 wxRect
wxMetalRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
3351 wxScrollBar::Element elem
,
3354 return StandardGetScrollbarRect(scrollbar
, elem
,
3355 thumbPos
, m_sizeScrollbarArrow
);
3358 wxCoord
wxMetalRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
3360 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
3363 wxHitTest
wxMetalRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
3364 const wxPoint
& pt
) const
3366 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
3369 wxCoord
wxMetalRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
3372 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
3375 int wxMetalRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
3378 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
3381 // ----------------------------------------------------------------------------
3382 // top level windows
3383 // ----------------------------------------------------------------------------
3385 int wxMetalRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
3387 wxRect client
= GetFrameClientArea(rect
, flags
);
3389 if ( client
.Inside(pt
) )
3390 return wxHT_TOPLEVEL_CLIENT_AREA
;
3392 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3394 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3396 if ( flags
& wxTOPLEVEL_ICON
)
3398 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Inside(pt
) )
3399 return wxHT_TOPLEVEL_ICON
;
3402 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
3403 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
3404 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3406 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3408 if ( btnRect
.Inside(pt
) )
3409 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
3410 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
3412 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3414 if ( btnRect
.Inside(pt
) )
3415 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
3416 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3418 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3420 if ( btnRect
.Inside(pt
) )
3421 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
3422 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3424 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3426 if ( btnRect
.Inside(pt
) )
3427 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
3428 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3430 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3432 if ( btnRect
.Inside(pt
) )
3433 return wxHT_TOPLEVEL_BUTTON_HELP
;
3434 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3437 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
3438 return wxHT_TOPLEVEL_TITLEBAR
;
3441 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3443 // we are certainly at one of borders, lets decide which one:
3446 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3447 if ( pt
.x
< client
.x
)
3448 border
|= wxHT_TOPLEVEL_BORDER_W
;
3449 else if ( pt
.x
>= client
.width
+ client
.x
)
3450 border
|= wxHT_TOPLEVEL_BORDER_E
;
3451 if ( pt
.y
< client
.y
)
3452 border
|= wxHT_TOPLEVEL_BORDER_N
;
3453 else if ( pt
.y
>= client
.height
+ client
.y
)
3454 border
|= wxHT_TOPLEVEL_BORDER_S
;
3458 return wxHT_NOWHERE
;
3461 void wxMetalRenderer::DrawFrameTitleBar(wxDC
& dc
,
3463 const wxString
& title
,
3467 int specialButtonFlags
)
3469 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3471 DrawFrameBorder(dc
, rect
, flags
);
3473 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3475 DrawFrameBackground(dc
, rect
, flags
);
3476 if ( flags
& wxTOPLEVEL_ICON
)
3477 DrawFrameIcon(dc
, rect
, icon
, flags
);
3478 DrawFrameTitle(dc
, rect
, title
, flags
);
3480 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3482 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
3483 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
3485 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3487 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
3488 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
3489 specialButtonFlags
: 0);
3490 x
-= FRAME_BUTTON_WIDTH
+ 2;
3492 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3494 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
3495 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
3496 specialButtonFlags
: 0);
3497 x
-= FRAME_BUTTON_WIDTH
;
3499 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3501 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
3502 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
3503 specialButtonFlags
: 0);
3504 x
-= FRAME_BUTTON_WIDTH
;
3506 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3508 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
3509 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
3510 specialButtonFlags
: 0);
3511 x
-= FRAME_BUTTON_WIDTH
;
3513 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3515 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
3516 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
3517 specialButtonFlags
: 0);
3518 x
-= FRAME_BUTTON_WIDTH
;
3523 void wxMetalRenderer::DrawFrameBorder(wxDC
& dc
,
3527 if ( !(flags
& wxTOPLEVEL_BORDER
) ) return;
3531 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penBlack
);
3532 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penDarkGrey
);
3533 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3534 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
3535 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3538 void wxMetalRenderer::DrawFrameBackground(wxDC
& dc
,
3542 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) ) return;
3544 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3545 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE
) :
3546 wxSCHEME_COLOUR(m_scheme
, TITLEBAR
);
3548 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3549 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3551 DrawBackground(dc
, col
, r
);
3554 void wxMetalRenderer::DrawFrameTitle(wxDC
& dc
,
3556 const wxString
& title
,
3559 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3560 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE_TEXT
) :
3561 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_TEXT
);
3563 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3564 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3565 if ( flags
& wxTOPLEVEL_ICON
)
3567 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
3568 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
3576 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3577 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
3578 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3579 r
.width
-= FRAME_BUTTON_WIDTH
;
3580 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3581 r
.width
-= FRAME_BUTTON_WIDTH
;
3582 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3583 r
.width
-= FRAME_BUTTON_WIDTH
;
3584 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3585 r
.width
-= FRAME_BUTTON_WIDTH
;
3587 dc
.SetFont(m_titlebarFont
);
3588 dc
.SetTextForeground(col
);
3591 dc
.GetTextExtent(title
, &textW
, NULL
);
3592 if ( textW
> r
.width
)
3594 // text is too big, let's shorten it and add "..." after it:
3595 size_t len
= title
.length();
3596 wxCoord WSoFar
, letterW
;
3598 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
3599 if ( WSoFar
> r
.width
)
3601 // not enough space to draw anything
3607 for (size_t i
= 0; i
< len
; i
++)
3609 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
3610 if ( letterW
+ WSoFar
> r
.width
)
3616 dc
.DrawLabel(s
, wxNullBitmap
, r
,
3617 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3620 dc
.DrawLabel(title
, wxNullBitmap
, r
,
3621 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3624 void wxMetalRenderer::DrawFrameIcon(wxDC
& dc
,
3631 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3632 dc
.DrawIcon(icon
, r
.x
, r
.y
);
3636 void wxMetalRenderer::DrawFrameButton(wxDC
& dc
,
3637 wxCoord x
, wxCoord y
,
3641 wxRect
r(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3646 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
3647 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
3648 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
3649 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
3650 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
3652 wxFAIL_MSG(wxT("incorrect button specification"));
3655 if ( flags
& wxCONTROL_PRESSED
)
3657 DrawShadedRect(dc
, &r
, m_penBlack
, m_penHighlight
);
3658 DrawShadedRect(dc
, &r
, m_penDarkGrey
, m_penLightGrey
);
3659 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3660 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
+1, r
.y
+1, TRUE
);
3664 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penBlack
);
3665 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penDarkGrey
);
3666 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3667 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
, r
.y
, TRUE
);
3672 wxRect
wxMetalRenderer::GetFrameClientArea(const wxRect
& rect
,
3677 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3679 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3680 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3681 FRAME_BORDER_THICKNESS
;
3684 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3686 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
3687 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
3693 wxSize
wxMetalRenderer::GetFrameTotalSize(const wxSize
& clientSize
,
3696 wxSize
s(clientSize
);
3698 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3700 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3701 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3702 FRAME_BORDER_THICKNESS
;
3706 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3707 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3712 wxSize
wxMetalRenderer::GetFrameMinSize(int flags
) const
3716 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3718 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3719 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3720 FRAME_BORDER_THICKNESS
;
3725 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3727 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3729 if ( flags
& wxTOPLEVEL_ICON
)
3730 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
3731 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3732 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
3733 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3734 s
.x
+= FRAME_BUTTON_WIDTH
;
3735 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3736 s
.x
+= FRAME_BUTTON_WIDTH
;
3737 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3738 s
.x
+= FRAME_BUTTON_WIDTH
;
3739 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3740 s
.x
+= FRAME_BUTTON_WIDTH
;
3746 wxSize
wxMetalRenderer::GetFrameIconSize() const
3748 return wxSize(16, 16);
3752 // ----------------------------------------------------------------------------
3754 // ----------------------------------------------------------------------------
3756 static char *error_xpm
[]={
3763 "...........########.............",
3764 "........###aaaaaaaa###..........",
3765 ".......#aaaaaaaaaaaaaa#.........",
3766 ".....##aaaaaaaaaaaaaaaa##.......",
3767 "....#aaaaaaaaaaaaaaaaaaaa#......",
3768 "...#aaaaaaaaaaaaaaaaaaaaaa#.....",
3769 "...#aaaaaaaaaaaaaaaaaaaaaa#b....",
3770 "..#aaaaaacaaaaaaaaaacaaaaaa#b...",
3771 ".#aaaaaacccaaaaaaaacccaaaaaa#...",
3772 ".#aaaaacccccaaaaaacccccaaaaa#b..",
3773 ".#aaaaaacccccaaaacccccaaaaaa#bb.",
3774 "#aaaaaaaacccccaacccccaaaaaaaa#b.",
3775 "#aaaaaaaaaccccccccccaaaaaaaaa#b.",
3776 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3777 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3778 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3779 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3780 "#aaaaaaaaaccccccccccaaaaaaaaa#bb",
3781 "#aaaaaaaacccccaacccccaaaaaaaa#bb",
3782 ".#aaaaaacccccaaaacccccaaaaaa#bbb",
3783 ".#aaaaacccccaaaaaacccccaaaaa#bbb",
3784 ".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
3785 "..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
3786 "...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
3787 "...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
3788 "....#aaaaaaaaaaaaaaaaaaaa#bbb...",
3789 ".....##aaaaaaaaaaaaaaaa##bbbb...",
3790 "......b#aaaaaaaaaaaaaa#bbbbb....",
3791 ".......b###aaaaaaaa###bbbbb.....",
3792 ".........bb########bbbbbb.......",
3793 "..........bbbbbbbbbbbbbb........",
3794 ".............bbbbbbbb..........."};
3796 static char *info_xpm
[]={
3804 "...........########.............",
3805 "........###abbbbbba###..........",
3806 "......##abbbbbbbbbbbba##........",
3807 ".....#abbbbbbbbbbbbbbbba#.......",
3808 "....#bbbbbbbaccccabbbbbbbd......",
3809 "...#bbbbbbbbccccccbbbbbbbbd.....",
3810 "..#bbbbbbbbbccccccbbbbbbbbbd....",
3811 ".#abbbbbbbbbaccccabbbbbbbbbad...",
3812 ".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
3813 "#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
3814 "#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
3815 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3816 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3817 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3818 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3819 "#abbbbbbbbbbbcccccbbbbbbbbbbad##",
3820 ".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
3821 ".#abbbbbbbbbbcccccbbbbbbbbbad###",
3822 "..#bbbbbbbbcccccccccbbbbbbbd###.",
3823 "...dbbbbbbbbbbbbbbbbbbbbbbd####.",
3824 "....dbbbbbbbbbbbbbbbbbbbbd####..",
3825 ".....dabbbbbbbbbbbbbbbbad####...",
3826 "......ddabbbbbbbbbbbbadd####....",
3827 ".......#dddabbbbbbaddd#####.....",
3828 "........###dddabbbd#######......",
3829 "..........####dbbbd#####........",
3830 ".............#dbbbd##...........",
3831 "...............dbbd##...........",
3832 "................dbd##...........",
3833 ".................dd##...........",
3834 "..................###...........",
3835 "...................##..........."};
3837 static char *question_xpm
[]={
3845 "...........########.............",
3846 "........###abbbbbba###..........",
3847 "......##abbbbbbbbbbbba##........",
3848 ".....#abbbbbbbbbbbbbbbba#.......",
3849 "....#bbbbbbbbbbbbbbbbbbbbc......",
3850 "...#bbbbbbbaddddddabbbbbbbc.....",
3851 "..#bbbbbbbadabbddddabbbbbbbc....",
3852 ".#abbbbbbbddbbbbddddbbbbbbbac...",
3853 ".#bbbbbbbbddddbbddddbbbbbbbbc#..",
3854 "#abbbbbbbbddddbaddddbbbbbbbbac#.",
3855 "#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
3856 "#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
3857 "#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
3858 "#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
3859 "#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
3860 "#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
3861 ".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
3862 ".#abbbbbbbbbbddddbbbbbbbbbbac###",
3863 "..#bbbbbbbbbbddddbbbbbbbbbbc###.",
3864 "...cbbbbbbbbbaddabbbbbbbbbc####.",
3865 "....cbbbbbbbbbbbbbbbbbbbbc####..",
3866 ".....cabbbbbbbbbbbbbbbbac####...",
3867 "......ccabbbbbbbbbbbbacc####....",
3868 ".......#cccabbbbbbaccc#####.....",
3869 "........###cccabbbc#######......",
3870 "..........####cbbbc#####........",
3871 ".............#cbbbc##...........",
3872 "...............cbbc##...........",
3873 "................cbc##...........",
3874 ".................cc##...........",
3875 "..................###...........",
3876 "...................##..........."};
3878 static char *warning_xpm
[]={
3886 ".............###................",
3887 "............#aabc...............",
3888 "...........#aaaabcd.............",
3889 "...........#aaaaacdd............",
3890 "..........#aaaaaabcdd...........",
3891 "..........#aaaaaaacdd...........",
3892 ".........#aaaaaaaabcdd..........",
3893 ".........#aaaaaaaaacdd..........",
3894 "........#aaaaaaaaaabcdd.........",
3895 "........#aaabcccbaaacdd.........",
3896 ".......#aaaacccccaaabcdd........",
3897 ".......#aaaacccccaaaacdd........",
3898 "......#aaaaacccccaaaabcdd.......",
3899 "......#aaaaacccccaaaaacdd.......",
3900 ".....#aaaaaacccccaaaaabcdd......",
3901 ".....#aaaaaa#ccc#aaaaaacdd......",
3902 "....#aaaaaaabcccbaaaaaabcdd.....",
3903 "....#aaaaaaaacccaaaaaaaacdd.....",
3904 "...#aaaaaaaaa#c#aaaaaaaabcdd....",
3905 "...#aaaaaaaaabcbaaaaaaaaacdd....",
3906 "..#aaaaaaaaaaacaaaaaaaaaabcdd...",
3907 "..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
3908 ".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
3909 ".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
3910 "#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
3911 "#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
3912 "#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
3913 "#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
3914 ".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
3915 "..#ccccccccccccccccccccccccddddd",
3916 "....ddddddddddddddddddddddddddd.",
3917 ".....ddddddddddddddddddddddddd.."};
3919 wxBitmap
wxMetalArtProvider::CreateBitmap(const wxArtID
& id
,
3920 const wxArtClient
& WXUNUSED(client
),
3921 const wxSize
& WXUNUSED(size
))
3923 if ( id
== wxART_INFORMATION
)
3924 return wxBitmap(info_xpm
);
3925 if ( id
== wxART_ERROR
)
3926 return wxBitmap(error_xpm
);
3927 if ( id
== wxART_WARNING
)
3928 return wxBitmap(warning_xpm
);
3929 if ( id
== wxART_QUESTION
)
3930 return wxBitmap(question_xpm
);
3931 return wxNullBitmap
;
3935 // ----------------------------------------------------------------------------
3936 // text control geometry
3937 // ----------------------------------------------------------------------------
3939 static inline int GetTextBorderWidth()
3944 wxRect
wxMetalRenderer::GetTextTotalArea(const wxTextCtrl
*text
,
3945 const wxRect
& rect
) const
3947 wxRect rectTotal
= rect
;
3949 wxCoord widthBorder
= GetTextBorderWidth();
3950 rectTotal
.Inflate(widthBorder
);
3952 // this is what Windows does
3958 wxRect
wxMetalRenderer::GetTextClientArea(const wxTextCtrl
*text
,
3960 wxCoord
*extraSpaceBeyond
) const
3962 wxRect rectText
= rect
;
3964 // undo GetTextTotalArea()
3965 if ( rectText
.height
> 0 )
3968 wxCoord widthBorder
= GetTextBorderWidth();
3969 rectText
.Inflate(-widthBorder
);
3971 if ( extraSpaceBeyond
)
3972 *extraSpaceBeyond
= 0;
3977 // ----------------------------------------------------------------------------
3979 // ----------------------------------------------------------------------------
3981 void wxMetalRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
3984 if ( wxDynamicCast(window
, wxScrollBar
) )
3986 // we only set the width of vert scrollbars and height of the
3988 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3989 size
->y
= m_sizeScrollbarArrow
.y
;
3991 size
->x
= m_sizeScrollbarArrow
.x
;
3993 // skip border width adjustments, they don't make sense for us
3996 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3999 if ( wxDynamicCast(window
, wxButton
) )
4001 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
4003 // TODO: don't harcode all this
4004 size
->x
+= 3*window
->GetCharWidth();
4006 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
4007 if ( size
->y
< heightBtn
- 8 )
4008 size
->y
= heightBtn
;
4013 // no border width adjustments for buttons
4016 #endif // wxUSE_BUTTON
4018 // take into account the border width
4019 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
4020 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
4021 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
4024 // ============================================================================
4026 // ============================================================================
4028 // ----------------------------------------------------------------------------
4029 // wxMetalInputHandler
4030 // ----------------------------------------------------------------------------
4032 wxMetalInputHandler::wxMetalInputHandler(wxMetalRenderer
*renderer
)
4034 m_renderer
= renderer
;
4037 bool wxMetalInputHandler::HandleKey(wxInputConsumer
*control
,
4038 const wxKeyEvent
& event
,
4044 bool wxMetalInputHandler::HandleMouse(wxInputConsumer
*control
,
4045 const wxMouseEvent
& event
)
4047 // clicking on the control gives it focus
4048 if ( event
.ButtonDown() )
4050 wxWindow
*win
= control
->GetInputWindow();
4052 if (( wxWindow::FindFocus() != control
->GetInputWindow() ) &&
4053 ( win
->AcceptsFocus() ) )
4064 // ----------------------------------------------------------------------------
4065 // wxMetalScrollBarInputHandler
4066 // ----------------------------------------------------------------------------
4068 wxMetalScrollBarInputHandler::
4069 wxMetalScrollBarInputHandler(wxMetalRenderer
*renderer
,
4070 wxInputHandler
*handler
)
4071 : wxStdScrollBarInputHandler(renderer
, handler
)
4073 m_scrollPaused
= FALSE
;
4077 bool wxMetalScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
4078 const wxControlAction
& action
)
4080 // stop if went beyond the position of the original click (this can only
4081 // happen when we scroll by pages)
4083 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
4085 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4086 != wxHT_SCROLLBAR_BAR_2
;
4088 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
4090 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4091 != wxHT_SCROLLBAR_BAR_1
;
4096 StopScrolling(scrollbar
);
4098 scrollbar
->Refresh();
4103 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
4106 bool wxMetalScrollBarInputHandler::HandleMouse(wxInputConsumer
*control
,
4107 const wxMouseEvent
& event
)
4109 // remember the current state
4110 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
4112 // do process the message
4113 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
4115 // analyse the changes
4116 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
4118 // we just started dragging the thumb, remember its initial position to
4119 // be able to restore it if the drag is cancelled later
4120 m_eventStartDrag
= event
;
4126 bool wxMetalScrollBarInputHandler::HandleMouseMove(wxInputConsumer
*control
,
4127 const wxMouseEvent
& event
)
4129 // we don't highlight scrollbar elements, so there is no need to process
4130 // mouse move events normally - only do it while mouse is captured (i.e.
4131 // when we're dragging the thumb or pressing on something)
4132 if ( !m_winCapture
)
4135 if ( event
.Entering() )
4137 // we're not interested in this at all
4141 wxScrollBar
*scrollbar
= wxStaticCast(control
->GetInputWindow(), wxScrollBar
);
4143 if ( m_scrollPaused
)
4145 // check if the mouse returned to its original location
4147 if ( event
.Leaving() )
4153 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4154 if ( ht
== m_htLast
)
4156 // yes it did, resume scrolling
4157 m_scrollPaused
= FALSE
;
4158 if ( m_timerScroll
)
4160 // we were scrolling by line/page, restart timer
4161 m_timerScroll
->Start(m_interval
);
4163 Press(scrollbar
, TRUE
);
4165 else // we were dragging the thumb
4167 // restore its last location
4168 HandleThumbMove(scrollbar
, m_eventLastDrag
);
4174 else // normal case, scrolling hasn't been paused
4176 // if we're scrolling the scrollbar because the arrow or the shaft was
4177 // pressed, check that the mouse stays on the same scrollbar element
4180 // Always let thumb jump back if we leave the scrollbar
4181 if ( event
.Moving() )
4183 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4185 else // event.Leaving()
4190 // Jump back only if we get far away from it
4191 wxPoint pos
= event
.GetPosition();
4192 if (scrollbar
->HasFlag( wxVERTICAL
))
4194 if (pos
.x
> -40 && pos
.x
< scrollbar
->GetSize().x
+40)
4199 if (pos
.y
> -40 && pos
.y
< scrollbar
->GetSize().y
+40)
4202 ht
= m_renderer
->HitTestScrollbar(scrollbar
, pos
);
4205 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4206 // is still ok - we only want to catch the case when the mouse leaves
4207 // the scrollbar here
4208 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
4210 ht
= wxHT_SCROLLBAR_THUMB
;
4213 if ( ht
!= m_htLast
)
4215 // what were we doing? 2 possibilities: either an arrow/shaft was
4216 // pressed in which case we have a timer and so we just stop it or
4217 // we were dragging the thumb
4218 if ( m_timerScroll
)
4221 m_interval
= m_timerScroll
->GetInterval();
4222 m_timerScroll
->Stop();
4223 m_scrollPaused
= TRUE
;
4225 // unpress the arrow
4226 Press(scrollbar
, FALSE
);
4228 else // we were dragging the thumb
4230 // remember the current thumb position to be able to restore it
4231 // if the mouse returns to it later
4232 m_eventLastDrag
= event
;
4234 // and restore the original position (before dragging) of the
4236 HandleThumbMove(scrollbar
, m_eventStartDrag
);
4243 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
4246 // ----------------------------------------------------------------------------
4247 // wxMetalCheckboxInputHandler
4248 // ----------------------------------------------------------------------------
4250 bool wxMetalCheckboxInputHandler::HandleKey(wxInputConsumer
*control
,
4251 const wxKeyEvent
& event
,
4256 wxControlAction action
;
4257 int keycode
= event
.GetKeyCode();
4261 action
= wxACTION_CHECKBOX_TOGGLE
;
4265 case WXK_NUMPAD_SUBTRACT
:
4266 action
= wxACTION_CHECKBOX_CHECK
;
4270 case WXK_NUMPAD_ADD
:
4271 case WXK_NUMPAD_EQUAL
:
4272 action
= wxACTION_CHECKBOX_CLEAR
;
4278 control
->PerformAction(action
);
4287 // ----------------------------------------------------------------------------
4288 // wxMetalTextCtrlInputHandler
4289 // ----------------------------------------------------------------------------
4291 bool wxMetalTextCtrlInputHandler::HandleKey(wxInputConsumer
*control
,
4292 const wxKeyEvent
& event
,
4295 // handle only MSW-specific text bindings here, the others are handled in
4299 int keycode
= event
.GetKeyCode();
4301 wxControlAction action
;
4302 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
4304 action
= wxACTION_TEXT_CUT
;
4306 else if ( keycode
== WXK_INSERT
)
4308 if ( event
.ControlDown() )
4309 action
= wxACTION_TEXT_COPY
;
4310 else if ( event
.ShiftDown() )
4311 action
= wxACTION_TEXT_PASTE
;
4314 if ( action
!= wxACTION_NONE
)
4316 control
->PerformAction(action
);
4322 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);
4325 // ----------------------------------------------------------------------------
4326 // wxMetalStatusBarInputHandler
4327 // ----------------------------------------------------------------------------
4329 wxMetalStatusBarInputHandler::
4330 wxMetalStatusBarInputHandler(wxInputHandler
*handler
)
4331 : wxStdInputHandler(handler
)
4336 bool wxMetalStatusBarInputHandler::IsOnGrip(wxWindow
*statbar
,
4337 const wxPoint
& pt
) const
4339 if ( statbar
->HasFlag(wxST_SIZEGRIP
) &&
4340 statbar
->GetParent()->HasFlag(wxRESIZE_BORDER
) )
4343 parentTLW
= wxDynamicCast(statbar
->GetParent(), wxTopLevelWindow
);
4345 wxCHECK_MSG( parentTLW
, FALSE
,
4346 _T("the status bar should be a child of a TLW") );
4348 // a maximized window can't be resized anyhow
4349 if ( !parentTLW
->IsMaximized() )
4351 // VZ: I think that the standard Windows behaviour is to only
4352 // show the resizing cursor when the mouse is on top of the
4353 // grip itself but apparently different Windows versions behave
4354 // differently (?) and it seems a better UI to allow resizing
4355 // the status bar even when the mouse is above the grip
4356 wxSize sizeSbar
= statbar
->GetSize();
4358 int diff
= sizeSbar
.x
- pt
.x
;
4359 return diff
>= 0 && diff
< (wxCoord
)STATUSBAR_GRIP_SIZE
;
4366 bool wxMetalStatusBarInputHandler::HandleMouse(wxInputConsumer
*consumer
,
4367 const wxMouseEvent
& event
)
4369 if ( event
.Button(1) )
4371 if ( event
.ButtonDown(1) )
4373 wxWindow
*statbar
= consumer
->GetInputWindow();
4375 if ( IsOnGrip(statbar
, event
.GetPosition()) )
4377 wxTopLevelWindow
*tlw
= wxDynamicCast(statbar
->GetParent(),
4381 tlw
->PerformAction(wxACTION_TOPLEVEL_RESIZE
,
4382 wxHT_TOPLEVEL_BORDER_SE
);
4384 statbar
->SetCursor(m_cursorOld
);
4392 return wxStdInputHandler::HandleMouse(consumer
, event
);
4395 bool wxMetalStatusBarInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
4396 const wxMouseEvent
& event
)
4398 wxWindow
*statbar
= consumer
->GetInputWindow();
4400 bool isOnGrip
= IsOnGrip(statbar
, event
.GetPosition());
4401 if ( isOnGrip
!= m_isOnGrip
)
4403 m_isOnGrip
= isOnGrip
;
4406 m_cursorOld
= statbar
->GetCursor();
4407 statbar
->SetCursor(wxCURSOR_SIZENWSE
);
4411 statbar
->SetCursor(m_cursorOld
);
4415 return wxStdInputHandler::HandleMouseMove(consumer
, event
);
4418 // ----------------------------------------------------------------------------
4419 // wxMetalFrameInputHandler
4420 // ----------------------------------------------------------------------------
4422 class wxMetalSystemMenuEvtHandler
: public wxEvtHandler
4425 wxMetalSystemMenuEvtHandler(wxMetalFrameInputHandler
*handler
);
4427 void Attach(wxInputConsumer
*consumer
);
4431 DECLARE_EVENT_TABLE()
4432 void OnSystemMenu(wxCommandEvent
&event
);
4433 void OnCloseFrame(wxCommandEvent
&event
);
4434 void OnClose(wxCloseEvent
&event
);
4436 wxMetalFrameInputHandler
*m_inputHnd
;
4437 wxTopLevelWindow
*m_wnd
;
4438 wxAcceleratorTable m_oldAccelTable
;
4441 wxMetalSystemMenuEvtHandler::wxMetalSystemMenuEvtHandler(
4442 wxMetalFrameInputHandler
*handler
)
4444 m_inputHnd
= handler
;
4448 void wxMetalSystemMenuEvtHandler::Attach(wxInputConsumer
*consumer
)
4450 wxASSERT_MSG( m_wnd
== NULL
, _T("can't attach the handler twice!") );
4452 m_wnd
= wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4453 m_wnd
->PushEventHandler(this);
4455 // VS: This code relies on using generic implementation of
4456 // wxAcceleratorTable in wxUniv!
4457 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4458 m_oldAccelTable
= table
;
4459 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_SPACE
, wxID_SYSTEM_MENU
));
4460 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_F4
, wxID_CLOSE_FRAME
));
4461 m_wnd
->SetAcceleratorTable(table
);
4464 void wxMetalSystemMenuEvtHandler::Detach()
4468 m_wnd
->SetAcceleratorTable(m_oldAccelTable
);
4469 m_wnd
->RemoveEventHandler(this);
4474 BEGIN_EVENT_TABLE(wxMetalSystemMenuEvtHandler
, wxEvtHandler
)
4475 EVT_MENU(wxID_SYSTEM_MENU
, wxMetalSystemMenuEvtHandler::OnSystemMenu
)
4476 EVT_MENU(wxID_CLOSE_FRAME
, wxMetalSystemMenuEvtHandler::OnCloseFrame
)
4477 EVT_CLOSE(wxMetalSystemMenuEvtHandler::OnClose
)
4480 void wxMetalSystemMenuEvtHandler::OnSystemMenu(wxCommandEvent
&WXUNUSED(event
))
4482 int border
= ((m_wnd
->GetWindowStyle() & wxRESIZE_BORDER
) &&
4483 !m_wnd
->IsMaximized()) ?
4484 RESIZEABLE_FRAME_BORDER_THICKNESS
:
4485 FRAME_BORDER_THICKNESS
;
4486 wxPoint pt
= m_wnd
->GetClientAreaOrigin();
4487 pt
.x
= -pt
.x
+ border
;
4488 pt
.y
= -pt
.y
+ border
+ FRAME_TITLEBAR_HEIGHT
;
4490 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4491 m_wnd
->SetAcceleratorTable(wxNullAcceleratorTable
);
4492 m_inputHnd
->PopupSystemMenu(m_wnd
, pt
);
4493 m_wnd
->SetAcceleratorTable(table
);
4496 void wxMetalSystemMenuEvtHandler::OnCloseFrame(wxCommandEvent
&WXUNUSED(event
))
4498 m_wnd
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4499 wxTOPLEVEL_BUTTON_CLOSE
);
4502 void wxMetalSystemMenuEvtHandler::OnClose(wxCloseEvent
&event
)
4509 wxMetalFrameInputHandler::wxMetalFrameInputHandler(wxInputHandler
*handler
)
4510 : wxStdFrameInputHandler(handler
)
4512 m_menuHandler
= new wxMetalSystemMenuEvtHandler(this);
4515 wxMetalFrameInputHandler::~wxMetalFrameInputHandler()
4517 if ( m_menuHandler
)
4519 m_menuHandler
->Detach();
4520 delete m_menuHandler
;
4524 bool wxMetalFrameInputHandler::HandleMouse(wxInputConsumer
*consumer
,
4525 const wxMouseEvent
& event
)
4527 if ( event
.LeftDClick() || event
.LeftDown() || event
.RightDown() )
4529 wxTopLevelWindow
*tlw
=
4530 wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4532 long hit
= tlw
->HitTest(event
.GetPosition());
4534 if ( event
.LeftDClick() && hit
== wxHT_TOPLEVEL_TITLEBAR
)
4536 tlw
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4537 tlw
->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4538 : wxTOPLEVEL_BUTTON_MAXIMIZE
);
4541 else if ( tlw
->GetWindowStyle() & wxSYSTEM_MENU
)
4543 if ( (event
.LeftDown() && hit
== wxHT_TOPLEVEL_ICON
) ||
4544 (event
.RightDown() &&
4545 (hit
== wxHT_TOPLEVEL_TITLEBAR
||
4546 hit
== wxHT_TOPLEVEL_ICON
)) )
4548 PopupSystemMenu(tlw
, event
.GetPosition());
4554 return wxStdFrameInputHandler::HandleMouse(consumer
, event
);
4557 void wxMetalFrameInputHandler::PopupSystemMenu(wxTopLevelWindow
*window
,
4558 const wxPoint
& pos
) const
4560 wxMenu
*menu
= new wxMenu
;
4562 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4563 menu
->Append(wxID_RESTORE_FRAME
, _("&Restore"));
4564 menu
->Append(wxID_MOVE_FRAME
, _("&Move"));
4565 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4566 menu
->Append(wxID_RESIZE_FRAME
, _("&Size"));
4567 if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME
) )
4568 menu
->Append(wxID_ICONIZE_FRAME
, _("Mi&nimize"));
4569 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4570 menu
->Append(wxID_MAXIMIZE_FRAME
, _("Ma&ximize"));
4571 menu
->AppendSeparator();
4572 menu
->Append(wxID_CLOSE_FRAME
, _("Close\tAlt-F4"));
4574 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4576 if ( window
->IsMaximized() )
4578 menu
->Enable(wxID_MAXIMIZE_FRAME
, FALSE
);
4579 menu
->Enable(wxID_MOVE_FRAME
, FALSE
);
4580 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4581 menu
->Enable(wxID_RESIZE_FRAME
, FALSE
);
4584 menu
->Enable(wxID_RESTORE_FRAME
, FALSE
);
4587 window
->PopupMenu(menu
, pos
);
4591 bool wxMetalFrameInputHandler::HandleActivation(wxInputConsumer
*consumer
,
4594 if ( consumer
->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU
)
4596 // always detach if active frame changed:
4597 m_menuHandler
->Detach();
4601 m_menuHandler
->Attach(consumer
);
4605 return wxStdFrameInputHandler::HandleActivation(consumer
, activated
);