]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/renderer.cpp
textctrl always needs ATSU...
[wxWidgets.git] / src / mac / carbon / renderer.cpp
CommitLineData
9c7f49f5 1///////////////////////////////////////////////////////////////////////////////
7af14d71 2// Name: src/mac/carbon/renderer.cpp
38c4cb6a 3// Purpose: implementation of wxRendererNative for Mac
9c7f49f5
VZ
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.07.2003
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
65571936 9// License: wxWindows licence
9c7f49f5
VZ
10///////////////////////////////////////////////////////////////////////////////
11
9c7f49f5
VZ
12// for compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20 #include "wx/string.h"
4c948343
VZ
21 #include "wx/dc.h"
22 #include "wx/bitmap.h"
23 #include "wx/settings.h"
ed4b0fdc 24 #include "wx/dcclient.h"
1832043f 25 #include "wx/toplevel.h"
7af14d71 26#endif
9c7f49f5
VZ
27
28#include "wx/renderer.h"
8acd14d1 29#include "wx/graphics.h"
547aafd2 30#include "wx/mac/uma.h"
9c7f49f5 31
9c7f49f5 32
5cb80ad2 33class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
9c7f49f5
VZ
34{
35public:
36 // draw the header control button (used by wxListCtrl)
c97c9952 37 virtual int DrawHeaderButton( wxWindow *win,
7af14d71
DS
38 wxDC& dc,
39 const wxRect& rect,
4b94ddc4 40 int flags = 0,
80752b57 41 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
4b94ddc4 42 wxHeaderButtonParams* params = NULL );
9c7f49f5 43
4b94ddc4 44 virtual int GetHeaderButtonHeight(wxWindow *win);
a61c9122 45
9c7f49f5 46 // draw the expanded/collapsed icon for a tree control item
7af14d71
DS
47 virtual void DrawTreeItemButton( wxWindow *win,
48 wxDC& dc,
49 const wxRect& rect,
50 int flags = 0 );
9c7f49f5 51
b3208e11 52 // draw a (vertical) sash
7af14d71
DS
53 virtual void DrawSplitterSash( wxWindow *win,
54 wxDC& dc,
55 const wxSize& size,
56 wxCoord position,
57 wxOrientation orient,
58 int flags = 0 );
cf511e87 59
6239ee05
SC
60 virtual void DrawCheckBox(wxWindow *win,
61 wxDC& dc,
62 const wxRect& rect,
63 int flags = 0);
64
cf511e87
RD
65 virtual void DrawComboBoxDropButton(wxWindow *win,
66 wxDC& dc,
67 const wxRect& rect,
68 int flags = 0);
a61c9122 69
cf511e87
RD
70 virtual void DrawPushButton(wxWindow *win,
71 wxDC& dc,
72 const wxRect& rect,
73 int flags = 0);
a61c9122 74
a4609ab8
KO
75 virtual void DrawItemSelectionRect(wxWindow *win,
76 wxDC& dc,
77 const wxRect& rect,
78 int flags = 0);
b3208e11 79
688a201a
JS
80 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
81
9c7f49f5 82private:
cf511e87
RD
83 void DrawMacThemeButton(wxWindow *win,
84 wxDC& dc,
85 const wxRect& rect,
86 int flags,
87 int kind,
88 int adornment);
a61c9122 89
9c7f49f5 90 // the tree buttons
7af14d71
DS
91 wxBitmap m_bmpTreeExpanded;
92 wxBitmap m_bmpTreeCollapsed;
9c7f49f5
VZ
93};
94
9c7f49f5
VZ
95// ============================================================================
96// implementation
97// ============================================================================
98
7af14d71 99// static
f0244295 100wxRendererNative& wxRendererNative::GetDefault()
9c7f49f5
VZ
101{
102 static wxRendererMac s_rendererMac;
103
104 return s_rendererMac;
105}
106
c97c9952 107int wxRendererMac::DrawHeaderButton( wxWindow *win,
7af14d71
DS
108 wxDC& dc,
109 const wxRect& rect,
4b94ddc4 110 int flags,
80752b57 111 wxHeaderSortIconType sortArrow,
4b94ddc4 112 wxHeaderButtonParams* params )
9c7f49f5 113{
1c5decd0
SC
114 const wxCoord x = rect.x;
115 const wxCoord y = rect.y;
116 const wxCoord w = rect.width;
117 const wxCoord h = rect.height;
7af14d71 118
11d1adbf 119 dc.SetBrush( *wxTRANSPARENT_BRUSH );
9c7f49f5 120
a62f32af
SC
121 HIRect headerRect = CGRectMake( x, y, w, h );
122 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
2480cf88 123 {
f968da28 124 win->Refresh( &rect );
a62f32af
SC
125 }
126 else
127 {
128 CGContextRef cgContext;
888dde65
RR
129 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
130
131 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
7af14d71 132
a62f32af
SC
133 {
134 HIThemeButtonDrawInfo drawInfo;
135 HIRect labelRect;
7af14d71 136
a62f32af
SC
137 memset( &drawInfo, 0, sizeof(drawInfo) );
138 drawInfo.version = 0;
a62f32af 139 drawInfo.kind = kThemeListHeaderButton;
4b94ddc4
RD
140 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
141 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
a62f32af 142 drawInfo.adornment = kThemeAdornmentNone;
4b94ddc4
RD
143
144 // The down arrow is drawn automatically, change it to an up arrow if needed.
80752b57 145 if ( sortArrow == wxHDR_SORT_ICON_UP )
4b94ddc4 146 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
a61c9122 147
a62f32af 148 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
4b94ddc4
RD
149
150 // If we don't want any arrows we need to draw over the one already there
80752b57 151 if ( (flags & wxCONTROL_SELECTED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
4b94ddc4
RD
152 {
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 );
a61c9122 160 }
a62f32af 161 }
11d1adbf 162 }
4b94ddc4
RD
163
164 // Reserve room for the arrows before writing the label, and turn off the
165 // flags we've already handled
166 wxRect newRect(rect);
80752b57 167 if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
4b94ddc4
RD
168 {
169 newRect.width -= 12;
80752b57 170 sortArrow = wxHDR_SORT_ICON_NONE;
4b94ddc4 171 }
80752b57 172 flags &= ~wxCONTROL_SELECTED;
4b94ddc4 173
c97c9952 174 return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
4b94ddc4
RD
175}
176
177
178int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
179{
688a201a
JS
180 SInt32 standardHeight;
181 OSStatus errStatus;
4b94ddc4
RD
182
183 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
184 if (errStatus == noErr)
185 {
186 return standardHeight;
187 }
188 return -1;
9c7f49f5
VZ
189}
190
7af14d71
DS
191void wxRendererMac::DrawTreeItemButton( wxWindow *win,
192 wxDC& dc,
193 const wxRect& rect,
194 int flags )
9c7f49f5 195{
1c5decd0 196 // now the wxGCDC is using native transformations
f3d0a750
RD
197 const wxCoord x = rect.x;
198 const wxCoord y = rect.y;
199 const wxCoord w = rect.width;
200 const wxCoord h = rect.height;
1c5decd0 201
46b59ead
KO
202 dc.SetBrush( *wxTRANSPARENT_BRUSH );
203
204 HIRect headerRect = CGRectMake( x, y, w, h );
205 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
206 {
f968da28 207 win->Refresh( &rect );
9c7f49f5 208 }
46b59ead
KO
209 else
210 {
211 CGContextRef cgContext;
9c7f49f5 212
888dde65
RR
213 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
214 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
7af14d71 215
e1673e52
SC
216 HIThemeButtonDrawInfo drawInfo;
217 HIRect labelRect;
46b59ead 218
e1673e52
SC
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;
227
228 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
46b59ead 229 }
9c7f49f5
VZ
230}
231
7af14d71
DS
232void wxRendererMac::DrawSplitterSash( wxWindow *win,
233 wxDC& dc,
234 const wxSize& size,
235 wxCoord position,
236 wxOrientation orient,
237 int WXUNUSED(flags) )
b3208e11 238{
a62f32af
SC
239 bool hasMetal = win->MacGetTopLevelWindow()->MacGetMetalAppearance();
240 SInt32 height;
241 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
242 HIRect splitterRect;
243 if (orient == wxVERTICAL)
244 splitterRect = CGRectMake( position, 0, height, size.y );
245 else
246 splitterRect = CGRectMake( 0, position, size.x, height );
7af14d71 247
a62f32af
SC
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
547aafd2 250
a62f32af
SC
251 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
252 {
65108179
SC
253 wxRect rect( (int) splitterRect.origin.x, (int) splitterRect.origin.y, (int) splitterRect.size.width,
254 (int) splitterRect.size.height );
f968da28
SC
255 win->Refresh( &rect );
256 }
a62f32af
SC
257 else
258 {
259 CGContextRef cgContext;
888dde65
RR
260 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
261 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
547aafd2 262
a62f32af
SC
263 HIThemeSplitterDrawInfo drawInfo;
264 drawInfo.version = 0;
265 drawInfo.state = kThemeStateActive;
266 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
267 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
547aafd2 268 }
b3208e11 269}
a4609ab8
KO
270
271void
272wxRendererMac::DrawItemSelectionRect(wxWindow *win,
273 wxDC& dc,
274 const wxRect& rect,
275 int flags )
276{
055de350
VZ
277 if ( !(flags & wxCONTROL_SELECTED) )
278 return;
65108179
SC
279
280 wxColour col( wxMacCreateCGColorFromHITheme( (flags & wxCONTROL_FOCUSED) ?
281 kThemeBrushAlternatePrimaryHighlightColor
282 : kThemeBrushSecondaryHighlightColor ) );
283 wxBrush selBrush( col );
284
a4609ab8
KO
285 dc.SetPen( *wxTRANSPARENT_PEN );
286 dc.SetBrush( selBrush );
287 dc.DrawRectangle( rect );
288}
cf511e87
RD
289
290
291void
292wxRendererMac::DrawMacThemeButton(wxWindow *win,
293 wxDC& dc,
294 const wxRect& rect,
295 int flags,
296 int kind,
297 int adornment)
298{
cf511e87
RD
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;
cf511e87
RD
304
305 dc.SetBrush( *wxTRANSPARENT_BRUSH );
306
307 HIRect headerRect = CGRectMake( x, y, w, h );
308 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
309 {
f968da28 310 win->Refresh( &rect );
cf511e87
RD
311 }
312 else
313 {
888dde65 314 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
cf511e87 315 CGContextRef cgContext;
888dde65 316 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
cf511e87 317
e1673e52
SC
318 HIThemeButtonDrawInfo drawInfo;
319 HIRect labelRect;
cf511e87 320
e1673e52
SC
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;
329
330 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
cf511e87
RD
331 }
332}
333
6239ee05
SC
334void
335wxRendererMac::DrawCheckBox(wxWindow *win,
336 wxDC& dc,
337 const wxRect& rect,
338 int flags)
339{
340 if (flags & wxCONTROL_CHECKED)
341 flags |= wxCONTROL_SELECTED;
342
343 DrawMacThemeButton(win, dc, rect, flags,
344 kThemeCheckBox, kThemeAdornmentNone);
345}
cf511e87
RD
346
347void
348wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
349 wxDC& dc,
350 const wxRect& rect,
351 int flags)
352{
f8e1a81f 353 int kind;
a61c9122 354 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
f8e1a81f 355 kind = kThemeArrowButtonSmall;
a61c9122 356 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
f8e1a81f
JS
357 kind = kThemeArrowButtonMini;
358 else
359 kind = kThemeArrowButton;
a61c9122 360
cf511e87 361 DrawMacThemeButton(win, dc, rect, flags,
f8e1a81f 362 kind, kThemeAdornmentArrowDownArrow);
cf511e87 363}
a61c9122 364
cf511e87
RD
365void
366wxRendererMac::DrawPushButton(wxWindow *win,
367 wxDC& dc,
368 const wxRect& rect,
369 int flags)
370{
f8e1a81f 371 int kind;
a61c9122
JS
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))
f8e1a81f
JS
376 kind = kThemeBevelButtonSmall;
377 else
378 kind = kThemeBevelButton;
379
cf511e87 380 DrawMacThemeButton(win, dc, rect, flags,
f8e1a81f 381 kind, kThemeAdornmentNone);
cf511e87 382}
a61c9122 383
688a201a
JS
384void
385wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
386{
387 if (!win)
388 {
389 wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
390 return;
391 }
392
e1673e52 393 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
688a201a 394
e1673e52
SC
395 HIThemeFrameDrawInfo info ;
396 memset( &info, 0 , sizeof(info) ) ;
688a201a 397
e1673e52
SC
398 info.version = 0 ;
399 info.kind = 0 ;
400 info.state = kThemeStateActive;
401 info.isFocused = true ;
688a201a 402
e1673e52
SC
403 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
404 wxASSERT( cgContext ) ;
688a201a 405
e1673e52 406 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
688a201a
JS
407}
408