1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/renderer.cpp
3 // Purpose: implementation of wxRendererNative for Mac
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 20.07.2003
7 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // for compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #if wxOSX_USE_COCOA_OR_CARBON
15
16
17 #ifndef WX_PRECOMP
18 #include "wx/string.h"
19 #include "wx/dc.h"
20 #include "wx/bitmap.h"
21 #include "wx/settings.h"
22 #include "wx/dcclient.h"
23 #include "wx/dcmemory.h"
24 #include "wx/toplevel.h"
25 #endif
26
27 #include "wx/renderer.h"
28 #include "wx/graphics.h"
29 #include "wx/dcgraph.h"
30 #include "wx/splitter.h"
31 #include "wx/time.h"
32 #include "wx/osx/private.h"
33 #include "wx/osx/private/available.h"
34
35 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
36 #include "wx/image.h"
37 #include "wx/mstream.h"
38 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
39
40
41 // check if we're having a CGContext we can draw into
wxHasCGContext(wxWindow * WXUNUSED (win),wxDC & dc)42 inline bool wxHasCGContext(wxWindow* WXUNUSED(win), wxDC& dc)
43 {
44 wxGCDCImpl* gcdc = wxDynamicCast( dc.GetImpl() , wxGCDCImpl);
45
46 if ( gcdc )
47 {
48 if ( gcdc->GetGraphicsContext()->GetNativeContext() )
49 return true;
50 }
51 return false;
52 }
53
54
55
56 class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
57 {
58 public:
59 // draw the header control button (used by wxListCtrl)
60 virtual int DrawHeaderButton( wxWindow *win,
61 wxDC& dc,
62 const wxRect& rect,
63 int flags = 0,
64 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
65 wxHeaderButtonParams* params = NULL ) wxOVERRIDE;
66
67 virtual int GetHeaderButtonHeight(wxWindow *win) wxOVERRIDE;
68
69 virtual int GetHeaderButtonMargin(wxWindow *win) wxOVERRIDE;
70
71 // draw the expanded/collapsed icon for a tree control item
72 virtual void DrawTreeItemButton( wxWindow *win,
73 wxDC& dc,
74 const wxRect& rect,
75 int flags = 0 ) wxOVERRIDE;
76
77 // draw a (vertical) sash
78 virtual void DrawSplitterSash( wxWindow *win,
79 wxDC& dc,
80 const wxSize& size,
81 wxCoord position,
82 wxOrientation orient,
83 int flags = 0 ) wxOVERRIDE;
84
85 virtual void DrawCheckBox(wxWindow *win,
86 wxDC& dc,
87 const wxRect& rect,
88 int flags = 0) wxOVERRIDE;
89
90 virtual wxSize GetCheckBoxSize(wxWindow* win, int flags = 0) wxOVERRIDE;
91
92 virtual void DrawComboBoxDropButton(wxWindow *win,
93 wxDC& dc,
94 const wxRect& rect,
95 int flags = 0) wxOVERRIDE;
96
97 virtual void DrawPushButton(wxWindow *win,
98 wxDC& dc,
99 const wxRect& rect,
100 int flags = 0) wxOVERRIDE;
101
102 virtual void DrawCollapseButton(wxWindow *win,
103 wxDC& dc,
104 const wxRect& rect,
105 int flags = 0) wxOVERRIDE;
106
107 virtual wxSize GetCollapseButtonSize(wxWindow *win, wxDC& dc) wxOVERRIDE;
108
109 virtual void DrawItemSelectionRect(wxWindow *win,
110 wxDC& dc,
111 const wxRect& rect,
112 int flags = 0) wxOVERRIDE;
113
114 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0) wxOVERRIDE;
115
116 virtual void DrawChoice(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) wxOVERRIDE;
117
118 virtual void DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) wxOVERRIDE;
119
120 virtual void DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) wxOVERRIDE;
121
122 virtual void DrawRadioBitmap(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0) wxOVERRIDE;
123
124 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
125 virtual void DrawTitleBarBitmap(wxWindow *win,
126 wxDC& dc,
127 const wxRect& rect,
128 wxTitleBarButton button,
129 int flags = 0) wxOVERRIDE;
130 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
131
132 virtual void DrawGauge(wxWindow* win,
133 wxDC& dc,
134 const wxRect& rect,
135 int value,
136 int max,
137 int flags = 0) wxOVERRIDE;
138
139 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win) wxOVERRIDE;
140
141 private:
142 void DrawMacThemeButton(wxWindow *win,
143 wxDC& dc,
144 const wxRect& rect,
145 int flags,
146 int kind,
147 int adornment);
148
149 // the tree buttons
150 wxBitmap m_bmpTreeExpanded;
151 wxBitmap m_bmpTreeCollapsed;
152 };
153
154 // ============================================================================
155 // implementation
156 // ============================================================================
157
158 // static
GetDefault()159 wxRendererNative& wxRendererNative::GetDefault()
160 {
161 static wxRendererMac s_rendererMac;
162
163 return s_rendererMac;
164 }
165
DrawHeaderButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,wxHeaderSortIconType sortArrow,wxHeaderButtonParams * params)166 int wxRendererMac::DrawHeaderButton( wxWindow *win,
167 wxDC& dc,
168 const wxRect& rect,
169 int flags,
170 wxHeaderSortIconType sortArrow,
171 wxHeaderButtonParams* params )
172 {
173 if ( wxSystemSettings::GetAppearance().IsDark() )
174 return wxRendererNative::GetGeneric().DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
175
176 const wxCoord x = rect.x;
177 const wxCoord y = rect.y;
178 const wxCoord w = rect.width;
179 const wxCoord h = rect.height;
180
181 dc.SetBrush( *wxTRANSPARENT_BRUSH );
182
183 HIRect headerRect = CGRectMake( x, y, w, h );
184 if ( !wxHasCGContext(win, dc) )
185 {
186 win->RefreshRect(rect);
187 }
188 else
189 {
190 CGContextRef cgContext;
191 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
192
193 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
194
195 {
196 HIThemeButtonDrawInfo drawInfo;
197 HIRect labelRect;
198
199 memset( &drawInfo, 0, sizeof(drawInfo) );
200 drawInfo.version = 0;
201 drawInfo.kind = kThemeListHeaderButton;
202 drawInfo.adornment = kThemeAdornmentNone;
203 drawInfo.value = kThemeButtonOff;
204 if ( flags & wxCONTROL_DISABLED )
205 drawInfo.state = kThemeStateInactive;
206 else if ( flags & wxCONTROL_PRESSED )
207 drawInfo.state = kThemeStatePressed;
208 else
209 drawInfo.state = kThemeStateActive;
210
211 // The down arrow is drawn automatically (if value is kThemeButtonOn)
212 // change it to an up arrow if needed.
213 if ( sortArrow == wxHDR_SORT_ICON_UP )
214 {
215 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
216 drawInfo.value = kThemeButtonOn;
217 }
218 else if (sortArrow == wxHDR_SORT_ICON_DOWN )
219 {
220 drawInfo.value = kThemeButtonOn;
221 }
222
223 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
224 }
225 }
226
227 // Reserve room for the arrows before writing the label, and turn off the
228 // flags we've already handled
229 wxRect newRect(rect);
230 if ( sortArrow != wxHDR_SORT_ICON_NONE )
231 {
232 newRect.width -= 12;
233 sortArrow = wxHDR_SORT_ICON_NONE;
234 }
235 flags &= ~wxCONTROL_PRESSED;
236
237 return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
238 }
239
240
GetHeaderButtonHeight(wxWindow * WXUNUSED (win))241 int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
242 {
243 SInt32 standardHeight;
244 OSStatus errStatus;
245
246 errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
247 if (errStatus == noErr)
248 {
249 return standardHeight;
250 }
251 return -1;
252 }
253
GetHeaderButtonMargin(wxWindow * WXUNUSED (win))254 int wxRendererMac::GetHeaderButtonMargin(wxWindow *WXUNUSED(win))
255 {
256 return 0; // TODO: How to determine the real margin?
257 }
258
DrawTreeItemButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)259 void wxRendererMac::DrawTreeItemButton( wxWindow *win,
260 wxDC& dc,
261 const wxRect& rect,
262 int flags )
263 {
264 // now the wxGCDC is using native transformations
265 const wxCoord x = rect.x;
266 const wxCoord y = rect.y;
267 const wxCoord w = rect.width;
268 const wxCoord h = rect.height;
269
270 dc.SetBrush( *wxTRANSPARENT_BRUSH );
271
272 HIRect headerRect = CGRectMake( x, y, w, h );
273 if ( !wxHasCGContext(win, dc) )
274 {
275 win->RefreshRect(rect);
276 }
277 else
278 {
279 CGContextRef cgContext;
280
281 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
282 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
283
284 HIThemeButtonDrawInfo drawInfo;
285 HIRect labelRect;
286
287 memset( &drawInfo, 0, sizeof(drawInfo) );
288 drawInfo.version = 0;
289 drawInfo.kind = kThemeDisclosureButton;
290 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
291 // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
292 // We need to set the value using the 'old' DrawThemeButton constants instead.
293 drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
294 drawInfo.adornment = kThemeAdornmentNone;
295
296 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
297 }
298 }
299
300 wxSplitterRenderParams
GetSplitterParams(const wxWindow * win)301 wxRendererMac::GetSplitterParams(const wxWindow *win)
302 {
303 // see below
304 SInt32 sashWidth,
305 border;
306 #if wxOSX_USE_COCOA
307 if ( win->HasFlag(wxSP_3DSASH) )
308 GetThemeMetric( kThemeMetricPaneSplitterHeight, &sashWidth ); // Cocoa == Carbon == 7
309 else if ( win->HasFlag(wxSP_NOSASH) ) // actually Cocoa doesn't allow 0
310 sashWidth = 0;
311 else // no 3D effect - Cocoa [NSSplitView dividerThickNess] for NSSplitViewDividerStyleThin
312 sashWidth = 1;
313 #else // Carbon
314 if ( win->HasFlag(wxSP_3DSASH) )
315 GetThemeMetric( kThemeMetricPaneSplitterHeight, &sashWidth );
316 else if ( win->HasFlag(wxSP_NOSASH) )
317 sashWidth = 0;
318 else // no 3D effect
319 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &sashWidth );
320 #endif // Cocoa/Carbon
321
322 if ( win->HasFlag(wxSP_3DBORDER) )
323 border = 2;
324 else // no 3D effect
325 border = 0;
326
327 return wxSplitterRenderParams(sashWidth, border, false);
328 }
329
330
DrawSplitterSash(wxWindow * win,wxDC & dc,const wxSize & size,wxCoord position,wxOrientation orient,int WXUNUSED (flags))331 void wxRendererMac::DrawSplitterSash( wxWindow *win,
332 wxDC& dc,
333 const wxSize& size,
334 wxCoord position,
335 wxOrientation orient,
336 int WXUNUSED(flags) )
337 {
338 // Note that we can't use ternary ?: operator or any other construct with
339 // logical operators here, WX_IS_MACOS_AVAILABLE() must appear inside an
340 // "if" statement to avoid -Wunsupported-availability-guard with Xcode 10.
341 bool hasMetal;
342 if (WX_IS_MACOS_AVAILABLE(10, 14))
343 hasMetal = false;
344 else
345 hasMetal = win->MacGetTopLevelWindow()->GetExtraStyle() & wxFRAME_EX_METAL;
346
347 SInt32 height;
348
349 height = wxRendererNative::Get().GetSplitterParams(win).widthSash;
350
351 // Do not draw over border drawn by wxRendererGeneric::DrawSplitterBorder()
352 const wxCoord borderAdjust = win->HasFlag(wxSP_3DBORDER) ? 2 : 0;
353
354 HIRect splitterRect;
355 if (orient == wxVERTICAL)
356 splitterRect = CGRectMake( position, borderAdjust, height, size.y - 2*borderAdjust );
357 else
358 splitterRect = CGRectMake( borderAdjust, position, size.x - 2*borderAdjust, height );
359
360 // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
361 // strange redraw errors occur if we don't do this
362
363 if ( !wxHasCGContext(win, dc) )
364 {
365 wxRect rect( (int) splitterRect.origin.x, (int) splitterRect.origin.y, (int) splitterRect.size.width,
366 (int) splitterRect.size.height );
367 win->RefreshRect( rect );
368 }
369 else
370 {
371 CGContextRef cgContext;
372 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
373 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
374
375 if ( hasMetal )
376 {
377 HIThemeBackgroundDrawInfo bgdrawInfo;
378 bgdrawInfo.version = 0;
379 bgdrawInfo.state = kThemeStateActive;
380 bgdrawInfo.kind = hasMetal ? kThemeBackgroundMetal : kThemeBackgroundPlacard;
381
382 HIThemeDrawBackground(&splitterRect, &bgdrawInfo, cgContext, kHIThemeOrientationNormal);
383 }
384 else
385 {
386 CGContextSetFillColorWithColor(cgContext,win->GetBackgroundColour().GetCGColor());
387 CGContextFillRect(cgContext,splitterRect);
388 }
389
390 if ( win->HasFlag(wxSP_3DSASH) )
391 {
392 if ( !wxSystemSettings::GetAppearance().IsDark() )
393 {
394 HIThemeSplitterDrawInfo drawInfo;
395 drawInfo.version = 0;
396 drawInfo.state = kThemeStateActive;
397 drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
398 HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
399 }
400 }
401 }
402 }
403
404 void
DrawItemSelectionRect(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)405 wxRendererMac::DrawItemSelectionRect(wxWindow * WXUNUSED(win),
406 wxDC& dc,
407 const wxRect& rect,
408 int flags)
409 {
410 if ( !(flags & wxCONTROL_SELECTED) )
411 return;
412
413 wxColour col( wxMacCreateCGColorFromHITheme( (flags & wxCONTROL_FOCUSED) ?
414 kThemeBrushAlternatePrimaryHighlightColor
415 : kThemeBrushSecondaryHighlightColor ) );
416 wxBrush selBrush( col );
417
418 dc.SetPen( *wxTRANSPARENT_PEN );
419 dc.SetBrush( selBrush );
420 dc.DrawRectangle( rect );
421 }
422
423
424 void
DrawMacThemeButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,int kind,int adornment)425 wxRendererMac::DrawMacThemeButton(wxWindow *win,
426 wxDC& dc,
427 const wxRect& rect,
428 int flags,
429 int kind,
430 int adornment)
431 {
432 // now the wxGCDC is using native transformations
433 const wxCoord x = rect.x;
434 const wxCoord y = rect.y;
435 const wxCoord w = rect.width;
436 const wxCoord h = rect.height;
437
438 dc.SetBrush( *wxTRANSPARENT_BRUSH );
439
440 HIRect headerRect = CGRectMake( x, y, w, h );
441 if ( !wxHasCGContext(win, dc) )
442 {
443 win->RefreshRect(rect);
444 }
445 else
446 {
447 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
448 CGContextRef cgContext;
449 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
450
451 HIThemeButtonDrawInfo drawInfo;
452 HIRect labelRect;
453
454 memset( &drawInfo, 0, sizeof(drawInfo) );
455 drawInfo.version = 0;
456 drawInfo.kind = kind;
457 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
458 drawInfo.value = (flags & wxCONTROL_PRESSED) ? kThemeButtonOn : kThemeButtonOff;
459 if (flags & wxCONTROL_UNDETERMINED)
460 drawInfo.value = kThemeButtonMixed;
461 drawInfo.adornment = adornment;
462 if (flags & wxCONTROL_FOCUSED)
463 drawInfo.adornment |= kThemeAdornmentFocus;
464
465 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
466 }
467 }
468
469 void
DrawCheckBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)470 wxRendererMac::DrawCheckBox(wxWindow *win,
471 wxDC& dc,
472 const wxRect& rect,
473 int flags)
474 {
475 if (flags & wxCONTROL_CHECKED)
476 flags |= wxCONTROL_PRESSED;
477
478 int kind;
479
480 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
481 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
482 kind = kThemeCheckBoxSmall;
483 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
484 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
485 kind = kThemeCheckBoxMini;
486 else
487 kind = kThemeCheckBox;
488
489
490 DrawMacThemeButton(win, dc, rect, flags,
491 kind, kThemeAdornmentNone);
492 }
493
GetCheckBoxSize(wxWindow * win,int WXUNUSED (flags))494 wxSize wxRendererMac::GetCheckBoxSize(wxWindow* win, int WXUNUSED(flags))
495 {
496 // Even though we don't use the window in this implementation, still check
497 // that it's valid to avoid surprises when running the same code under the
498 // other platforms.
499 wxCHECK_MSG( win, wxSize(0, 0), "Must have a valid window" );
500
501 wxSize size;
502 SInt32 width, height;
503 OSStatus errStatus;
504
505 errStatus = GetThemeMetric(kThemeMetricCheckBoxWidth, &width);
506 if (errStatus == noErr)
507 {
508 size.SetWidth(width);
509 }
510
511 errStatus = GetThemeMetric(kThemeMetricCheckBoxHeight, &height);
512 if (errStatus == noErr)
513 {
514 size.SetHeight(height);
515 }
516
517 return size;
518 }
519
520 void
DrawComboBoxDropButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)521 wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
522 wxDC& dc,
523 const wxRect& rect,
524 int flags)
525 {
526 int kind;
527 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
528 kind = kThemeArrowButtonSmall;
529 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
530 kind = kThemeArrowButtonMini;
531 else
532 kind = kThemeArrowButton;
533
534 DrawMacThemeButton(win, dc, rect, flags,
535 kind, kThemeAdornmentArrowDownArrow);
536 }
537
538 void
DrawPushButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)539 wxRendererMac::DrawPushButton(wxWindow *win,
540 wxDC& dc,
541 const wxRect& rect,
542 int flags)
543 {
544 int kind;
545 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
546 kind = kThemeBevelButtonSmall;
547 // There is no kThemeBevelButtonMini, but in this case, use Small
548 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
549 kind = kThemeBevelButtonSmall;
550 else
551 kind = kThemeBevelButton;
552
553 DrawMacThemeButton(win, dc, rect, flags,
554 kind, kThemeAdornmentNone);
555 }
556
DrawCollapseButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)557 void wxRendererMac::DrawCollapseButton(wxWindow *win,
558 wxDC& dc,
559 const wxRect& rect,
560 int flags)
561 {
562 int adornment = (flags & wxCONTROL_EXPANDED)
563 ? kThemeAdornmentArrowUpArrow
564 : kThemeAdornmentArrowDownArrow;
565
566 DrawMacThemeButton(win, dc, rect, flags,
567 kThemeArrowButton, adornment);
568 }
569
GetCollapseButtonSize(wxWindow * WXUNUSED (win),wxDC & WXUNUSED (dc))570 wxSize wxRendererMac::GetCollapseButtonSize(wxWindow *WXUNUSED(win), wxDC& WXUNUSED(dc))
571 {
572 wxSize size;
573 SInt32 width, height;
574 OSStatus errStatus;
575
576 errStatus = GetThemeMetric(kThemeMetricDisclosureButtonWidth, &width);
577 if (errStatus == noErr)
578 {
579 size.SetWidth(width);
580 }
581
582 errStatus = GetThemeMetric(kThemeMetricDisclosureButtonHeight, &height);
583 if (errStatus == noErr)
584 {
585 size.SetHeight(height);
586 }
587
588 // strict metrics size cutoff the button, increase the size
589 size.IncBy(1);
590
591 return size;
592 }
593
594 void
DrawFocusRect(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)595 wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
596 {
597 if (!win)
598 {
599 wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
600 return;
601 }
602
603 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
604
605 HIThemeFrameDrawInfo info ;
606
607 memset( &info, 0 , sizeof(info) ) ;
608
609 info.version = 0 ;
610 info.kind = 0 ;
611 info.state = kThemeStateActive;
612 info.isFocused = true ;
613
614 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
615 wxASSERT( cgContext ) ;
616
617 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
618 }
619
DrawChoice(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)620 void wxRendererMac::DrawChoice(wxWindow* win, wxDC& dc,
621 const wxRect& rect, int flags)
622 {
623 int kind;
624
625 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
626 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
627 kind = kThemePopupButtonSmall;
628 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
629 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
630 kind = kThemePopupButtonMini;
631 else
632 kind = kThemePopupButton;
633
634 DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone);
635 }
636
637
DrawComboBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)638 void wxRendererMac::DrawComboBox(wxWindow* win, wxDC& dc,
639 const wxRect& rect, int flags)
640 {
641 int kind;
642
643 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
644 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
645 kind = kThemeComboBoxSmall;
646 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
647 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
648 kind = kThemeComboBoxMini;
649 else
650 kind = kThemeComboBox;
651
652 DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone);
653 }
654
DrawRadioBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)655 void wxRendererMac::DrawRadioBitmap(wxWindow* win, wxDC& dc,
656 const wxRect& rect, int flags)
657 {
658 int kind;
659
660 if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
661 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
662 kind = kThemeRadioButtonSmall;
663 else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
664 (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
665 kind = kThemeRadioButtonMini;
666 else
667 kind = kThemeRadioButton;
668
669 if (flags & wxCONTROL_CHECKED)
670 flags |= wxCONTROL_PRESSED;
671
672 DrawMacThemeButton(win, dc, rect, flags,
673 kind, kThemeAdornmentNone);
674 }
675
DrawTextCtrl(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)676 void wxRendererMac::DrawTextCtrl(wxWindow* win, wxDC& dc,
677 const wxRect& rect, int flags)
678 {
679 const wxCoord x = rect.x;
680 const wxCoord y = rect.y;
681 const wxCoord w = rect.width;
682 const wxCoord h = rect.height;
683
684 dc.SetBrush( *wxWHITE_BRUSH );
685 dc.SetPen( *wxTRANSPARENT_PEN );
686 dc.DrawRectangle(rect);
687
688 dc.SetBrush( *wxTRANSPARENT_BRUSH );
689
690 HIRect hiRect = CGRectMake( x, y, w, h );
691 if ( !wxHasCGContext(win, dc) )
692 {
693 win->RefreshRect(rect);
694 }
695 else
696 {
697 CGContextRef cgContext;
698
699 cgContext = (CGContextRef) static_cast<wxGCDCImpl*>(dc.GetImpl())->GetGraphicsContext()->GetNativeContext();
700
701 {
702 HIThemeFrameDrawInfo drawInfo;
703
704 memset( &drawInfo, 0, sizeof(drawInfo) );
705 drawInfo.version = 0;
706 drawInfo.kind = kHIThemeFrameTextFieldSquare;
707 drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
708 if (flags & wxCONTROL_FOCUSED)
709 drawInfo.isFocused = true;
710
711 HIThemeDrawFrame( &hiRect, &drawInfo, cgContext, kHIThemeOrientationNormal);
712 }
713 }
714 }
715
716 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
717
DrawTitleBarBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,wxTitleBarButton button,int flags)718 void wxRendererMac::DrawTitleBarBitmap(wxWindow *win,
719 wxDC& dc,
720 const wxRect& rect,
721 wxTitleBarButton button,
722 int flags)
723 {
724 // currently we only support the close bitmap here
725 if ( button != wxTITLEBAR_BUTTON_CLOSE )
726 {
727 m_rendererNative.DrawTitleBarBitmap(win, dc, rect, button, flags);
728 return;
729 }
730
731 wxColour glyphColor;
732
733 // The following hard coded RGB values are based the close button in
734 // XCode 6+ welcome screen
735 bool drawCircle;
736 if ( flags & wxCONTROL_PRESSED )
737 {
738 drawCircle = true;
739 glyphColor = wxColour(104, 104, 104);
740 dc.SetPen(wxPen(wxColour(70, 70, 71), 1));
741 dc.SetBrush(wxColour(78, 78, 78));
742 }
743 else if ( flags & wxCONTROL_CURRENT )
744 {
745 drawCircle = true;
746 glyphColor = *wxWHITE;
747 dc.SetPen(wxPen(wxColour(163, 165, 166), 1));
748 dc.SetBrush(wxColour(182, 184, 187));
749 }
750 else
751 {
752 drawCircle = false;
753 glyphColor = wxColour(145, 147, 149);
754 }
755
756 if ( drawCircle )
757 {
758 wxRect circleRect(rect);
759 circleRect.Deflate(2);
760
761 dc.DrawEllipse(circleRect);
762 }
763
764 dc.SetPen(wxPen(glyphColor, 1));
765
766 wxRect centerRect(rect);
767 centerRect.Deflate(5);
768 centerRect.height++;
769 centerRect.width++;
770
771 dc.DrawLine(centerRect.GetTopLeft(), centerRect.GetBottomRight());
772 dc.DrawLine(centerRect.GetTopRight(), centerRect.GetBottomLeft());
773 }
774
775 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
776
DrawGauge(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int value,int max,int WXUNUSED (flags))777 void wxRendererMac::DrawGauge(wxWindow* WXUNUSED(win),
778 wxDC& dc,
779 const wxRect& rect,
780 int value,
781 int max,
782 int WXUNUSED(flags))
783 {
784 const wxCoord x = rect.x;
785 const wxCoord y = rect.y;
786 const wxCoord w = rect.width;
787 const wxCoord h = rect.height;
788
789 HIThemeTrackDrawInfo tdi;
790 tdi.version = 0;
791 tdi.min = 0;
792 tdi.value = value;
793 tdi.max = max;
794 tdi.bounds = CGRectMake(x, y, w, h);
795 tdi.attributes = kThemeTrackHorizontal;
796 tdi.enableState = kThemeTrackActive;
797 tdi.kind = kThemeLargeProgressBar;
798
799 int milliSecondsPerStep = 1000 / 60;
800 wxLongLongNative localTime = wxGetLocalTimeMillis();
801 tdi.trackInfo.progress.phase = localTime.GetValue() / milliSecondsPerStep % 32;
802
803 CGContextRef cgContext;
804 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
805
806 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
807
808 HIThemeDrawTrack(&tdi, NULL, cgContext, kHIThemeOrientationNormal);
809 }
810
811 #endif
812