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 int CORNER
= 1;
140 const wxCoord x
= rect
.x
-1,
146 wxGetOsVersion( &major
, &minor
);
148 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
150 #if defined(__WXMAC_OSX__) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 )
151 if ( HIThemeDrawButton
!= 0 )
153 HIRect headerRect
= CGRectMake( x
, y
, w
, h
);
154 if ( dc
.IsKindOf( CLASSINFO( wxPaintDC
) ) == false )
156 Rect r
= { (short) headerRect
.origin
.y
, (short) headerRect
.origin
.x
,
157 (short) (headerRect
.origin
.y
+ headerRect
.size
.height
) , (short) (headerRect
.origin
.x
+ headerRect
.size
.width
) } ;
158 RgnHandle updateRgn
= NewRgn() ;
159 RectRgn( updateRgn
, &r
) ;
160 HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle() , updateRgn
, true ) ;
161 DisposeRgn( updateRgn
) ;
165 CGContextRef cgContext
;
166 #if wxMAC_USE_CORE_GRAPHICS
167 cgContext
= dynamic_cast<wxMacCGContext
*>(dc
.GetGraphicContext())->GetNativeContext() ;
170 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
171 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
172 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
173 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
176 HIThemeButtonDrawInfo drawInfo
;
178 memset( &drawInfo
, 0 , sizeof(drawInfo
) ) ;
179 drawInfo
.version
= 0 ;
180 drawInfo
.state
= kThemeStateActive
;
181 drawInfo
.kind
= kThemeListHeaderButton
;
183 drawInfo
.adornment
= kThemeAdornmentNone
;
184 HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect
) ;
186 #if wxMAC_USE_CORE_GRAPHICS
188 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
196 dc
.SetPen( wxPen( wxColour( 0xC5 , 0xC5 , 0xC5 ) , 1 , wxSOLID
) );
197 dc
.DrawRectangle( x
, y
+CORNER
, 1, h
-CORNER
); // left
198 // The right border is overdrawn by the left border of the right neighbouring
199 // header (to maintain a proper single pixel border). Except for the
200 // rightmost header of the listctrl.
201 dc
.DrawRectangle( x
+w
+(CORNER
*2), y
+CORNER
, 1, h
-CORNER
); // right
202 dc
.SetPen( wxPen( wxColour( 0xB1 , 0xB1 , 0xB1 ) , 1 , wxSOLID
) );
203 dc
.DrawRectangle( x
, y
+h
, w
+(CORNER
*3), 1 ); // bottom
204 dc
.DrawRectangle( x
, y
, w
+(CORNER
*3), 1 ); // top
206 // Do a fill of the interior for background:
207 dc
.SetPen( wxPen( wxColour( 0xF6 , 0xF6 , 0xF6 ) , 1 , wxSOLID
) );
208 dc
.DrawRectangle( x
+CORNER
, y
+CORNER
, w
+CORNER
, h
-CORNER
);
210 // Do the gradient fill:
211 static int grayValues
[] =
213 0xF6, 0xF2, 0xEF, 0xED, 0xED, 0xEB, 0xEA, 0xEA, 0xE8,
214 0xE8, 0xE2, 0xE5, 0xE8, 0xEB, 0xEF, 0xF2, 0xFD
217 for (i
=0; i
< h
&& i
< (int)WXSIZEOF(grayValues
); i
++)
219 dc
.SetPen( wxPen( wxColour( grayValues
[i
] , grayValues
[i
] , grayValues
[i
] ),
221 dc
.DrawRectangle( x
+CORNER
, y
+CORNER
+i
, w
+CORNER
, 1 );
226 dc
.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW
) , 1 , wxSOLID
) );
227 dc
.DrawLine( x
+w
-CORNER
+1, y
, x
+w
, y
+h
); // right (outer)
228 dc
.DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
230 wxPen
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID
);
233 dc
.DrawLine( x
+w
-CORNER
, y
, x
+w
-1, y
+h
); // right (inner)
234 dc
.DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
236 dc
.SetPen( *wxWHITE_PEN
);
237 dc
.DrawRectangle( x
, y
, w
-CORNER
+1, 1 ); // top (outer)
238 dc
.DrawRectangle( x
, y
, 1, h
); // left (outer)
239 dc
.DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
240 dc
.DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
245 wxRendererMac::DrawTreeItemButton(wxWindow
*win
,
250 // init the buttons on demand
251 if ( !m_bmpTreeExpanded
.Ok() )
253 m_bmpTreeExpanded
= wxBitmap(aqua_arrow_down_xpm
);
254 m_bmpTreeCollapsed
= wxBitmap(aqua_arrow_right_xpm
);
259 // VZ: this is the old code from treectlg.cpp which apparently doesn't work
260 // but I kept it here just in case it is needed -- if not, please
262 #if 0 // def __WXMAC__
263 wxMacPortSetter
helper(&dc
) ;
264 wxMacWindowClipper
clipper(this) ;
265 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
268 int loc_y
= y_mid
- 6 ;
269 MacWindowToRootWindow( & loc_x
, & loc_y
) ;
270 Rect bounds
= { loc_y
, loc_x
, loc_y
+ 18 , loc_x
+ 12 } ;
271 ThemeButtonDrawInfo info
= { kThemeStateActive
, item
->IsExpanded() ? kThemeDisclosureDown
: kThemeDisclosureRight
,
272 kThemeAdornmentNone
};
273 DrawThemeButton( &bounds
, kThemeDisclosureButton
,
274 &info
, NULL
, NULL
, NULL
, NULL
) ;
276 dc
.DrawBitmap(flags
& wxCONTROL_EXPANDED
? m_bmpTreeExpanded
277 : m_bmpTreeCollapsed
,
278 rect
.x
, rect
.y
, true /* use mask */);
283 wxRendererMac::DrawSplitterSash(wxWindow
*win
,
287 wxOrientation orient
,
290 #if defined(__WXMAC_OSX__) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 )
291 if ( HIThemeDrawPaneSplitter
!= 0 )
293 bool hasMetal
= win
->MacGetTopLevelWindow()->MacGetMetalAppearance() ;
295 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
) ;
296 HIRect splitterRect
;
297 if ( orient
== wxVERTICAL
)
298 splitterRect
= CGRectMake( position
, 0 , height
, size
.y
);
300 splitterRect
= CGRectMake( 0 , position
, size
.x
, height
);
301 #if !wxMAC_USE_CORE_GRAPHICS
302 HIViewConvertRect( &splitterRect
, (HIViewRef
) win
->GetHandle() , (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
) ) == false )
310 Rect r
= { (short) splitterRect
.origin
.y
, (short) splitterRect
.origin
.x
,
311 (short) (splitterRect
.origin
.y
+ splitterRect
.size
.height
) , (short) (splitterRect
.origin
.x
+ splitterRect
.size
.width
) } ;
312 RgnHandle updateRgn
= NewRgn() ;
313 RectRgn( updateRgn
, &r
) ;
314 HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle() , updateRgn
, true ) ;
315 DisposeRgn( updateRgn
) ;
319 CGContextRef cgContext
;
320 #if wxMAC_USE_CORE_GRAPHICS
321 cgContext
= dynamic_cast<wxMacCGContext
*>(dc
.GetGraphicContext())->GetNativeContext() ;
324 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
325 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
326 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
327 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
330 HIThemeSplitterDrawInfo drawInfo
;
331 drawInfo
.version
= 0 ;
332 drawInfo
.state
= kThemeStateActive
;
333 drawInfo
.adornment
= hasMetal
? kHIThemeSplitterAdornmentMetal
: kHIThemeSplitterAdornmentNone
;
334 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
336 #if wxMAC_USE_CORE_GRAPHICS
338 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
345 // Do the gradient fill:
346 static int grayValues
[] =
348 0xA0, 0xF6, 0xED, 0xE4, 0xE2, 0xD0, 0xA0
350 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
351 if ( orient
== wxVERTICAL
)
354 for (i
=0; i
< (int)WXSIZEOF(grayValues
); i
++)
356 dc
.SetPen( wxPen( wxColour( grayValues
[i
] , grayValues
[i
] , grayValues
[i
] ),
358 dc
.DrawRectangle( position
+i
, 0, 1, size
.y
);
364 for (i
=0; i
< (int)WXSIZEOF(grayValues
); i
++)
366 dc
.SetPen( wxPen( wxColour( grayValues
[i
] , grayValues
[i
] , grayValues
[i
] ),
368 dc
.DrawRectangle( 0, position
+i
, size
.x
, 1 );