]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/renderer.cpp
mac cleanup
[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 {
a62f32af 124 Rect r =
2480cf88 125 {
a62f32af
SC
126 (short) headerRect.origin.y, (short) headerRect.origin.x,
127 (short) (headerRect.origin.y + headerRect.size.height),
128 (short) (headerRect.origin.x + headerRect.size.width)
129 };
130
131 RgnHandle updateRgn = NewRgn();
132 RectRgn( updateRgn, &r );
133 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
134 DisposeRgn( updateRgn );
135 }
136 else
137 {
138 CGContextRef cgContext;
7af14d71 139
be01a403 140 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
7af14d71 141
a62f32af
SC
142 {
143 HIThemeButtonDrawInfo drawInfo;
144 HIRect labelRect;
7af14d71 145
a62f32af
SC
146 memset( &drawInfo, 0, sizeof(drawInfo) );
147 drawInfo.version = 0;
a62f32af 148 drawInfo.kind = kThemeListHeaderButton;
4b94ddc4
RD
149 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
150 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
a62f32af 151 drawInfo.adornment = kThemeAdornmentNone;
4b94ddc4
RD
152
153 // The down arrow is drawn automatically, change it to an up arrow if needed.
80752b57 154 if ( sortArrow == wxHDR_SORT_ICON_UP )
4b94ddc4 155 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
a61c9122 156
a62f32af 157 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
4b94ddc4
RD
158
159 // If we don't want any arrows we need to draw over the one already there
80752b57 160 if ( (flags & wxCONTROL_SELECTED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
4b94ddc4
RD
161 {
162 // clip to the header rectangle
163 CGContextSaveGState( cgContext );
164 CGContextClipToRect( cgContext, headerRect );
165 // but draw bigger than that so the arrow will get clipped off
166 headerRect.size.width += 25;
167 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
168 CGContextRestoreGState( cgContext );
a61c9122 169 }
a62f32af 170 }
11d1adbf 171 }
4b94ddc4
RD
172
173 // Reserve room for the arrows before writing the label, and turn off the
174 // flags we've already handled
175 wxRect newRect(rect);
80752b57 176 if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
4b94ddc4
RD
177 {
178 newRect.width -= 12;
80752b57 179 sortArrow = wxHDR_SORT_ICON_NONE;
4b94ddc4 180 }
80752b57 181 flags &= ~wxCONTROL_SELECTED;
4b94ddc4 182
c97c9952 183 return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
4b94ddc4
RD
184}
185
186
187int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
188{
688a201a
JS
189 SInt32 standardHeight;
190 OSStatus errStatus;
4b94ddc4
RD
191
192 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
193 if (errStatus == noErr)
194 {
195 return standardHeight;
196 }
197 return -1;
9c7f49f5
VZ
198}
199
7af14d71
DS
200void wxRendererMac::DrawTreeItemButton( wxWindow *win,
201 wxDC& dc,
202 const wxRect& rect,
203 int flags )
9c7f49f5 204{
1c5decd0 205 // now the wxGCDC is using native transformations
f3d0a750
RD
206 const wxCoord x = rect.x;
207 const wxCoord y = rect.y;
208 const wxCoord w = rect.width;
209 const wxCoord h = rect.height;
1c5decd0 210
46b59ead
KO
211 dc.SetBrush( *wxTRANSPARENT_BRUSH );
212
213 HIRect headerRect = CGRectMake( x, y, w, h );
214 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
215 {
216 Rect r =
9c7f49f5 217 {
46b59ead
KO
218 (short) headerRect.origin.y, (short) headerRect.origin.x,
219 (short) (headerRect.origin.y + headerRect.size.height),
220 (short) (headerRect.origin.x + headerRect.size.width)
221 };
222
223 RgnHandle updateRgn = NewRgn();
224 RectRgn( updateRgn, &r );
225 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
226 DisposeRgn( updateRgn );
9c7f49f5 227 }
46b59ead
KO
228 else
229 {
230 CGContextRef cgContext;
9c7f49f5 231
46b59ead 232 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
7af14d71 233
e1673e52
SC
234 HIThemeButtonDrawInfo drawInfo;
235 HIRect labelRect;
46b59ead 236
e1673e52
SC
237 memset( &drawInfo, 0, sizeof(drawInfo) );
238 drawInfo.version = 0;
239 drawInfo.kind = kThemeDisclosureButton;
240 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
241 // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
242 // We need to set the value using the 'old' DrawThemeButton constants instead.
243 drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
244 drawInfo.adornment = kThemeAdornmentNone;
245
246 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
46b59ead 247 }
9c7f49f5
VZ
248}
249
7af14d71
DS
250void wxRendererMac::DrawSplitterSash( wxWindow *win,
251 wxDC& dc,
252 const wxSize& size,
253 wxCoord position,
254 wxOrientation orient,
255 int WXUNUSED(flags) )
b3208e11 256{
a62f32af
SC
257 bool hasMetal = win->MacGetTopLevelWindow()->MacGetMetalAppearance();
258 SInt32 height;
259 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
260 HIRect splitterRect;
261 if (orient == wxVERTICAL)
262 splitterRect = CGRectMake( position, 0, height, size.y );
263 else
264 splitterRect = CGRectMake( 0, position, size.x, height );
7af14d71 265
a62f32af
SC
266 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
267 // strange redraw errors occur if we don't do this
547aafd2 268
a62f32af
SC
269 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
270 {
271 Rect r =
547aafd2 272 {
a62f32af
SC
273 (short) splitterRect.origin.y,
274 (short) splitterRect.origin.x,
275 (short) (splitterRect.origin.y + splitterRect.size.height),
276 (short) (splitterRect.origin.x + splitterRect.size.width)
277 };
278
279 RgnHandle updateRgn = NewRgn();
280 RectRgn( updateRgn, &r );
281 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
282 DisposeRgn( updateRgn );
283 }
284 else
285 {
286 CGContextRef cgContext;
7af14d71 287
be01a403 288 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
547aafd2 289
a62f32af
SC
290 HIThemeSplitterDrawInfo drawInfo;
291 drawInfo.version = 0;
292 drawInfo.state = kThemeStateActive;
293 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
294 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
547aafd2 295 }
b3208e11 296}
a4609ab8
KO
297
298void
299wxRendererMac::DrawItemSelectionRect(wxWindow *win,
300 wxDC& dc,
301 const wxRect& rect,
302 int flags )
303{
055de350
VZ
304 if ( !(flags & wxCONTROL_SELECTED) )
305 return;
ce0cf2b8
RR
306
307 if (flags & wxCONTROL_FOCUSED)
308 {
309 if (!IsControlActive( (ControlRef)win->GetHandle() ))
310 flags = wxCONTROL_SELECTED;
311 }
055de350 312
a61c9122 313 RGBColor selColor;
055de350
VZ
314 GetThemeBrushAsColor(flags & wxCONTROL_FOCUSED
315 ? kThemeBrushAlternatePrimaryHighlightColor
316 : kThemeBrushSecondaryHighlightColor,
317 32, true, &selColor);
a61c9122 318
055de350 319 wxBrush selBrush(selColor);
a4609ab8
KO
320
321 dc.SetPen( *wxTRANSPARENT_PEN );
322 dc.SetBrush( selBrush );
323 dc.DrawRectangle( rect );
324}
cf511e87
RD
325
326
327void
328wxRendererMac::DrawMacThemeButton(wxWindow *win,
329 wxDC& dc,
330 const wxRect& rect,
331 int flags,
332 int kind,
333 int adornment)
334{
cf511e87
RD
335 // now the wxGCDC is using native transformations
336 const wxCoord x = rect.x;
337 const wxCoord y = rect.y;
338 const wxCoord w = rect.width;
339 const wxCoord h = rect.height;
cf511e87
RD
340
341 dc.SetBrush( *wxTRANSPARENT_BRUSH );
342
343 HIRect headerRect = CGRectMake( x, y, w, h );
344 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
345 {
346 Rect r =
347 {
348 (short) headerRect.origin.y, (short) headerRect.origin.x,
349 (short) (headerRect.origin.y + headerRect.size.height),
350 (short) (headerRect.origin.x + headerRect.size.width)
351 };
352
353 RgnHandle updateRgn = NewRgn();
354 RectRgn( updateRgn, &r );
355 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
356 DisposeRgn( updateRgn );
357 }
358 else
359 {
360 CGContextRef cgContext;
cf511e87 361 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
cf511e87 362
e1673e52
SC
363 HIThemeButtonDrawInfo drawInfo;
364 HIRect labelRect;
cf511e87 365
e1673e52
SC
366 memset( &drawInfo, 0, sizeof(drawInfo) );
367 drawInfo.version = 0;
368 drawInfo.kind = kind;
369 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
370 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
371 if (flags & wxCONTROL_UNDETERMINED)
372 drawInfo.value = kThemeButtonMixed;
373 drawInfo.adornment = adornment;
374
375 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
cf511e87
RD
376 }
377}
378
6239ee05
SC
379void
380wxRendererMac::DrawCheckBox(wxWindow *win,
381 wxDC& dc,
382 const wxRect& rect,
383 int flags)
384{
385 if (flags & wxCONTROL_CHECKED)
386 flags |= wxCONTROL_SELECTED;
387
388 DrawMacThemeButton(win, dc, rect, flags,
389 kThemeCheckBox, kThemeAdornmentNone);
390}
cf511e87
RD
391
392void
393wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
394 wxDC& dc,
395 const wxRect& rect,
396 int flags)
397{
f8e1a81f 398 int kind;
a61c9122 399 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
f8e1a81f 400 kind = kThemeArrowButtonSmall;
a61c9122 401 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
f8e1a81f
JS
402 kind = kThemeArrowButtonMini;
403 else
404 kind = kThemeArrowButton;
a61c9122 405
cf511e87 406 DrawMacThemeButton(win, dc, rect, flags,
f8e1a81f 407 kind, kThemeAdornmentArrowDownArrow);
cf511e87 408}
a61c9122 409
cf511e87
RD
410void
411wxRendererMac::DrawPushButton(wxWindow *win,
412 wxDC& dc,
413 const wxRect& rect,
414 int flags)
415{
f8e1a81f 416 int kind;
a61c9122
JS
417 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
418 kind = kThemeBevelButtonSmall;
419 // There is no kThemeBevelButtonMini, but in this case, use Small
420 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
f8e1a81f
JS
421 kind = kThemeBevelButtonSmall;
422 else
423 kind = kThemeBevelButton;
424
cf511e87 425 DrawMacThemeButton(win, dc, rect, flags,
f8e1a81f 426 kind, kThemeAdornmentNone);
cf511e87 427}
a61c9122 428
688a201a
JS
429void
430wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
431{
432 if (!win)
433 {
434 wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
435 return;
436 }
437
e1673e52 438 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
688a201a 439
e1673e52
SC
440 HIThemeFrameDrawInfo info ;
441 memset( &info, 0 , sizeof(info) ) ;
688a201a 442
e1673e52
SC
443 info.version = 0 ;
444 info.kind = 0 ;
445 info.state = kThemeStateActive;
446 info.isFocused = true ;
688a201a 447
e1673e52
SC
448 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
449 wxASSERT( cgContext ) ;
688a201a 450
e1673e52 451 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
688a201a
JS
452}
453