]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/renderer.cpp
Implement wxRendererMac::DrawItemSelectionRect and move the generic wxTreeCtrl to...
[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 void 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 DrawItemSelectionRect(wxWindow *win,
61 wxDC& dc,
62 const wxRect& rect,
63 int flags = 0);
64
65 private:
66 // the tree buttons
67 wxBitmap m_bmpTreeExpanded;
68 wxBitmap m_bmpTreeCollapsed;
69 };
70
71 // ============================================================================
72 // implementation
73 // ============================================================================
74
75 // static
76 wxRendererNative& wxRendererNative::GetDefault()
77 {
78 static wxRendererMac s_rendererMac;
79
80 return s_rendererMac;
81 }
82
83 void wxRendererMac::DrawHeaderButton( wxWindow *win,
84 wxDC& dc,
85 const wxRect& rect,
86 int flags,
87 wxHeaderSortIconType sortArrow,
88 wxHeaderButtonParams* params )
89 {
90 #if !wxMAC_USE_CORE_GRAPHICS
91 const wxCoord x = dc.LogicalToDeviceX(rect.x);
92 const wxCoord y = dc.LogicalToDeviceY(rect.y);
93 const wxCoord w = dc.LogicalToDeviceXRel(rect.width);
94 const wxCoord h = dc.LogicalToDeviceYRel(rect.height);
95 #else
96 // now the wxGCDC is using native transformations
97 const wxCoord x = rect.x;
98 const wxCoord y = rect.y;
99 const wxCoord w = rect.width;
100 const wxCoord h = rect.height;
101 #endif
102
103 dc.SetBrush( *wxTRANSPARENT_BRUSH );
104
105 HIRect headerRect = CGRectMake( x, y, w, h );
106 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
107 {
108 Rect r =
109 {
110 (short) headerRect.origin.y, (short) headerRect.origin.x,
111 (short) (headerRect.origin.y + headerRect.size.height),
112 (short) (headerRect.origin.x + headerRect.size.width)
113 };
114
115 RgnHandle updateRgn = NewRgn();
116 RectRgn( updateRgn, &r );
117 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
118 DisposeRgn( updateRgn );
119 }
120 else
121 {
122 CGContextRef cgContext;
123
124 #if wxMAC_USE_CORE_GRAPHICS
125 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
126 #else
127 Rect bounds;
128
129 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
130 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
131
132 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
133 CGContextScaleCTM( cgContext, 1, -1 );
134
135 HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle) dc.m_macCurrentClipRgn ), cgContext );
136 CGContextClip( cgContext );
137 HIViewConvertRect( &headerRect, (HIViewRef) win->GetHandle(), (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
138 #endif
139
140 {
141 HIThemeButtonDrawInfo drawInfo;
142 HIRect labelRect;
143
144 memset( &drawInfo, 0, sizeof(drawInfo) );
145 drawInfo.version = 0;
146 drawInfo.kind = kThemeListHeaderButton;
147 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
148 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
149 drawInfo.adornment = kThemeAdornmentNone;
150
151 // The down arrow is drawn automatically, change it to an up arrow if needed.
152 if ( sortArrow == wxHDR_SORT_ICON_UP )
153 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
154
155 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
156
157 // If we don't want any arrows we need to draw over the one already there
158 if ( (flags & wxCONTROL_SELECTED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
159 {
160 // clip to the header rectangle
161 CGContextSaveGState( cgContext );
162 CGContextClipToRect( cgContext, headerRect );
163 // but draw bigger than that so the arrow will get clipped off
164 headerRect.size.width += 25;
165 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
166 CGContextRestoreGState( cgContext );
167 }
168 }
169
170 #if wxMAC_USE_CORE_GRAPHICS
171 #else
172 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
173 #endif
174 }
175
176 // Reserve room for the arrows before writing the label, and turn off the
177 // flags we've already handled
178 wxRect newRect(rect);
179 if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
180 {
181 newRect.width -= 12;
182 sortArrow = wxHDR_SORT_ICON_NONE;
183 }
184 flags &= ~wxCONTROL_SELECTED;
185
186 DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
187 }
188
189
190 int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
191 {
192 SInt32 standardHeight;
193 OSStatus errStatus;
194
195 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
196 if (errStatus == noErr)
197 {
198 return standardHeight;
199 }
200 return -1;
201 }
202
203 void wxRendererMac::DrawTreeItemButton( wxWindow *win,
204 wxDC& dc,
205 const wxRect& rect,
206 int flags )
207 {
208 #if !wxMAC_USE_CORE_GRAPHICS
209 const wxCoord x = dc.LogicalToDeviceX(rect.x);
210 const wxCoord y = dc.LogicalToDeviceY(rect.y);
211 const wxCoord w = dc.LogicalToDeviceXRel(rect.width);
212 const wxCoord h = dc.LogicalToDeviceYRel(rect.height);
213 #else
214 // now the wxGCDC is using native transformations
215 const wxCoord x = rect.x;
216 const wxCoord y = rect.y;
217 const wxCoord w = rect.width;
218 const wxCoord h = rect.height;
219 #endif
220
221 dc.SetBrush( *wxTRANSPARENT_BRUSH );
222
223 HIRect headerRect = CGRectMake( x, y, w, h );
224 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
225 {
226 Rect r =
227 {
228 (short) headerRect.origin.y, (short) headerRect.origin.x,
229 (short) (headerRect.origin.y + headerRect.size.height),
230 (short) (headerRect.origin.x + headerRect.size.width)
231 };
232
233 RgnHandle updateRgn = NewRgn();
234 RectRgn( updateRgn, &r );
235 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
236 DisposeRgn( updateRgn );
237 }
238 else
239 {
240 CGContextRef cgContext;
241
242 #if wxMAC_USE_CORE_GRAPHICS
243 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
244 #else
245 Rect bounds;
246
247 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
248 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
249
250 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
251 CGContextScaleCTM( cgContext, 1, -1 );
252
253 HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle) dc.m_macCurrentClipRgn ), cgContext );
254 CGContextClip( cgContext );
255 HIViewConvertRect( &headerRect, (HIViewRef) win->GetHandle(), (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
256 #endif
257
258 {
259 HIThemeButtonDrawInfo drawInfo;
260 HIRect labelRect;
261
262 memset( &drawInfo, 0, sizeof(drawInfo) );
263 drawInfo.version = 0;
264 drawInfo.kind = kThemeDisclosureButton;
265 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
266 // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
267 // We need to set the value using the 'old' DrawThemeButton constants instead.
268 drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
269 drawInfo.adornment = kThemeAdornmentNone;
270
271 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
272
273 }
274
275 #if wxMAC_USE_CORE_GRAPHICS
276 #else
277 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
278 #endif
279 }
280 }
281
282 void wxRendererMac::DrawSplitterSash( wxWindow *win,
283 wxDC& dc,
284 const wxSize& size,
285 wxCoord position,
286 wxOrientation orient,
287 int WXUNUSED(flags) )
288 {
289 bool hasMetal = win->MacGetTopLevelWindow()->MacGetMetalAppearance();
290 SInt32 height;
291 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
292 HIRect splitterRect;
293 if (orient == wxVERTICAL)
294 splitterRect = CGRectMake( position, 0, height, size.y );
295 else
296 splitterRect = CGRectMake( 0, position, size.x, height );
297
298 #if !wxMAC_USE_CORE_GRAPHICS
299 HIViewConvertRect(
300 &splitterRect,
301 (HIViewRef) win->GetHandle(),
302 (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
303 #endif
304
305 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
306 // strange redraw errors occur if we don't do this
307
308 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
309 {
310 Rect r =
311 {
312 (short) splitterRect.origin.y,
313 (short) splitterRect.origin.x,
314 (short) (splitterRect.origin.y + splitterRect.size.height),
315 (short) (splitterRect.origin.x + splitterRect.size.width)
316 };
317
318 RgnHandle updateRgn = NewRgn();
319 RectRgn( updateRgn, &r );
320 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
321 DisposeRgn( updateRgn );
322 }
323 else
324 {
325 CGContextRef cgContext;
326
327 #if wxMAC_USE_CORE_GRAPHICS
328 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
329 #else
330 Rect bounds;
331 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
332 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
333 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
334 CGContextScaleCTM( cgContext, 1, -1 );
335 #endif
336
337 HIThemeSplitterDrawInfo drawInfo;
338 drawInfo.version = 0;
339 drawInfo.state = kThemeStateActive;
340 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
341 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
342
343 #if wxMAC_USE_CORE_GRAPHICS
344 #else
345 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
346 #endif
347 }
348 }
349
350 void
351 wxRendererMac::DrawItemSelectionRect(wxWindow *win,
352 wxDC& dc,
353 const wxRect& rect,
354 int flags )
355 {
356 RGBColor selColor;
357 if (flags & wxCONTROL_SELECTED)
358 {
359 if (flags & wxCONTROL_FOCUSED)
360 GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor, 32, true, &selColor);
361 else
362 GetThemeBrushAsColor(kThemeBrushSecondaryHighlightColor, 32, true, &selColor);
363 }
364
365 wxBrush selBrush = wxBrush( wxColour( selColor.red, selColor.green, selColor.blue ), wxSOLID );
366
367 dc.SetPen( *wxTRANSPARENT_PEN );
368 dc.SetBrush( selBrush );
369 dc.DrawRectangle( rect );
370 }