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
, 
  62     wxBitmap m_bmpTreeExpanded
; 
  63     wxBitmap m_bmpTreeCollapsed
; 
  66 // ============================================================================ 
  68 // ============================================================================ 
  71 wxRendererNative
& wxRendererNative::GetDefault() 
  73     static wxRendererMac s_rendererMac
; 
  78 void wxRendererMac::DrawHeaderButton( wxWindow 
*win
, 
  82     wxHeaderSortIconType sortArrow
, 
  83     wxHeaderButtonParams
* params 
) 
  85 #if !wxMAC_USE_CORE_GRAPHICS 
  86     const wxCoord x 
= dc
.LogicalToDeviceX(rect
.x
); 
  87     const wxCoord y 
= dc
.LogicalToDeviceY(rect
.y
); 
  88     const wxCoord w 
= dc
.LogicalToDeviceXRel(rect
.width
); 
  89     const wxCoord h 
= dc
.LogicalToDeviceYRel(rect
.height
); 
  91     // now the wxGCDC is using native transformations 
  92     const wxCoord x 
= rect
.x
; 
  93     const wxCoord y 
= rect
.y
; 
  94     const wxCoord w 
= rect
.width
; 
  95     const wxCoord h 
= rect
.height
; 
  98     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
 100     HIRect headerRect 
= CGRectMake( x
, y
, w
, h 
); 
 101     if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC 
) ) ) 
 105             (short) headerRect
.origin
.y
, (short) headerRect
.origin
.x
, 
 106             (short) (headerRect
.origin
.y 
+ headerRect
.size
.height
), 
 107             (short) (headerRect
.origin
.x 
+ headerRect
.size
.width
) 
 110         RgnHandle updateRgn 
= NewRgn(); 
 111         RectRgn( updateRgn
, &r 
); 
 112         HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle(), updateRgn
, true ); 
 113         DisposeRgn( updateRgn 
); 
 117         CGContextRef cgContext
; 
 119 #if wxMAC_USE_CORE_GRAPHICS 
 120         cgContext 
= (CGContextRef
) dc
.GetGraphicsContext()->GetNativeContext(); 
 124         GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds 
); 
 125         QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext 
); 
 127         CGContextTranslateCTM( cgContext
, 0, bounds
.bottom 
- bounds
.top 
); 
 128         CGContextScaleCTM( cgContext
, 1, -1 ); 
 130         HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle
) dc
.m_macCurrentClipRgn 
), cgContext 
); 
 131         CGContextClip( cgContext 
); 
 132         HIViewConvertRect( &headerRect
, (HIViewRef
) win
->GetHandle(), (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() ); 
 136             HIThemeButtonDrawInfo drawInfo
; 
 139             memset( &drawInfo
, 0, sizeof(drawInfo
) ); 
 140             drawInfo
.version 
= 0; 
 141             drawInfo
.kind 
= kThemeListHeaderButton
; 
 142             drawInfo
.state 
= (flags 
& wxCONTROL_DISABLED
) ? kThemeStateInactive 
: kThemeStateActive
; 
 143             drawInfo
.value 
= (flags 
& wxCONTROL_SELECTED
) ? kThemeButtonOn 
: kThemeButtonOff
; 
 144             drawInfo
.adornment 
= kThemeAdornmentNone
; 
 146             // The down arrow is drawn automatically, change it to an up arrow if needed. 
 147             if ( sortArrow 
== wxHDR_SORT_ICON_UP 
) 
 148                 drawInfo
.adornment 
= kThemeAdornmentHeaderButtonSortUp
; 
 150             HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect 
); 
 152             // If we don't want any arrows we need to draw over the one already there 
 153             if ( (flags 
& wxCONTROL_SELECTED
) && (sortArrow 
== wxHDR_SORT_ICON_NONE
) ) 
 155                 // clip to the header rectangle 
 156                 CGContextSaveGState( cgContext 
); 
 157                 CGContextClipToRect( cgContext
, headerRect 
); 
 158                 // but draw bigger than that so the arrow will get clipped off 
 159                 headerRect
.size
.width 
+= 25; 
 160                 HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect 
); 
 161                 CGContextRestoreGState( cgContext 
); 
 165 #if wxMAC_USE_CORE_GRAPHICS 
 167         QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext 
); 
 171     // Reserve room for the arrows before writing the label, and turn off the 
 172     // flags we've already handled 
 173     wxRect 
newRect(rect
); 
 174     if ( (flags 
& wxCONTROL_SELECTED
) && (sortArrow 
!= wxHDR_SORT_ICON_NONE
) ) 
 177         sortArrow 
= wxHDR_SORT_ICON_NONE
; 
 179     flags 
&= ~wxCONTROL_SELECTED
; 
 181     DrawHeaderButtonContents(win
, dc
, newRect
, flags
, sortArrow
, params
); 
 185 int wxRendererMac::GetHeaderButtonHeight(wxWindow
* WXUNUSED(win
)) 
 187     SInt32              standardHeight
; 
 190     errStatus 
= GetThemeMetric( kThemeMetricListHeaderHeight
, &standardHeight 
); 
 191     if (errStatus 
== noErr
) 
 193         return standardHeight
; 
 198 void wxRendererMac::DrawTreeItemButton( wxWindow 
*win
, 
 203 #if !wxMAC_USE_CORE_GRAPHICS 
 204     const wxCoord x 
= dc
.LogicalToDeviceX(rect
.x
); 
 205     const wxCoord y 
= dc
.LogicalToDeviceY(rect
.y
); 
 206     const wxCoord w 
= dc
.LogicalToDeviceXRel(rect
.width
); 
 207     const wxCoord h 
= dc
.LogicalToDeviceYRel(rect
.height
); 
 209     // now the wxGCDC is using native transformations 
 210     const wxCoord x 
= rect
.x
; 
 211     const wxCoord y 
= rect
.y
; 
 212     const wxCoord w 
= rect
.width
; 
 213     const wxCoord h 
= rect
.height
; 
 216     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
 218     HIRect headerRect 
= CGRectMake( x
, y
, w
, h 
); 
 219     if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC 
) ) ) 
 223             (short) headerRect
.origin
.y
, (short) headerRect
.origin
.x
, 
 224             (short) (headerRect
.origin
.y 
+ headerRect
.size
.height
), 
 225             (short) (headerRect
.origin
.x 
+ headerRect
.size
.width
) 
 228         RgnHandle updateRgn 
= NewRgn(); 
 229         RectRgn( updateRgn
, &r 
); 
 230         HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle(), updateRgn
, true ); 
 231         DisposeRgn( updateRgn 
); 
 235         CGContextRef cgContext
; 
 237 #if wxMAC_USE_CORE_GRAPHICS 
 238         cgContext 
= (CGContextRef
) dc
.GetGraphicsContext()->GetNativeContext(); 
 242         GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds 
); 
 243         QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext 
); 
 245         CGContextTranslateCTM( cgContext
, 0, bounds
.bottom 
- bounds
.top 
); 
 246         CGContextScaleCTM( cgContext
, 1, -1 ); 
 248         HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle
) dc
.m_macCurrentClipRgn 
), cgContext 
); 
 249         CGContextClip( cgContext 
); 
 250         HIViewConvertRect( &headerRect
, (HIViewRef
) win
->GetHandle(), (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() ); 
 254             HIThemeButtonDrawInfo drawInfo
; 
 257             memset( &drawInfo
, 0, sizeof(drawInfo
) ); 
 258             drawInfo
.version 
= 0; 
 259             drawInfo
.kind 
= kThemeDisclosureButton
; 
 260             drawInfo
.state 
= (flags 
& wxCONTROL_DISABLED
) ? kThemeStateInactive 
: kThemeStateActive
; 
 261             // Apple mailing list posts say to use the arrow adornment constants, but those don't work. 
 262             // We need to set the value using the 'old' DrawThemeButton constants instead. 
 263             drawInfo
.value 
= (flags 
& wxCONTROL_EXPANDED
) ? kThemeDisclosureDown 
: kThemeDisclosureRight
; 
 264             drawInfo
.adornment 
= kThemeAdornmentNone
;  
 266             HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect 
); 
 270 #if wxMAC_USE_CORE_GRAPHICS 
 272         QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext 
); 
 277 void wxRendererMac::DrawSplitterSash( wxWindow 
*win
, 
 281     wxOrientation orient
, 
 282     int WXUNUSED(flags
) ) 
 284     bool hasMetal 
= win
->MacGetTopLevelWindow()->MacGetMetalAppearance(); 
 286     GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height 
); 
 288     if (orient 
== wxVERTICAL
) 
 289         splitterRect 
= CGRectMake( position
, 0, height
, size
.y 
); 
 291         splitterRect 
= CGRectMake( 0, position
, size
.x
, height 
); 
 293 #if !wxMAC_USE_CORE_GRAPHICS 
 296         (HIViewRef
) win
->GetHandle(), 
 297         (HIViewRef
) win
->MacGetTopLevelWindow()->GetHandle() ); 
 300     // under compositing we should only draw when called by the OS, otherwise just issue a redraw command 
 301     // strange redraw errors occur if we don't do this 
 303     if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC 
) ) ) 
 307             (short) splitterRect
.origin
.y
, 
 308             (short) splitterRect
.origin
.x
, 
 309             (short) (splitterRect
.origin
.y 
+ splitterRect
.size
.height
), 
 310             (short) (splitterRect
.origin
.x 
+ splitterRect
.size
.width
) 
 313         RgnHandle updateRgn 
= NewRgn(); 
 314         RectRgn( updateRgn
, &r 
); 
 315         HIViewSetNeedsDisplayInRegion( (HIViewRef
) win
->GetHandle(), updateRgn
, true ); 
 316         DisposeRgn( updateRgn 
); 
 320         CGContextRef cgContext
; 
 322 #if wxMAC_USE_CORE_GRAPHICS 
 323         cgContext 
= (CGContextRef
) dc
.GetGraphicsContext()->GetNativeContext(); 
 326         GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds 
); 
 327         QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext 
); 
 328         CGContextTranslateCTM( cgContext
, 0, bounds
.bottom 
- bounds
.top 
); 
 329         CGContextScaleCTM( cgContext
, 1, -1 ); 
 332         HIThemeSplitterDrawInfo drawInfo
; 
 333         drawInfo
.version 
= 0; 
 334         drawInfo
.state 
= kThemeStateActive
; 
 335         drawInfo
.adornment 
= hasMetal 
? kHIThemeSplitterAdornmentMetal 
: kHIThemeSplitterAdornmentNone
; 
 336         HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal 
); 
 338 #if wxMAC_USE_CORE_GRAPHICS 
 340         QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext 
);