]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/renderer.cpp
CGFloat
[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 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
130
131 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
132
133 {
134 HIThemeButtonDrawInfo drawInfo;
135 HIRect labelRect;
136
137 memset( &drawInfo, 0, sizeof(drawInfo) );
138 drawInfo.version = 0;
139 drawInfo.kind = kThemeListHeaderButton;
140 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
141 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
142 drawInfo.adornment = kThemeAdornmentNone;
143
144 // The down arrow is drawn automatically, change it to an up arrow if needed.
145 if ( sortArrow == wxHDR_SORT_ICON_UP )
146 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
147
148 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
149
150 // If we don't want any arrows we need to draw over the one already there
151 if ( (flags & wxCONTROL_SELECTED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
152 {
153 // clip to the header rectangle
154 CGContextSaveGState( cgContext );
155 CGContextClipToRect( cgContext, headerRect );
156 // but draw bigger than that so the arrow will get clipped off
157 headerRect.size.width += 25;
158 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
159 CGContextRestoreGState( cgContext );
160 }
161 }
162 }
163
164 // Reserve room for the arrows before writing the label, and turn off the
165 // flags we've already handled
166 wxRect newRect(rect);
167 if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
168 {
169 newRect.width -= 12;
170 sortArrow = wxHDR_SORT_ICON_NONE;
171 }
172 flags &= ~wxCONTROL_SELECTED;
173
174 return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
175 }
176
177
178 int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
179 {
180 SInt32 standardHeight;
181 OSStatus errStatus;
182
183 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
184 if (errStatus == noErr)
185 {
186 return standardHeight;
187 }
188 return -1;
189 }
190
191 void wxRendererMac::DrawTreeItemButton( wxWindow *win,
192 wxDC& dc,
193 const wxRect& rect,
194 int flags )
195 {
196 // now the wxGCDC is using native transformations
197 const wxCoord x = rect.x;
198 const wxCoord y = rect.y;
199 const wxCoord w = rect.width;
200 const wxCoord h = rect.height;
201
202 dc.SetBrush( *wxTRANSPARENT_BRUSH );
203
204 HIRect headerRect = CGRectMake( x, y, w, h );
205 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
206 {
207 win->Refresh( &rect );
208 }
209 else
210 {
211 CGContextRef cgContext;
212
213 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
214 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
215
216 HIThemeButtonDrawInfo drawInfo;
217 HIRect labelRect;
218
219 memset( &drawInfo, 0, sizeof(drawInfo) );
220 drawInfo.version = 0;
221 drawInfo.kind = kThemeDisclosureButton;
222 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
223 // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
224 // We need to set the value using the 'old' DrawThemeButton constants instead.
225 drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
226 drawInfo.adornment = kThemeAdornmentNone;
227
228 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
229 }
230 }
231
232 void wxRendererMac::DrawSplitterSash( wxWindow *win,
233 wxDC& dc,
234 const wxSize& size,
235 wxCoord position,
236 wxOrientation orient,
237 int WXUNUSED(flags) )
238 {
239 bool hasMetal = win->MacGetTopLevelWindow()->MacGetMetalAppearance();
240 SInt32 height;
241 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
242 HIRect splitterRect;
243 if (orient == wxVERTICAL)
244 splitterRect = CGRectMake( position, 0, height, size.y );
245 else
246 splitterRect = CGRectMake( 0, position, size.x, height );
247
248 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
249 // strange redraw errors occur if we don't do this
250
251 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
252 {
253 wxRect rect( (int) splitterRect.origin.x, (int) splitterRect.origin.y, (int) splitterRect.size.width,
254 (int) splitterRect.size.height );
255 win->Refresh( &rect );
256 }
257 else
258 {
259 CGContextRef cgContext;
260 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
261 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
262
263 HIThemeSplitterDrawInfo drawInfo;
264 drawInfo.version = 0;
265 drawInfo.state = kThemeStateActive;
266 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
267 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
268 }
269 }
270
271 void
272 wxRendererMac::DrawItemSelectionRect(wxWindow * WXUNUSED(win),
273 wxDC& dc,
274 const wxRect& rect,
275 int flags)
276 {
277 if ( !(flags & wxCONTROL_SELECTED) )
278 return;
279
280 wxColour col( wxMacCreateCGColorFromHITheme( (flags & wxCONTROL_FOCUSED) ?
281 kThemeBrushAlternatePrimaryHighlightColor
282 : kThemeBrushSecondaryHighlightColor ) );
283 wxBrush selBrush( col );
284
285 dc.SetPen( *wxTRANSPARENT_PEN );
286 dc.SetBrush( selBrush );
287 dc.DrawRectangle( rect );
288 }
289
290
291 void
292 wxRendererMac::DrawMacThemeButton(wxWindow *win,
293 wxDC& dc,
294 const wxRect& rect,
295 int flags,
296 int kind,
297 int adornment)
298 {
299 // now the wxGCDC is using native transformations
300 const wxCoord x = rect.x;
301 const wxCoord y = rect.y;
302 const wxCoord w = rect.width;
303 const wxCoord h = rect.height;
304
305 dc.SetBrush( *wxTRANSPARENT_BRUSH );
306
307 HIRect headerRect = CGRectMake( x, y, w, h );
308 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
309 {
310 win->Refresh( &rect );
311 }
312 else
313 {
314 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
315 CGContextRef cgContext;
316 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
317
318 HIThemeButtonDrawInfo drawInfo;
319 HIRect labelRect;
320
321 memset( &drawInfo, 0, sizeof(drawInfo) );
322 drawInfo.version = 0;
323 drawInfo.kind = kind;
324 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
325 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
326 if (flags & wxCONTROL_UNDETERMINED)
327 drawInfo.value = kThemeButtonMixed;
328 drawInfo.adornment = adornment;
329
330 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
331 }
332 }
333
334 void
335 wxRendererMac::DrawCheckBox(wxWindow *win,
336 wxDC& dc,
337 const wxRect& rect,
338 int flags)
339 {
340 if (flags & wxCONTROL_CHECKED)
341 flags |= wxCONTROL_SELECTED;
342
343 DrawMacThemeButton(win, dc, rect, flags,
344 kThemeCheckBox, kThemeAdornmentNone);
345 }
346
347 void
348 wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
349 wxDC& dc,
350 const wxRect& rect,
351 int flags)
352 {
353 int kind;
354 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
355 kind = kThemeArrowButtonSmall;
356 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
357 kind = kThemeArrowButtonMini;
358 else
359 kind = kThemeArrowButton;
360
361 DrawMacThemeButton(win, dc, rect, flags,
362 kind, kThemeAdornmentArrowDownArrow);
363 }
364
365 void
366 wxRendererMac::DrawPushButton(wxWindow *win,
367 wxDC& dc,
368 const wxRect& rect,
369 int flags)
370 {
371 int kind;
372 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
373 kind = kThemeBevelButtonSmall;
374 // There is no kThemeBevelButtonMini, but in this case, use Small
375 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
376 kind = kThemeBevelButtonSmall;
377 else
378 kind = kThemeBevelButton;
379
380 DrawMacThemeButton(win, dc, rect, flags,
381 kind, kThemeAdornmentNone);
382 }
383
384 void
385 wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
386 {
387 if (!win)
388 {
389 wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
390 return;
391 }
392
393 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
394
395 HIThemeFrameDrawInfo info ;
396 memset( &info, 0 , sizeof(info) ) ;
397
398 info.version = 0 ;
399 info.kind = 0 ;
400 info.state = kThemeStateActive;
401 info.isFocused = true ;
402
403 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
404 wxASSERT( cgContext ) ;
405
406 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
407 }
408