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