]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/renderer.cpp
make renderer independent of windowing system
[wxWidgets.git] / src / mac / carbon / renderer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/renderer.cpp
3 // Purpose: implementation of wxRendererNative for Mac
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 20.07.2003
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // for compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/string.h"
21 #include "wx/dc.h"
22 #include "wx/bitmap.h"
23 #include "wx/settings.h"
24 #include "wx/dcclient.h"
25 #include "wx/toplevel.h"
26 #endif
27
28 #include "wx/renderer.h"
29 #include "wx/graphics.h"
30 #include "wx/mac/uma.h"
31
32
33 class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
34 {
35 public:
36 // draw the header control button (used by wxListCtrl)
37 virtual int DrawHeaderButton( wxWindow *win,
38 wxDC& dc,
39 const wxRect& rect,
40 int flags = 0,
41 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
42 wxHeaderButtonParams* params = NULL );
43
44 virtual int GetHeaderButtonHeight(wxWindow *win);
45
46 // draw the expanded/collapsed icon for a tree control item
47 virtual void DrawTreeItemButton( wxWindow *win,
48 wxDC& dc,
49 const wxRect& rect,
50 int flags = 0 );
51
52 // draw a (vertical) sash
53 virtual void DrawSplitterSash( wxWindow *win,
54 wxDC& dc,
55 const wxSize& size,
56 wxCoord position,
57 wxOrientation orient,
58 int flags = 0 );
59
60 virtual void DrawCheckBox(wxWindow *win,
61 wxDC& dc,
62 const wxRect& rect,
63 int flags = 0);
64
65 virtual void DrawComboBoxDropButton(wxWindow *win,
66 wxDC& dc,
67 const wxRect& rect,
68 int flags = 0);
69
70 virtual void DrawPushButton(wxWindow *win,
71 wxDC& dc,
72 const wxRect& rect,
73 int flags = 0);
74
75 virtual void DrawItemSelectionRect(wxWindow *win,
76 wxDC& dc,
77 const wxRect& rect,
78 int flags = 0);
79
80 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
81
82 private:
83 void DrawMacThemeButton(wxWindow *win,
84 wxDC& dc,
85 const wxRect& rect,
86 int flags,
87 int kind,
88 int adornment);
89
90 // the tree buttons
91 wxBitmap m_bmpTreeExpanded;
92 wxBitmap m_bmpTreeCollapsed;
93 };
94
95 // ============================================================================
96 // implementation
97 // ============================================================================
98
99 // static
100 wxRendererNative& wxRendererNative::GetDefault()
101 {
102 static wxRendererMac s_rendererMac;
103
104 return s_rendererMac;
105 }
106
107 int wxRendererMac::DrawHeaderButton( wxWindow *win,
108 wxDC& dc,
109 const wxRect& rect,
110 int flags,
111 wxHeaderSortIconType sortArrow,
112 wxHeaderButtonParams* params )
113 {
114 const wxCoord x = rect.x;
115 const wxCoord y = rect.y;
116 const wxCoord w = rect.width;
117 const wxCoord h = rect.height;
118
119 dc.SetBrush( *wxTRANSPARENT_BRUSH );
120
121 HIRect headerRect = CGRectMake( x, y, w, h );
122 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
123 {
124 win->Refresh( &rect );
125 }
126 else
127 {
128 CGContextRef cgContext;
129
130 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
131
132 {
133 HIThemeButtonDrawInfo drawInfo;
134 HIRect labelRect;
135
136 memset( &drawInfo, 0, sizeof(drawInfo) );
137 drawInfo.version = 0;
138 drawInfo.kind = kThemeListHeaderButton;
139 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
140 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
141 drawInfo.adornment = kThemeAdornmentNone;
142
143 // The down arrow is drawn automatically, change it to an up arrow if needed.
144 if ( sortArrow == wxHDR_SORT_ICON_UP )
145 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
146
147 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
148
149 // If we don't want any arrows we need to draw over the one already there
150 if ( (flags & wxCONTROL_SELECTED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
151 {
152 // clip to the header rectangle
153 CGContextSaveGState( cgContext );
154 CGContextClipToRect( cgContext, headerRect );
155 // but draw bigger than that so the arrow will get clipped off
156 headerRect.size.width += 25;
157 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
158 CGContextRestoreGState( cgContext );
159 }
160 }
161 }
162
163 // Reserve room for the arrows before writing the label, and turn off the
164 // flags we've already handled
165 wxRect newRect(rect);
166 if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
167 {
168 newRect.width -= 12;
169 sortArrow = wxHDR_SORT_ICON_NONE;
170 }
171 flags &= ~wxCONTROL_SELECTED;
172
173 return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
174 }
175
176
177 int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
178 {
179 SInt32 standardHeight;
180 OSStatus errStatus;
181
182 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
183 if (errStatus == noErr)
184 {
185 return standardHeight;
186 }
187 return -1;
188 }
189
190 void wxRendererMac::DrawTreeItemButton( wxWindow *win,
191 wxDC& dc,
192 const wxRect& rect,
193 int flags )
194 {
195 // now the wxGCDC is using native transformations
196 const wxCoord x = rect.x;
197 const wxCoord y = rect.y;
198 const wxCoord w = rect.width;
199 const wxCoord h = rect.height;
200
201 dc.SetBrush( *wxTRANSPARENT_BRUSH );
202
203 HIRect headerRect = CGRectMake( x, y, w, h );
204 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
205 {
206 win->Refresh( &rect );
207 }
208 else
209 {
210 CGContextRef cgContext;
211
212 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
213
214 HIThemeButtonDrawInfo drawInfo;
215 HIRect labelRect;
216
217 memset( &drawInfo, 0, sizeof(drawInfo) );
218 drawInfo.version = 0;
219 drawInfo.kind = kThemeDisclosureButton;
220 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
221 // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
222 // We need to set the value using the 'old' DrawThemeButton constants instead.
223 drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
224 drawInfo.adornment = kThemeAdornmentNone;
225
226 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
227 }
228 }
229
230 void wxRendererMac::DrawSplitterSash( wxWindow *win,
231 wxDC& dc,
232 const wxSize& size,
233 wxCoord position,
234 wxOrientation orient,
235 int WXUNUSED(flags) )
236 {
237 bool hasMetal = win->MacGetTopLevelWindow()->MacGetMetalAppearance();
238 SInt32 height;
239 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
240 HIRect splitterRect;
241 if (orient == wxVERTICAL)
242 splitterRect = CGRectMake( position, 0, height, size.y );
243 else
244 splitterRect = CGRectMake( 0, position, size.x, height );
245
246 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
247 // strange redraw errors occur if we don't do this
248
249 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
250 {
251 wxRect rect( splitterRect.origin.x, splitterRect.origin.y, splitterRect.size.width, splitterRect.size.height );
252 win->Refresh( &rect );
253 }
254 else
255 {
256 CGContextRef cgContext;
257
258 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
259
260 HIThemeSplitterDrawInfo drawInfo;
261 drawInfo.version = 0;
262 drawInfo.state = kThemeStateActive;
263 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
264 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
265 }
266 }
267
268 void
269 wxRendererMac::DrawItemSelectionRect(wxWindow *win,
270 wxDC& dc,
271 const wxRect& rect,
272 int flags )
273 {
274 if ( !(flags & wxCONTROL_SELECTED) )
275 return;
276
277 wxBrush selBrush(wxColour( wxMacCreateCGColorFromHITheme( flags & wxCONTROL_FOCUSED ?
278 kThemeBrushAlternatePrimaryHighlightColor
279 : kThemeBrushSecondaryHighlightColor ) ) , wxSOLID );
280
281 dc.SetPen( *wxTRANSPARENT_PEN );
282 dc.SetBrush( selBrush );
283 dc.DrawRectangle( rect );
284 }
285
286
287 void
288 wxRendererMac::DrawMacThemeButton(wxWindow *win,
289 wxDC& dc,
290 const wxRect& rect,
291 int flags,
292 int kind,
293 int adornment)
294 {
295 // now the wxGCDC is using native transformations
296 const wxCoord x = rect.x;
297 const wxCoord y = rect.y;
298 const wxCoord w = rect.width;
299 const wxCoord h = rect.height;
300
301 dc.SetBrush( *wxTRANSPARENT_BRUSH );
302
303 HIRect headerRect = CGRectMake( x, y, w, h );
304 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
305 {
306 win->Refresh( &rect );
307 }
308 else
309 {
310 CGContextRef cgContext;
311 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
312
313 HIThemeButtonDrawInfo drawInfo;
314 HIRect labelRect;
315
316 memset( &drawInfo, 0, sizeof(drawInfo) );
317 drawInfo.version = 0;
318 drawInfo.kind = kind;
319 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
320 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
321 if (flags & wxCONTROL_UNDETERMINED)
322 drawInfo.value = kThemeButtonMixed;
323 drawInfo.adornment = adornment;
324
325 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
326 }
327 }
328
329 void
330 wxRendererMac::DrawCheckBox(wxWindow *win,
331 wxDC& dc,
332 const wxRect& rect,
333 int flags)
334 {
335 if (flags & wxCONTROL_CHECKED)
336 flags |= wxCONTROL_SELECTED;
337
338 DrawMacThemeButton(win, dc, rect, flags,
339 kThemeCheckBox, kThemeAdornmentNone);
340 }
341
342 void
343 wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
344 wxDC& dc,
345 const wxRect& rect,
346 int flags)
347 {
348 int kind;
349 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
350 kind = kThemeArrowButtonSmall;
351 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
352 kind = kThemeArrowButtonMini;
353 else
354 kind = kThemeArrowButton;
355
356 DrawMacThemeButton(win, dc, rect, flags,
357 kind, kThemeAdornmentArrowDownArrow);
358 }
359
360 void
361 wxRendererMac::DrawPushButton(wxWindow *win,
362 wxDC& dc,
363 const wxRect& rect,
364 int flags)
365 {
366 int kind;
367 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
368 kind = kThemeBevelButtonSmall;
369 // There is no kThemeBevelButtonMini, but in this case, use Small
370 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
371 kind = kThemeBevelButtonSmall;
372 else
373 kind = kThemeBevelButton;
374
375 DrawMacThemeButton(win, dc, rect, flags,
376 kind, kThemeAdornmentNone);
377 }
378
379 void
380 wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
381 {
382 if (!win)
383 {
384 wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
385 return;
386 }
387
388 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
389
390 HIThemeFrameDrawInfo info ;
391 memset( &info, 0 , sizeof(info) ) ;
392
393 info.version = 0 ;
394 info.kind = 0 ;
395 info.state = kThemeStateActive;
396 info.isFocused = true ;
397
398 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
399 wxASSERT( cgContext ) ;
400
401 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
402 }
403