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 int 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 DrawCheckBox(wxWindow 
*win
, 
  65     virtual void DrawComboBoxDropButton(wxWindow 
*win
, 
  70     virtual void DrawPushButton(wxWindow 
*win
, 
  75     virtual void DrawItemSelectionRect(wxWindow 
*win
, 
  80     virtual void DrawFocusRect(wxWindow
* win
, wxDC
& dc
, const wxRect
& rect
, int flags 
= 0); 
  83     void DrawMacThemeButton(wxWindow 
*win
, 
  91     wxBitmap m_bmpTreeExpanded
; 
  92     wxBitmap m_bmpTreeCollapsed
; 
  95 // ============================================================================ 
  97 // ============================================================================ 
 100 wxRendererNative
& wxRendererNative::GetDefault() 
 102     static wxRendererMac s_rendererMac
; 
 104     return s_rendererMac
; 
 107 int wxRendererMac::DrawHeaderButton( wxWindow 
*win
, 
 111     wxHeaderSortIconType sortArrow
, 
 112     wxHeaderButtonParams
* params 
) 
 114     const wxCoord x 
= rect
.x
; 
 115     const wxCoord y 
= rect
.y
; 
 116     const wxCoord w 
= rect
.width
; 
 117     const wxCoord h 
= rect
.height
; 
 119     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
 121     HIRect headerRect 
= CGRectMake( x
, y
, w
, h 
); 
 122     if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC 
) ) ) 
 124         win
->Refresh( &rect 
); 
 128         CGContextRef cgContext
; 
 129         wxGCDCImpl 
*impl 
= (wxGCDCImpl
*) dc
.GetImpl(); 
 131         cgContext 
= (CGContextRef
) impl
->GetGraphicsContext()->GetNativeContext(); 
 134             HIThemeButtonDrawInfo drawInfo
; 
 137             memset( &drawInfo
, 0, sizeof(drawInfo
) ); 
 138             drawInfo
.version 
= 0; 
 139             drawInfo
.kind 
= kThemeListHeaderButton
; 
 140             drawInfo
.state 
= (flags 
& wxCONTROL_DISABLED
) ? kThemeStateInactive 
: kThemeStateActive
; 
 141             drawInfo
.value 
= (flags 
& wxCONTROL_SELECTED
) ? kThemeButtonOn 
: kThemeButtonOff
; 
 142             drawInfo
.adornment 
= kThemeAdornmentNone
; 
 144             // The down arrow is drawn automatically, change it to an up arrow if needed. 
 145             if ( sortArrow 
== wxHDR_SORT_ICON_UP 
) 
 146                 drawInfo
.adornment 
= kThemeAdornmentHeaderButtonSortUp
; 
 148             HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect 
); 
 150             // If we don't want any arrows we need to draw over the one already there 
 151             if ( (flags 
& wxCONTROL_SELECTED
) && (sortArrow 
== wxHDR_SORT_ICON_NONE
) ) 
 153                 // clip to the header rectangle 
 154                 CGContextSaveGState( cgContext 
); 
 155                 CGContextClipToRect( cgContext
, headerRect 
); 
 156                 // but draw bigger than that so the arrow will get clipped off 
 157                 headerRect
.size
.width 
+= 25; 
 158                 HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect 
); 
 159                 CGContextRestoreGState( cgContext 
); 
 164     // Reserve room for the arrows before writing the label, and turn off the 
 165     // flags we've already handled 
 166     wxRect 
newRect(rect
); 
 167     if ( (flags 
& wxCONTROL_SELECTED
) && (sortArrow 
!= wxHDR_SORT_ICON_NONE
) ) 
 170         sortArrow 
= wxHDR_SORT_ICON_NONE
; 
 172     flags 
&= ~wxCONTROL_SELECTED
; 
 174     return DrawHeaderButtonContents(win
, dc
, newRect
, flags
, sortArrow
, params
); 
 178 int wxRendererMac::GetHeaderButtonHeight(wxWindow
* WXUNUSED(win
)) 
 180     SInt32      standardHeight
; 
 183     errStatus 
= GetThemeMetric( kThemeMetricListHeaderHeight
, &standardHeight 
); 
 184     if (errStatus 
== noErr
) 
 186         return standardHeight
; 
 191 void wxRendererMac::DrawTreeItemButton( wxWindow 
*win
, 
 196     // now the wxGCDC is using native transformations 
 197     const wxCoord x 
= rect
.x
; 
 198     const wxCoord y 
= rect
.y
; 
 199     const wxCoord w 
= rect
.width
; 
 200     const wxCoord h 
= rect
.height
; 
 202     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
 204     HIRect headerRect 
= CGRectMake( x
, y
, w
, h 
); 
 205     if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC 
) ) ) 
 207         win
->Refresh( &rect 
); 
 211         CGContextRef cgContext
; 
 213         wxGCDCImpl 
*impl 
= (wxGCDCImpl
*) dc
.GetImpl(); 
 214         cgContext 
= (CGContextRef
) impl
->GetGraphicsContext()->GetNativeContext(); 
 216         HIThemeButtonDrawInfo drawInfo
; 
 219         memset( &drawInfo
, 0, sizeof(drawInfo
) ); 
 220         drawInfo
.version 
= 0; 
 221         drawInfo
.kind 
= kThemeDisclosureButton
; 
 222         drawInfo
.state 
= (flags 
& wxCONTROL_DISABLED
) ? kThemeStateInactive 
: kThemeStateActive
; 
 223         // Apple mailing list posts say to use the arrow adornment constants, but those don't work. 
 224         // We need to set the value using the 'old' DrawThemeButton constants instead. 
 225         drawInfo
.value 
= (flags 
& wxCONTROL_EXPANDED
) ? kThemeDisclosureDown 
: kThemeDisclosureRight
; 
 226         drawInfo
.adornment 
= kThemeAdornmentNone
; 
 228         HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect 
); 
 232 void wxRendererMac::DrawSplitterSash( wxWindow 
*win
, 
 236     wxOrientation orient
, 
 237     int WXUNUSED(flags
) ) 
 239     bool hasMetal 
= win
->MacGetTopLevelWindow()->MacGetMetalAppearance(); 
 241     GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height 
); 
 243     if (orient 
== wxVERTICAL
) 
 244         splitterRect 
= CGRectMake( position
, 0, height
, size
.y 
); 
 246         splitterRect 
= CGRectMake( 0, position
, size
.x
, height 
); 
 248     // under compositing we should only draw when called by the OS, otherwise just issue a redraw command 
 249     // strange redraw errors occur if we don't do this 
 251     if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC 
) ) ) 
 253         wxRect 
rect( (int) splitterRect
.origin
.x
, (int) splitterRect
.origin
.y
, (int) splitterRect
.size
.width
, 
 254                      (int) splitterRect
.size
.height 
); 
 255         win
->Refresh( &rect 
); 
 259         CGContextRef cgContext
; 
 260         wxGCDCImpl 
*impl 
= (wxGCDCImpl
*) dc
.GetImpl(); 
 261         cgContext 
= (CGContextRef
) impl
->GetGraphicsContext()->GetNativeContext(); 
 263         HIThemeSplitterDrawInfo drawInfo
; 
 264         drawInfo
.version 
= 0; 
 265         drawInfo
.state 
= kThemeStateActive
; 
 266         drawInfo
.adornment 
= hasMetal 
? kHIThemeSplitterAdornmentMetal 
: kHIThemeSplitterAdornmentNone
; 
 267         HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal 
); 
 272 wxRendererMac::DrawItemSelectionRect(wxWindow 
* WXUNUSED(win
), 
 277     if ( !(flags 
& wxCONTROL_SELECTED
) ) 
 280     wxColour 
col( wxMacCreateCGColorFromHITheme( (flags 
& wxCONTROL_FOCUSED
) ? 
 281                                                  kThemeBrushAlternatePrimaryHighlightColor
 
 282                                                                              : kThemeBrushSecondaryHighlightColor 
) ); 
 283     wxBrush 
selBrush( col 
); 
 285     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
 286     dc
.SetBrush( selBrush 
); 
 287     dc
.DrawRectangle( rect 
); 
 292 wxRendererMac::DrawMacThemeButton(wxWindow 
*win
, 
 299     // now the wxGCDC is using native transformations 
 300     const wxCoord x 
= rect
.x
; 
 301     const wxCoord y 
= rect
.y
; 
 302     const wxCoord w 
= rect
.width
; 
 303     const wxCoord h 
= rect
.height
; 
 305     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
 307     HIRect headerRect 
= CGRectMake( x
, y
, w
, h 
); 
 308     if ( !dc
.IsKindOf( CLASSINFO( wxPaintDC 
) ) ) 
 310         win
->Refresh( &rect 
); 
 314         wxGCDCImpl 
*impl 
= (wxGCDCImpl
*) dc
.GetImpl(); 
 315         CGContextRef cgContext
; 
 316         cgContext 
= (CGContextRef
) impl
->GetGraphicsContext()->GetNativeContext(); 
 318         HIThemeButtonDrawInfo drawInfo
; 
 321         memset( &drawInfo
, 0, sizeof(drawInfo
) ); 
 322         drawInfo
.version 
= 0; 
 323         drawInfo
.kind 
= kind
; 
 324         drawInfo
.state 
= (flags 
& wxCONTROL_DISABLED
) ? kThemeStateInactive 
: kThemeStateActive
; 
 325         drawInfo
.value 
= (flags 
& wxCONTROL_SELECTED
) ? kThemeButtonOn 
: kThemeButtonOff
; 
 326         if (flags 
& wxCONTROL_UNDETERMINED
) 
 327             drawInfo
.value 
= kThemeButtonMixed
; 
 328         drawInfo
.adornment 
= adornment
; 
 330         HIThemeDrawButton( &headerRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
, &labelRect 
); 
 335 wxRendererMac::DrawCheckBox(wxWindow 
*win
, 
 340     if (flags 
& wxCONTROL_CHECKED
) 
 341         flags 
|= wxCONTROL_SELECTED
; 
 343     DrawMacThemeButton(win
, dc
, rect
, flags
, 
 344                        kThemeCheckBox
, kThemeAdornmentNone
); 
 348 wxRendererMac::DrawComboBoxDropButton(wxWindow 
*win
, 
 354     if (win
->GetWindowVariant() == wxWINDOW_VARIANT_SMALL 
|| (win
->GetParent() && win
->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL
)) 
 355         kind 
= kThemeArrowButtonSmall
; 
 356     else if (win
->GetWindowVariant() == wxWINDOW_VARIANT_MINI 
|| (win
->GetParent() && win
->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI
)) 
 357         kind 
= kThemeArrowButtonMini
; 
 359         kind 
= kThemeArrowButton
; 
 361     DrawMacThemeButton(win
, dc
, rect
, flags
, 
 362                        kind
, kThemeAdornmentArrowDownArrow
); 
 366 wxRendererMac::DrawPushButton(wxWindow 
*win
, 
 372     if (win
->GetWindowVariant() == wxWINDOW_VARIANT_SMALL 
|| (win
->GetParent() && win
->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL
)) 
 373         kind 
= kThemeBevelButtonSmall
; 
 374     // There is no kThemeBevelButtonMini, but in this case, use Small 
 375     else if (win
->GetWindowVariant() == wxWINDOW_VARIANT_MINI 
|| (win
->GetParent() && win
->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI
)) 
 376         kind 
= kThemeBevelButtonSmall
; 
 378         kind 
= kThemeBevelButton
; 
 380     DrawMacThemeButton(win
, dc
, rect
, flags
, 
 381                        kind
, kThemeAdornmentNone
); 
 385 wxRendererMac::DrawFocusRect(wxWindow
* win
, wxDC
& dc
, const wxRect
& rect
, int flags
) 
 389         wxDelegateRendererNative::DrawFocusRect(win
, dc
, rect
, flags
); 
 393     CGRect cgrect 
= CGRectMake( rect
.x 
, rect
.y 
, rect
.width
, rect
.height 
) ; 
 395     HIThemeFrameDrawInfo info 
; 
 396     memset( &info
, 0 , sizeof(info
) ) ; 
 400     info
.state 
= kThemeStateActive
; 
 401     info
.isFocused 
= true ; 
 403     CGContextRef cgContext 
= (CGContextRef
) win
->MacGetCGContextRef() ; 
 404     wxASSERT( cgContext 
) ; 
 406     HIThemeDrawFocusRect( &cgrect 
, true , cgContext 
, kHIThemeOrientationNormal 
) ;