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 
);