]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/renderer.cpp
More support for drawing native column headers, adds more states
[wxWidgets.git] / src / mac / carbon / renderer.cpp
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/mac/uma.h"
30
31
32 class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
33 {
34 public:
35 // draw the header control button (used by wxListCtrl)
36 virtual void DrawHeaderButton( wxWindow *win,
37 wxDC& dc,
38 const wxRect& rect,
39 int flags = 0,
40 wxHeaderButtonParams* params = NULL );
41
42 virtual int GetHeaderButtonHeight(wxWindow *win);
43
44 // draw the expanded/collapsed icon for a tree control item
45 virtual void DrawTreeItemButton( wxWindow *win,
46 wxDC& dc,
47 const wxRect& rect,
48 int flags = 0 );
49
50 // draw a (vertical) sash
51 virtual void DrawSplitterSash( wxWindow *win,
52 wxDC& dc,
53 const wxSize& size,
54 wxCoord position,
55 wxOrientation orient,
56 int flags = 0 );
57
58 private:
59 // the tree buttons
60 wxBitmap m_bmpTreeExpanded;
61 wxBitmap m_bmpTreeCollapsed;
62 };
63
64 // ----------------------------------------------------------------------------
65 // Aqua arrows
66 // ----------------------------------------------------------------------------
67
68 /* XPM */
69 static const char *aqua_arrow_right_xpm[] =
70 {
71 // columns rows colors chars-per-pixel
72 "13 11 4 1",
73 " c None",
74 "b c #C0C0C0",
75 "c c #707070",
76 "d c #A0A0A0",
77
78 // pixels
79 " b ",
80 " ddb ",
81 " cccdb ",
82 " cccccd ",
83 " ccccccdb ",
84 " ccccccccd",
85 " ccccccdb ",
86 " cccccb ",
87 " cccdb ",
88 " ddb ",
89 " b "
90 };
91
92 /* XPM */
93 static const char *aqua_arrow_down_xpm[] =
94 {
95 // columns rows colors chars-per-pixel
96 "13 11 4 1",
97 " c None",
98 "b c #C0C0C0",
99 "c c #707070",
100 "d c #A0A0A0",
101
102 // pixels
103 " ",
104 " ",
105 " bdcccccccdb ",
106 " dcccccccd ",
107 " bcccccccb ",
108 " dcccccd ",
109 " bcccccb ",
110 " bcccd ",
111 " dcd ",
112 " bcb ",
113 " d "
114 };
115
116 // ============================================================================
117 // implementation
118 // ============================================================================
119
120 // static
121 wxRendererNative& wxRendererNative::GetDefault()
122 {
123 static wxRendererMac s_rendererMac;
124
125 return s_rendererMac;
126 }
127
128 void wxRendererMac::DrawHeaderButton( wxWindow *win,
129 wxDC& dc,
130 const wxRect& rect,
131 int flags,
132 wxHeaderButtonParams* params )
133 {
134 const wxCoord x = dc.XLOG2DEV(rect.x /*- 1*/);
135 const wxCoord y = dc.YLOG2DEV(rect.y /*- 1*/);
136 const wxCoord w = dc.XLOG2DEVREL(rect.width);
137 const wxCoord h = dc.YLOG2DEVREL(rect.height);
138
139 dc.SetBrush( *wxTRANSPARENT_BRUSH );
140
141 HIRect headerRect = CGRectMake( x, y, w, h );
142 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
143 {
144 Rect r =
145 {
146 (short) headerRect.origin.y, (short) headerRect.origin.x,
147 (short) (headerRect.origin.y + headerRect.size.height),
148 (short) (headerRect.origin.x + headerRect.size.width)
149 };
150
151 RgnHandle updateRgn = NewRgn();
152 RectRgn( updateRgn, &r );
153 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
154 DisposeRgn( updateRgn );
155 }
156 else
157 {
158 CGContextRef cgContext;
159
160 #if wxMAC_USE_CORE_GRAPHICS
161 cgContext = ((wxMacCGContext*)(dc.GetGraphicContext()))->GetNativeContext();
162 #else
163 Rect bounds;
164
165 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
166 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
167
168 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
169 CGContextScaleCTM( cgContext, 1, -1 );
170
171 HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle) dc.m_macCurrentClipRgn ), cgContext );
172 CGContextClip( cgContext );
173 HIViewConvertRect( &headerRect, (HIViewRef) win->GetHandle(), (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
174 #endif
175
176 {
177 HIThemeButtonDrawInfo drawInfo;
178 HIRect labelRect;
179
180 memset( &drawInfo, 0, sizeof(drawInfo) );
181 drawInfo.version = 0;
182 drawInfo.kind = kThemeListHeaderButton;
183 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
184 drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
185 drawInfo.adornment = kThemeAdornmentNone;
186
187 // The down arrow is drawn automatically, change it to an up arrow if needed.
188 if ( flags & wxCONTROL_UPICON )
189 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
190
191 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
192
193 // If we don't want any arrows we need to draw over the one already there
194 if ( (flags & wxCONTROL_SELECTED) && !(flags & (wxCONTROL_UPICON|wxCONTROL_DOWNICON)) )
195 {
196 // clip to the header rectangle
197 CGContextSaveGState( cgContext );
198 CGContextClipToRect( cgContext, headerRect );
199 // but draw bigger than that so the arrow will get clipped off
200 headerRect.size.width += 25;
201 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
202 CGContextRestoreGState( cgContext );
203 }
204 }
205
206 #if wxMAC_USE_CORE_GRAPHICS
207 #else
208 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
209 #endif
210 }
211
212 // Reserve room for the arrows before writing the label, and turn off the
213 // flags we've already handled
214 wxRect newRect(rect);
215 if ( (flags & wxCONTROL_SELECTED) && (flags & (wxCONTROL_UPICON|wxCONTROL_DOWNICON)) )
216 {
217 newRect.width -= 12;
218 }
219 flags &= ~(wxCONTROL_SELECTED | wxCONTROL_UPICON | wxCONTROL_DOWNICON);
220
221 DrawHeaderButtonContents(win, dc, newRect, flags, params);
222 }
223
224
225 int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
226 {
227 SInt32 standardHeight;
228 OSStatus errStatus;
229
230 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
231 if (errStatus == noErr)
232 {
233 return standardHeight;
234 }
235 return -1;
236 }
237
238
239 void wxRendererMac::DrawTreeItemButton( wxWindow *win,
240 wxDC& dc,
241 const wxRect& rect,
242 int flags )
243 {
244 // init the buttons on demand
245 if ( !m_bmpTreeExpanded.Ok() )
246 {
247 m_bmpTreeExpanded = wxBitmap(aqua_arrow_down_xpm);
248 m_bmpTreeCollapsed = wxBitmap(aqua_arrow_right_xpm);
249 }
250
251 // draw them
252
253 // VZ: this is the old code from treectlg.cpp which apparently doesn't work
254 // but I kept it here just in case it is needed -- if not, please
255 // remove it
256
257 #if 0 // def __WXMAC__
258 wxMacPortSetter helper(&dc);
259 wxMacWindowClipper clipper(this);
260 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() );
261
262 int loc_x = x - 5;
263 int loc_y = y_mid - 6;
264 MacWindowToRootWindow( &loc_x, &loc_y );
265 Rect bounds = { loc_y, loc_x, loc_y + 18, loc_x + 12 };
266 ThemeButtonDrawInfo info =
267 {
268 kThemeStateActive,
269 item->IsExpanded() ? kThemeDisclosureDown : kThemeDisclosureRight,
270 kThemeAdornmentNone
271 };
272
273 DrawThemeButton( &bounds, kThemeDisclosureButton, &info, NULL, NULL, NULL, NULL );
274 #else // 1
275 dc.DrawBitmap(
276 flags & wxCONTROL_EXPANDED
277 ? m_bmpTreeExpanded
278 : m_bmpTreeCollapsed,
279 rect.x, rect.y, true /* use mask */);
280 #endif
281 }
282
283 void wxRendererMac::DrawSplitterSash( wxWindow *win,
284 wxDC& dc,
285 const wxSize& size,
286 wxCoord position,
287 wxOrientation orient,
288 int WXUNUSED(flags) )
289 {
290 bool hasMetal = win->MacGetTopLevelWindow()->MacGetMetalAppearance();
291 SInt32 height;
292 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
293 HIRect splitterRect;
294 if (orient == wxVERTICAL)
295 splitterRect = CGRectMake( position, 0, height, size.y );
296 else
297 splitterRect = CGRectMake( 0, position, size.x, height );
298
299 #if !wxMAC_USE_CORE_GRAPHICS
300 HIViewConvertRect(
301 &splitterRect,
302 (HIViewRef) win->GetHandle(),
303 (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
304 #endif
305
306 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
307 // strange redraw errors occur if we don't do this
308
309 if ( !dc.IsKindOf( CLASSINFO( wxPaintDC ) ) )
310 {
311 Rect r =
312 {
313 (short) splitterRect.origin.y,
314 (short) splitterRect.origin.x,
315 (short) (splitterRect.origin.y + splitterRect.size.height),
316 (short) (splitterRect.origin.x + splitterRect.size.width)
317 };
318
319 RgnHandle updateRgn = NewRgn();
320 RectRgn( updateRgn, &r );
321 HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
322 DisposeRgn( updateRgn );
323 }
324 else
325 {
326 CGContextRef cgContext;
327
328 #if wxMAC_USE_CORE_GRAPHICS
329 cgContext = ((wxMacCGContext*)(dc.GetGraphicContext()))->GetNativeContext();
330 #else
331 Rect bounds;
332 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
333 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
334 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
335 CGContextScaleCTM( cgContext, 1, -1 );
336 #endif
337
338 HIThemeSplitterDrawInfo drawInfo;
339 drawInfo.version = 0;
340 drawInfo.state = kThemeStateActive;
341 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
342 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
343
344 #if wxMAC_USE_CORE_GRAPHICS
345 #else
346 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
347 #endif
348 }
349 }