1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: mac/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 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/string.h"
30 #include "wx/bitmap.h"
31 #include "wx/settings.h"
34 #include "wx/renderer.h"
35 #include "wx/toplevel.h"
36 #include "wx/dcclient.h"
37 #include "wx/mac/uma.h"
39 // ----------------------------------------------------------------------------
40 // wxRendererMac: our wxRendererNative implementation
41 // ----------------------------------------------------------------------------
43 class WXDLLEXPORT wxRendererMac
: public wxDelegateRendererNative
46 // draw the header control button (used by wxListCtrl)
47 virtual void DrawHeaderButton(wxWindow
*win
,
52 // draw the expanded/collapsed icon for a tree control item
53 virtual void DrawTreeItemButton(wxWindow
*win
,
58 // draw a (vertical) sash
59 virtual void DrawSplitterSash(wxWindow
*win
,
68 wxBitmap m_bmpTreeExpanded
,
72 // ----------------------------------------------------------------------------
74 // ----------------------------------------------------------------------------
77 static const char *aqua_arrow_right_xpm
[] = {
78 /* columns rows colors chars-per-pixel */
99 static const char *aqua_arrow_down_xpm
[] = {
100 /* columns rows colors chars-per-pixel */
120 // ============================================================================
122 // ============================================================================
125 wxRendererNative
& wxRendererNative::GetDefault()
127 static wxRendererMac s_rendererMac
;
129 return s_rendererMac
;
133 wxRendererMac::DrawHeaderButton(wxWindow
*win
,
138 const wxCoord x
= rect
.x
-1,
144 wxGetOsVersion( &major
, &minor
);
146 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
148 #if defined(__WXMAC_OSX__) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 )
149 if ( HIThemeDrawButton
!= 0 )
151 HIRect headerRect
= CGRectMake( x
, y
, w
, h
);
152 if ( dc
.IsKindOf( CLASSINFO( wxPaintDC
) ) == false )
154 Rect r
= { (short) headerRect
.origin
.y
, (short) headerRect
.origin
.x
,
155 (short) (headerRect
.origin
.y
+ headerRect
.size
.height
) , (short) (headerRect
.origin
.x
+ headerRect
.size
.width
) } ;
156 RgnHandle updateRgn
= NewRgn() ;
157 RectRgn( updateRgn
, &r
) ;
158 HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle() , updateRgn
, true ) ;
159 DisposeRgn( updateRgn
) ;
163 CGContextRef cgContext
;
164 #if wxMAC_USE_CORE_GRAPHICS
165 cgContext
= dynamic_cast<wxMacCGContext
*>(dc
.GetGraphicContext())->GetNativeContext() ;
168 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
169 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
170 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
171 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
172 HIViewConvertRect( &headerRect
, (HIViewRef
) win
->GetHandle() , (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() ) ;
175 HIThemeButtonDrawInfo drawInfo
;
177 memset( &drawInfo
, 0 , sizeof(drawInfo
) ) ;
178 drawInfo
.version
= 0 ;
179 drawInfo
.state
= ( flags
& wxCONTROL_DISABLED
) ? kThemeStateInactive
: kThemeStateActive
;
180 drawInfo
.kind
= kThemeListHeaderButton
;
182 drawInfo
.adornment
= kThemeAdornmentNone
;
183 HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect
) ;
185 #if wxMAC_USE_CORE_GRAPHICS
187 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
194 wxMacWindowClipper
clipper(win
) ;
195 Rect rect
= { y
, x
, y
+ h
, x
+ w
} ;
196 wxPoint origin
= win
->GetClientAreaOrigin() ;
200 win
->MacWindowToRootWindow( &dx
, &dy
) ;
201 OffsetRect( &rect
, dx
, dy
) ;
203 ThemeButtonDrawInfo drawInfo
;
204 memset( &drawInfo
, 0 , sizeof(drawInfo
) ) ;
205 drawInfo
.state
= ( flags
& wxCONTROL_DISABLED
) ? kThemeStateInactive
: kThemeStateActive
;
207 drawInfo
.adornment
= kThemeAdornmentNone
;
208 DrawThemeButton( &rect
, kThemeListHeaderButton
, &drawInfo
, NULL
, NULL
, NULL
, 0 ) ;
213 wxRendererMac::DrawTreeItemButton(wxWindow
*win
,
218 // init the buttons on demand
219 if ( !m_bmpTreeExpanded
.Ok() )
221 m_bmpTreeExpanded
= wxBitmap(aqua_arrow_down_xpm
);
222 m_bmpTreeCollapsed
= wxBitmap(aqua_arrow_right_xpm
);
227 // VZ: this is the old code from treectlg.cpp which apparently doesn't work
228 // but I kept it here just in case it is needed -- if not, please
230 #if 0 // def __WXMAC__
231 wxMacPortSetter
helper(&dc
) ;
232 wxMacWindowClipper
clipper(this) ;
233 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
236 int loc_y
= y_mid
- 6 ;
237 MacWindowToRootWindow( & loc_x
, & loc_y
) ;
238 Rect bounds
= { loc_y
, loc_x
, loc_y
+ 18 , loc_x
+ 12 } ;
239 ThemeButtonDrawInfo info
= { kThemeStateActive
, item
->IsExpanded() ? kThemeDisclosureDown
: kThemeDisclosureRight
,
240 kThemeAdornmentNone
};
241 DrawThemeButton( &bounds
, kThemeDisclosureButton
,
242 &info
, NULL
, NULL
, NULL
, NULL
) ;
244 dc
.DrawBitmap(flags
& wxCONTROL_EXPANDED
? m_bmpTreeExpanded
245 : m_bmpTreeCollapsed
,
246 rect
.x
, rect
.y
, true /* use mask */);
251 wxRendererMac::DrawSplitterSash(wxWindow
*win
,
255 wxOrientation orient
,
258 #if defined(__WXMAC_OSX__) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 )
259 if ( HIThemeDrawPaneSplitter
!= 0 )
261 bool hasMetal
= win
->MacGetTopLevelWindow()->MacGetMetalAppearance() ;
263 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
) ;
264 HIRect splitterRect
;
265 if ( orient
== wxVERTICAL
)
266 splitterRect
= CGRectMake( position
, 0 , height
, size
.y
);
268 splitterRect
= CGRectMake( 0 , position
, size
.x
, height
);
269 #if !wxMAC_USE_CORE_GRAPHICS
270 HIViewConvertRect( &splitterRect
, (HIViewRef
) win
->GetHandle() , (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() ) ;
273 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
274 // strange redraw errors occur if we don't do this
276 if ( dc
.IsKindOf( CLASSINFO( wxPaintDC
) ) == false )
278 Rect r
= { (short) splitterRect
.origin
.y
, (short) splitterRect
.origin
.x
,
279 (short) (splitterRect
.origin
.y
+ splitterRect
.size
.height
) , (short) (splitterRect
.origin
.x
+ splitterRect
.size
.width
) } ;
280 RgnHandle updateRgn
= NewRgn() ;
281 RectRgn( updateRgn
, &r
) ;
282 HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle() , updateRgn
, true ) ;
283 DisposeRgn( updateRgn
) ;
287 CGContextRef cgContext
;
288 #if wxMAC_USE_CORE_GRAPHICS
289 cgContext
= dynamic_cast<wxMacCGContext
*>(dc
.GetGraphicContext())->GetNativeContext() ;
292 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
293 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
294 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
295 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
298 HIThemeSplitterDrawInfo drawInfo
;
299 drawInfo
.version
= 0 ;
300 drawInfo
.state
= kThemeStateActive
;
301 drawInfo
.adornment
= hasMetal
? kHIThemeSplitterAdornmentMetal
: kHIThemeSplitterAdornmentNone
;
302 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
304 #if wxMAC_USE_CORE_GRAPHICS
306 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
313 // Do the gradient fill:
314 static int grayValues
[] =
316 0xA0, 0xF6, 0xED, 0xE4, 0xE2, 0xD0, 0xA0
318 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
319 if ( orient
== wxVERTICAL
)
322 for (i
=0; i
< (int)WXSIZEOF(grayValues
); i
++)
324 dc
.SetPen( wxPen( wxColour( grayValues
[i
] , grayValues
[i
] , grayValues
[i
] ),
326 dc
.DrawRectangle( position
+i
, 0, 1, size
.y
);
332 for (i
=0; i
< (int)WXSIZEOF(grayValues
); i
++)
334 dc
.SetPen( wxPen( wxColour( grayValues
[i
] , grayValues
[i
] , grayValues
[i
] ),
336 dc
.DrawRectangle( 0, position
+i
, size
.x
, 1 );