]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/renderer.cpp
minor fixes; replace references to Windows95 with references to wxMSW where possible
[wxWidgets.git] / src / osx / carbon / renderer.cpp
CommitLineData
489468fe 1///////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/carbon/renderer.cpp
489468fe
SC
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"
524c47aa 30#include "wx/dcgraph.h"
b2680ced 31#include "wx/osx/private.h"
489468fe 32
524c47aa
SC
33#if wxOSX_USE_COCOA
34// bring in the theme headers
35#include <Carbon/Carbon.h>
36#endif
489468fe
SC
37
38class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
39{
40public:
41 // draw the header control button (used by wxListCtrl)
42 virtual int DrawHeaderButton( wxWindow *win,
43 wxDC& dc,
44 const wxRect& rect,
45 int flags = 0,
46 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
47 wxHeaderButtonParams* params = NULL );
48
49 virtual int GetHeaderButtonHeight(wxWindow *win);
50
51 // draw the expanded/collapsed icon for a tree control item
52 virtual void DrawTreeItemButton( wxWindow *win,
53 wxDC& dc,
54 const wxRect& rect,
55 int flags = 0 );
56
57 // draw a (vertical) sash
58 virtual void DrawSplitterSash( wxWindow *win,
59 wxDC& dc,
60 const wxSize& size,
61 wxCoord position,
62 wxOrientation orient,
63 int flags = 0 );
64
65 virtual void DrawCheckBox(wxWindow *win,
66 wxDC& dc,
67 const wxRect& rect,
68 int flags = 0);
69
e8759560
VZ
70 virtual wxSize GetCheckBoxSize(wxWindow* win);
71
489468fe
SC
72 virtual void DrawComboBoxDropButton(wxWindow *win,
73 wxDC& dc,
74 const wxRect& rect,
75 int flags = 0);
76
77 virtual void DrawPushButton(wxWindow *win,
78 wxDC& dc,
79 const wxRect& rect,
80 int flags = 0);
81
82 virtual void DrawItemSelectionRect(wxWindow *win,
83 wxDC& dc,
84 const wxRect& rect,
85 int flags = 0);
86
87 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
88
89private:
90 void DrawMacThemeButton(wxWindow *win,
91 wxDC& dc,
92 const wxRect& rect,
93 int flags,
94 int kind,
95 int adornment);
96
97 // the tree buttons
98 wxBitmap m_bmpTreeExpanded;
99 wxBitmap m_bmpTreeCollapsed;
100};
101
102// ============================================================================
103// implementation
104// ============================================================================
105
106// static
107wxRendererNative& wxRendererNative::GetDefault()
108{
109 static wxRendererMac s_rendererMac;
110
111 return s_rendererMac;
112}
113
114int wxRendererMac::DrawHeaderButton( wxWindow *win,
115 wxDC& dc,
116 const wxRect& rect,
117 int flags,
118 wxHeaderSortIconType sortArrow,
119 wxHeaderButtonParams* params )
120{
121 const wxCoord x = rect.x;
122 const wxCoord y = rect.y;
123 const wxCoord w = rect.width;
124 const wxCoord h = rect.height;
125
126 dc.SetBrush( *wxTRANSPARENT_BRUSH );
127
128 HIRect headerRect = CGRectMake( x, y, w, h );
129 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
130 {
131 win->Refresh( &rect );
132 }
133 else
134 {
135 CGContextRef cgContext;
136 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
137
138 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
139
140 {
141 HIThemeButtonDrawInfo drawInfo;
142 HIRect labelRect;
143
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;
150
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;
154
155 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
156
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) )
159 {
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 );
167 }
168 }
169 }
170
171 // Reserve room for the arrows before writing the label, and turn off the
172 // flags we've already handled
173 wxRect newRect(rect);
174 if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
175 {
176 newRect.width -= 12;
177 sortArrow = wxHDR_SORT_ICON_NONE;
178 }
179 flags &= ~wxCONTROL_SELECTED;
180
181 return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
182}
183
184
185int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
186{
187 SInt32 standardHeight;
188 OSStatus errStatus;
189
190 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
191 if (errStatus == noErr)
192 {
193 return standardHeight;
194 }
195 return -1;
196}
197
198void wxRendererMac::DrawTreeItemButton( wxWindow *win,
199 wxDC& dc,
200 const wxRect& rect,
201 int flags )
202{
203 // now the wxGCDC is using native transformations
204 const wxCoord x = rect.x;
205 const wxCoord y = rect.y;
206 const wxCoord w = rect.width;
207 const wxCoord h = rect.height;
208
209 dc.SetBrush( *wxTRANSPARENT_BRUSH );
210
211 HIRect headerRect = CGRectMake( x, y, w, h );
212 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
213 {
214 win->Refresh( &rect );
215 }
216 else
217 {
218 CGContextRef cgContext;
219
220 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
221 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
222
223 HIThemeButtonDrawInfo drawInfo;
224 HIRect labelRect;
225
226 memset( &drawInfo, 0, sizeof(drawInfo) );
227 drawInfo.version = 0;
228 drawInfo.kind = kThemeDisclosureButton;
229 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
230 // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
231 // We need to set the value using the 'old' DrawThemeButton constants instead.
232 drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
233 drawInfo.adornment = kThemeAdornmentNone;
234
235 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
236 }
237}
238
239void wxRendererMac::DrawSplitterSash( wxWindow *win,
240 wxDC& dc,
241 const wxSize& size,
242 wxCoord position,
243 wxOrientation orient,
244 int WXUNUSED(flags) )
245{
b2680ced 246 bool hasMetal = win->MacGetTopLevelWindow()->GetExtraStyle() & wxFRAME_EX_METAL;
489468fe
SC
247 SInt32 height;
248 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
249 HIRect splitterRect;
250 if (orient == wxVERTICAL)
251 splitterRect = CGRectMake( position, 0, height, size.y );
252 else
253 splitterRect = CGRectMake( 0, position, size.x, height );
254
255 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
256 // strange redraw errors occur if we don't do this
257
258 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
259 {
260 wxRect rect( (int) splitterRect.origin.x, (int) splitterRect.origin.y, (int) splitterRect.size.width,
261 (int) splitterRect.size.height );
262 win->Refresh( &rect );
263 }
264 else
265 {
266 CGContextRef cgContext;
267 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
268 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
269
270 HIThemeSplitterDrawInfo drawInfo;
271 drawInfo.version = 0;
272 drawInfo.state = kThemeStateActive;
273 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
274 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
275 }
276}
277
278void
279wxRendererMac::DrawItemSelectionRect(wxWindow * WXUNUSED(win),
280 wxDC& dc,
281 const wxRect& rect,
282 int flags)
283{
284 if ( !(flags & wxCONTROL_SELECTED) )
285 return;
286
287 wxColour col( wxMacCreateCGColorFromHITheme( (flags & wxCONTROL_FOCUSED) ?
288 kThemeBrushAlternatePrimaryHighlightColor
289 : kThemeBrushSecondaryHighlightColor ) );
290 wxBrush selBrush( col );
291
292 dc.SetPen( *wxTRANSPARENT_PEN );
293 dc.SetBrush( selBrush );
294 dc.DrawRectangle( rect );
295}
296
297
298void
299wxRendererMac::DrawMacThemeButton(wxWindow *win,
300 wxDC& dc,
301 const wxRect& rect,
302 int flags,
303 int kind,
304 int adornment)
305{
306 // now the wxGCDC is using native transformations
307 const wxCoord x = rect.x;
308 const wxCoord y = rect.y;
309 const wxCoord w = rect.width;
310 const wxCoord h = rect.height;
311
312 dc.SetBrush( *wxTRANSPARENT_BRUSH );
313
314 HIRect headerRect = CGRectMake( x, y, w, h );
315 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
316 {
317 win->Refresh( &rect );
318 }
319 else
320 {
321 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
322 CGContextRef cgContext;
323 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
324
325 HIThemeButtonDrawInfo drawInfo;
326 HIRect labelRect;
327
328 memset( &drawInfo, 0, sizeof(drawInfo) );
329 drawInfo.version = 0;
330 drawInfo.kind = kind;
331 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
332 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
333 if (flags & wxCONTROL_UNDETERMINED)
334 drawInfo.value = kThemeButtonMixed;
335 drawInfo.adornment = adornment;
336
337 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
338 }
339}
340
341void
342wxRendererMac::DrawCheckBox(wxWindow *win,
343 wxDC& dc,
344 const wxRect& rect,
345 int flags)
346{
347 if (flags & wxCONTROL_CHECKED)
348 flags |= wxCONTROL_SELECTED;
349
350 DrawMacThemeButton(win, dc, rect, flags,
351 kThemeCheckBox, kThemeAdornmentNone);
352}
353
e8759560
VZ
354wxSize wxRendererMac::GetCheckBoxSize(wxWindow* WXUNUSED(win))
355{
356 wxSize size;
357 SInt32 width, height;
358 OSStatus errStatus;
359
360 errStatus = GetThemeMetric(kThemeMetricCheckBoxWidth, &width);
361 if (errStatus == noErr)
362 {
363 size.SetWidth(width);
364 }
365
366 errStatus = GetThemeMetric(kThemeMetricCheckBoxHeight, &height);
367 if (errStatus == noErr)
368 {
369 size.SetHeight(height);
370 }
371
372 return size;
373}
374
489468fe
SC
375void
376wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
377 wxDC& dc,
378 const wxRect& rect,
379 int flags)
380{
381 int kind;
382 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
383 kind = kThemeArrowButtonSmall;
384 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
385 kind = kThemeArrowButtonMini;
386 else
387 kind = kThemeArrowButton;
388
389 DrawMacThemeButton(win, dc, rect, flags,
390 kind, kThemeAdornmentArrowDownArrow);
391}
392
393void
394wxRendererMac::DrawPushButton(wxWindow *win,
395 wxDC& dc,
396 const wxRect& rect,
397 int flags)
398{
399 int kind;
400 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
401 kind = kThemeBevelButtonSmall;
402 // There is no kThemeBevelButtonMini, but in this case, use Small
403 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
404 kind = kThemeBevelButtonSmall;
405 else
406 kind = kThemeBevelButton;
407
408 DrawMacThemeButton(win, dc, rect, flags,
409 kind, kThemeAdornmentNone);
410}
411
412void
413wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
414{
415 if (!win)
416 {
417 wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
418 return;
419 }
420
421 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
422
423 HIThemeFrameDrawInfo info ;
424 memset( &info, 0 , sizeof(info) ) ;
425
426 info.version = 0 ;
427 info.kind = 0 ;
428 info.state = kThemeStateActive;
429 info.isFocused = true ;
430
431 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
432 wxASSERT( cgContext ) ;
433
434 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
435}