1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/renderer.cpp
3 // Purpose: implementation of wxRendererNative for Mac
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // for compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
20 #include "wx/string.h"
22 #include "wx/bitmap.h"
23 #include "wx/settings.h"
24 #include "wx/dcclient.h"
25 #include "wx/toplevel.h"
28 #include "wx/renderer.h"
29 #include "wx/graphics.h"
30 #include "wx/mac/uma.h"
33 class WXDLLEXPORT wxRendererMac
: public wxDelegateRendererNative
36 // draw the header control button (used by wxListCtrl)
37 virtual void DrawHeaderButton( wxWindow
*win
,
41 wxHeaderSortIconType sortArrow
= wxHDR_SORT_ICON_NONE
,
42 wxHeaderButtonParams
* params
= NULL
);
44 virtual int GetHeaderButtonHeight(wxWindow
*win
);
46 // draw the expanded/collapsed icon for a tree control item
47 virtual void DrawTreeItemButton( wxWindow
*win
,
52 // draw a (vertical) sash
53 virtual void DrawSplitterSash( wxWindow
*win
,
60 virtual void DrawItemSelectionRect(wxWindow
*win
,
67 wxBitmap m_bmpTreeExpanded
;
68 wxBitmap m_bmpTreeCollapsed
;
71 // ============================================================================
73 // ============================================================================
76 wxRendererNative
& wxRendererNative::GetDefault()
78 static wxRendererMac s_rendererMac
;
83 void wxRendererMac::DrawHeaderButton( wxWindow
*win
,
87 wxHeaderSortIconType sortArrow
,
88 wxHeaderButtonParams
* params
)
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
);
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
;
103 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
105 HIRect headerRect
= CGRectMake( x
, y
, w
, h
);
106 if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC
) ) )
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
)
115 RgnHandle updateRgn
= NewRgn();
116 RectRgn( updateRgn
, &r
);
117 HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle(), updateRgn
, true );
118 DisposeRgn( updateRgn
);
122 CGContextRef cgContext
;
124 #if wxMAC_USE_CORE_GRAPHICS
125 cgContext
= (CGContextRef
) dc
.GetGraphicsContext()->GetNativeContext();
129 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
);
130 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
);
132 CGContextTranslateCTM( cgContext
, 0, bounds
.bottom
- bounds
.top
);
133 CGContextScaleCTM( cgContext
, 1, -1 );
135 HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle
) dc
.m_macCurrentClipRgn
), cgContext
);
136 CGContextClip( cgContext
);
137 HIViewConvertRect( &headerRect
, (HIViewRef
) win
->GetHandle(), (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() );
141 HIThemeButtonDrawInfo drawInfo
;
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
;
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
;
155 HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect
);
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
) )
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
);
170 #if wxMAC_USE_CORE_GRAPHICS
172 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
);
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
) )
182 sortArrow
= wxHDR_SORT_ICON_NONE
;
184 flags
&= ~wxCONTROL_SELECTED
;
186 DrawHeaderButtonContents(win
, dc
, newRect
, flags
, sortArrow
, params
);
190 int wxRendererMac::GetHeaderButtonHeight(wxWindow
* WXUNUSED(win
))
192 SInt32 standardHeight
;
195 errStatus
= GetThemeMetric( kThemeMetricListHeaderHeight
, &standardHeight
);
196 if (errStatus
== noErr
)
198 return standardHeight
;
203 void wxRendererMac::DrawTreeItemButton( wxWindow
*win
,
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
);
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
;
221 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
223 HIRect headerRect
= CGRectMake( x
, y
, w
, h
);
224 if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC
) ) )
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
)
233 RgnHandle updateRgn
= NewRgn();
234 RectRgn( updateRgn
, &r
);
235 HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle(), updateRgn
, true );
236 DisposeRgn( updateRgn
);
240 CGContextRef cgContext
;
242 #if wxMAC_USE_CORE_GRAPHICS
243 cgContext
= (CGContextRef
) dc
.GetGraphicsContext()->GetNativeContext();
247 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
);
248 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
);
250 CGContextTranslateCTM( cgContext
, 0, bounds
.bottom
- bounds
.top
);
251 CGContextScaleCTM( cgContext
, 1, -1 );
253 HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle
) dc
.m_macCurrentClipRgn
), cgContext
);
254 CGContextClip( cgContext
);
255 HIViewConvertRect( &headerRect
, (HIViewRef
) win
->GetHandle(), (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() );
259 HIThemeButtonDrawInfo drawInfo
;
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
;
271 HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect
);
275 #if wxMAC_USE_CORE_GRAPHICS
277 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
);
282 void wxRendererMac::DrawSplitterSash( wxWindow
*win
,
286 wxOrientation orient
,
287 int WXUNUSED(flags
) )
289 bool hasMetal
= win
->MacGetTopLevelWindow()->MacGetMetalAppearance();
291 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
293 if (orient
== wxVERTICAL
)
294 splitterRect
= CGRectMake( position
, 0, height
, size
.y
);
296 splitterRect
= CGRectMake( 0, position
, size
.x
, height
);
298 #if !wxMAC_USE_CORE_GRAPHICS
301 (HIViewRef
) win
->GetHandle(),
302 (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() );
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
308 if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC
) ) )
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
)
318 RgnHandle updateRgn
= NewRgn();
319 RectRgn( updateRgn
, &r
);
320 HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle(), updateRgn
, true );
321 DisposeRgn( updateRgn
);
325 CGContextRef cgContext
;
327 #if wxMAC_USE_CORE_GRAPHICS
328 cgContext
= (CGContextRef
) dc
.GetGraphicsContext()->GetNativeContext();
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 );
337 HIThemeSplitterDrawInfo drawInfo
;
338 drawInfo
.version
= 0;
339 drawInfo
.state
= kThemeStateActive
;
340 drawInfo
.adornment
= hasMetal
? kHIThemeSplitterAdornmentMetal
: kHIThemeSplitterAdornmentNone
;
341 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
);
343 #if wxMAC_USE_CORE_GRAPHICS
345 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
);
351 wxRendererMac::DrawItemSelectionRect(wxWindow
*win
,
357 if (flags
& wxCONTROL_SELECTED
)
359 if (flags
& wxCONTROL_FOCUSED
)
360 GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor
, 32, true, &selColor
);
362 GetThemeBrushAsColor(kThemeBrushSecondaryHighlightColor
, 32, true, &selColor
);
365 wxBrush selBrush
= wxBrush( wxColour( selColor
.red
, selColor
.green
, selColor
.blue
), wxSOLID
);
367 dc
.SetPen( *wxTRANSPARENT_PEN
);
368 dc
.SetBrush( selBrush
);
369 dc
.DrawRectangle( rect
);