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