]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/renderer.cpp
64 bit clean printing
[wxWidgets.git] / src / mac / carbon / renderer.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/mac/carbon/renderer.cpp
3// Purpose: implementation of wxRendererNative for Mac
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>
9// License: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
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"
21 #include "wx/dc.h"
22 #include "wx/bitmap.h"
23 #include "wx/settings.h"
24 #include "wx/dcclient.h"
25 #include "wx/toplevel.h"
26#endif
27
28#include "wx/renderer.h"
29#include "wx/graphics.h"
30#include "wx/mac/uma.h"
31
32
33class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
34{
35public:
36 // draw the header control button (used by wxListCtrl)
37 virtual int DrawHeaderButton( wxWindow *win,
38 wxDC& dc,
39 const wxRect& rect,
40 int flags = 0,
41 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
42 wxHeaderButtonParams* params = NULL );
43
44 virtual int GetHeaderButtonHeight(wxWindow *win);
45
46 // draw the expanded/collapsed icon for a tree control item
47 virtual void DrawTreeItemButton( wxWindow *win,
48 wxDC& dc,
49 const wxRect& rect,
50 int flags = 0 );
51
52 // draw a (vertical) sash
53 virtual void DrawSplitterSash( wxWindow *win,
54 wxDC& dc,
55 const wxSize& size,
56 wxCoord position,
57 wxOrientation orient,
58 int flags = 0 );
59
60 virtual void DrawCheckBox(wxWindow *win,
61 wxDC& dc,
62 const wxRect& rect,
63 int flags = 0);
64
65 virtual void DrawComboBoxDropButton(wxWindow *win,
66 wxDC& dc,
67 const wxRect& rect,
68 int flags = 0);
69
70 virtual void DrawPushButton(wxWindow *win,
71 wxDC& dc,
72 const wxRect& rect,
73 int flags = 0);
74
75 virtual void DrawItemSelectionRect(wxWindow *win,
76 wxDC& dc,
77 const wxRect& rect,
78 int flags = 0);
79
80 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
81
82private:
83 void DrawMacThemeButton(wxWindow *win,
84 wxDC& dc,
85 const wxRect& rect,
86 int flags,
87 int kind,
88 int adornment);
89
90 // the tree buttons
91 wxBitmap m_bmpTreeExpanded;
92 wxBitmap m_bmpTreeCollapsed;
93};
94
95// ============================================================================
96// implementation
97// ============================================================================
98
99// static
100wxRendererNative& wxRendererNative::GetDefault()
101{
102 static wxRendererMac s_rendererMac;
103
104 return s_rendererMac;
105}
106
107int wxRendererMac::DrawHeaderButton( wxWindow *win,
108 wxDC& dc,
109 const wxRect& rect,
110 int flags,
111 wxHeaderSortIconType sortArrow,
112 wxHeaderButtonParams* params )
113{
114 const wxCoord x = rect.x;
115 const wxCoord y = rect.y;
116 const wxCoord w = rect.width;
117 const wxCoord h = rect.height;
118
119 dc.SetBrush( *wxTRANSPARENT_BRUSH );
120
121 HIRect headerRect = CGRectMake( x, y, w, h );
122 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
123 {
124 Rect r =
125 {
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;
139
140 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
141
142 {
143 HIThemeButtonDrawInfo drawInfo;
144 HIRect labelRect;
145
146 memset( &drawInfo, 0, sizeof(drawInfo) );
147 drawInfo.version = 0;
148 drawInfo.kind = kThemeListHeaderButton;
149 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
150 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
151 drawInfo.adornment = kThemeAdornmentNone;
152
153 // The down arrow is drawn automatically, change it to an up arrow if needed.
154 if ( sortArrow == wxHDR_SORT_ICON_UP )
155 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
156
157 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
158
159 // If we don't want any arrows we need to draw over the one already there
160 if ( (flags & wxCONTROL_SELECTED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
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 );
169 }
170 }
171 }
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);
176 if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
177 {
178 newRect.width -= 12;
179 sortArrow = wxHDR_SORT_ICON_NONE;
180 }
181 flags &= ~wxCONTROL_SELECTED;
182
183 return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
184}
185
186
187int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
188{
189 SInt32 standardHeight;
190 OSStatus errStatus;
191
192 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
193 if (errStatus == noErr)
194 {
195 return standardHeight;
196 }
197 return -1;
198}
199
200void wxRendererMac::DrawTreeItemButton( wxWindow *win,
201 wxDC& dc,
202 const wxRect& rect,
203 int flags )
204{
205 // now the wxGCDC is using native transformations
206 const wxCoord x = rect.x;
207 const wxCoord y = rect.y;
208 const wxCoord w = rect.width;
209 const wxCoord h = rect.height;
210
211 dc.SetBrush( *wxTRANSPARENT_BRUSH );
212
213 HIRect headerRect = CGRectMake( x, y, w, h );
214 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
215 {
216 Rect r =
217 {
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 );
227 }
228 else
229 {
230 CGContextRef cgContext;
231
232 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
233
234 HIThemeButtonDrawInfo drawInfo;
235 HIRect labelRect;
236
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 );
247 }
248}
249
250void wxRendererMac::DrawSplitterSash( wxWindow *win,
251 wxDC& dc,
252 const wxSize& size,
253 wxCoord position,
254 wxOrientation orient,
255 int WXUNUSED(flags) )
256{
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 );
265
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
268
269 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
270 {
271 Rect r =
272 {
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;
287
288 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
289
290 HIThemeSplitterDrawInfo drawInfo;
291 drawInfo.version = 0;
292 drawInfo.state = kThemeStateActive;
293 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
294 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
295 }
296}
297
298void
299wxRendererMac::DrawItemSelectionRect(wxWindow *win,
300 wxDC& dc,
301 const wxRect& rect,
302 int flags )
303{
304 if ( !(flags & wxCONTROL_SELECTED) )
305 return;
306
307 if (flags & wxCONTROL_FOCUSED)
308 {
309 if (!IsControlActive( (ControlRef)win->GetHandle() ))
310 flags = wxCONTROL_SELECTED;
311 }
312
313 RGBColor selColor;
314 GetThemeBrushAsColor(flags & wxCONTROL_FOCUSED
315 ? kThemeBrushAlternatePrimaryHighlightColor
316 : kThemeBrushSecondaryHighlightColor,
317 32, true, &selColor);
318
319 wxBrush selBrush(selColor);
320
321 dc.SetPen( *wxTRANSPARENT_PEN );
322 dc.SetBrush( selBrush );
323 dc.DrawRectangle( rect );
324}
325
326
327void
328wxRendererMac::DrawMacThemeButton(wxWindow *win,
329 wxDC& dc,
330 const wxRect& rect,
331 int flags,
332 int kind,
333 int adornment)
334{
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;
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;
361 cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
362
363 HIThemeButtonDrawInfo drawInfo;
364 HIRect labelRect;
365
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 );
376 }
377}
378
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}
391
392void
393wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
394 wxDC& dc,
395 const wxRect& rect,
396 int flags)
397{
398 int kind;
399 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
400 kind = kThemeArrowButtonSmall;
401 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
402 kind = kThemeArrowButtonMini;
403 else
404 kind = kThemeArrowButton;
405
406 DrawMacThemeButton(win, dc, rect, flags,
407 kind, kThemeAdornmentArrowDownArrow);
408}
409
410void
411wxRendererMac::DrawPushButton(wxWindow *win,
412 wxDC& dc,
413 const wxRect& rect,
414 int flags)
415{
416 int kind;
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))
421 kind = kThemeBevelButtonSmall;
422 else
423 kind = kThemeBevelButton;
424
425 DrawMacThemeButton(win, dc, rect, flags,
426 kind, kThemeAdornmentNone);
427}
428
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
438 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
439
440 HIThemeFrameDrawInfo info ;
441 memset( &info, 0 , sizeof(info) ) ;
442
443 info.version = 0 ;
444 info.kind = 0 ;
445 info.state = kThemeStateActive;
446 info.isFocused = true ;
447
448 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
449 wxASSERT( cgContext ) ;
450
451 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
452}
453