]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/renderer.cpp
Implement wxIcon::LoadFile by defering to wxBitmap implementation instead of creating...
[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( (int) splitterRect.origin.x, (int) splitterRect.origin.y, (int) splitterRect.size.width,
252 (int) splitterRect.size.height );
253 win->Refresh( &rect );
254 }
255 else
256 {
257 CGContextRef cgContext;
258
259 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
260
261 HIThemeSplitterDrawInfo drawInfo;
262 drawInfo.version = 0;
263 drawInfo.state = kThemeStateActive;
264 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
265 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
266 }
267 }
268
269 void
270 wxRendererMac::DrawItemSelectionRect(wxWindow *win,
271 wxDC& dc,
272 const wxRect& rect,
273 int flags )
274 {
275 if ( !(flags & wxCONTROL_SELECTED) )
276 return;
277
278 wxColour col( wxMacCreateCGColorFromHITheme( (flags & wxCONTROL_FOCUSED) ?
279 kThemeBrushAlternatePrimaryHighlightColor
280 : kThemeBrushSecondaryHighlightColor ) );
281 wxBrush selBrush( col );
282
283 dc.SetPen( *wxTRANSPARENT_PEN );
284 dc.SetBrush( selBrush );
285 dc.DrawRectangle( rect );
286 }
287
288
289 void
290 wxRendererMac::DrawMacThemeButton(wxWindow *win,
291 wxDC& dc,
292 const wxRect& rect,
293 int flags,
294 int kind,
295 int adornment)
296 {
297 // now the wxGCDC is using native transformations
298 const wxCoord x = rect.x;
299 const wxCoord y = rect.y;
300 const wxCoord w = rect.width;
301 const wxCoord h = rect.height;
302
303 dc.SetBrush( *wxTRANSPARENT_BRUSH );
304
305 HIRect headerRect = CGRectMake( x, y, w, h );
306 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
307 {
308 win->Refresh( &rect );
309 }
310 else
311 {
312 CGContextRef cgContext;
313 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
314
315 HIThemeButtonDrawInfo drawInfo;
316 HIRect labelRect;
317
318 memset( &drawInfo, 0, sizeof(drawInfo) );
319 drawInfo.version = 0;
320 drawInfo.kind = kind;
321 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
322 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
323 if (flags & wxCONTROL_UNDETERMINED)
324 drawInfo.value = kThemeButtonMixed;
325 drawInfo.adornment = adornment;
326
327 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
328 }
329 }
330
331 void
332 wxRendererMac::DrawCheckBox(wxWindow *win,
333 wxDC& dc,
334 const wxRect& rect,
335 int flags)
336 {
337 if (flags & wxCONTROL_CHECKED)
338 flags |= wxCONTROL_SELECTED;
339
340 DrawMacThemeButton(win, dc, rect, flags,
341 kThemeCheckBox, kThemeAdornmentNone);
342 }
343
344 void
345 wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
346 wxDC& dc,
347 const wxRect& rect,
348 int flags)
349 {
350 int kind;
351 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
352 kind = kThemeArrowButtonSmall;
353 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
354 kind = kThemeArrowButtonMini;
355 else
356 kind = kThemeArrowButton;
357
358 DrawMacThemeButton(win, dc, rect, flags,
359 kind, kThemeAdornmentArrowDownArrow);
360 }
361
362 void
363 wxRendererMac::DrawPushButton(wxWindow *win,
364 wxDC& dc,
365 const wxRect& rect,
366 int flags)
367 {
368 int kind;
369 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
370 kind = kThemeBevelButtonSmall;
371 // There is no kThemeBevelButtonMini, but in this case, use Small
372 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
373 kind = kThemeBevelButtonSmall;
374 else
375 kind = kThemeBevelButton;
376
377 DrawMacThemeButton(win, dc, rect, flags,
378 kind, kThemeAdornmentNone);
379 }
380
381 void
382 wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
383 {
384 if (!win)
385 {
386 wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
387 return;
388 }
389
390 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
391
392 HIThemeFrameDrawInfo info ;
393 memset( &info, 0 , sizeof(info) ) ;
394
395 info.version = 0 ;
396 info.kind = 0 ;
397 info.state = kThemeStateActive;
398 info.isFocused = true ;
399
400 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
401 wxASSERT( cgContext ) ;
402
403 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
404 }
405