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@wxwindows.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 #ifdef __BORLANDC__
17     #pragma hdrstop
18 #endif
19 
20 #ifndef WX_PRECOMP
21     #include "wx/string.h"
22     #include "wx/dc.h"
23     #include "wx/bitmap.h"
24     #include "wx/settings.h"
25     #include "wx/dcclient.h"
26     #include "wx/dcmemory.h"
27     #include "wx/toplevel.h"
28 #endif
29 
30 #include "wx/renderer.h"
31 #include "wx/graphics.h"
32 #include "wx/dcgraph.h"
33 #include "wx/splitter.h"
34 #include "wx/osx/private.h"
35 
36 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
37     #include "wx/image.h"
38     #include "wx/mstream.h"
39 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
40 
41 
42 // check if we're having a CGContext we can draw into
wxHasCGContext(wxWindow * WXUNUSED (win),wxDC & dc)43 inline bool wxHasCGContext(wxWindow* WXUNUSED(win), wxDC& dc)
44 {
45     wxGCDCImpl* gcdc = wxDynamicCast( dc.GetImpl() , wxGCDCImpl);
46 
47     if ( gcdc )
48     {
49         if ( gcdc->GetGraphicsContext()->GetNativeContext() )
50             return true;
51     }
52     return false;
53 }
54 
55 
56 
57 class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
58 {
59 public:
60     // draw the header control button (used by wxListCtrl)
61     virtual int DrawHeaderButton( wxWindow *win,
62         wxDC& dc,
63         const wxRect& rect,
64         int flags = 0,
65         wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
66         wxHeaderButtonParams* params = NULL );
67 
68     virtual int GetHeaderButtonHeight(wxWindow *win);
69 
70     virtual int GetHeaderButtonMargin(wxWindow *win);
71 
72     // draw the expanded/collapsed icon for a tree control item
73     virtual void DrawTreeItemButton( wxWindow *win,
74         wxDC& dc,
75         const wxRect& rect,
76         int flags = 0 );
77 
78     // draw a (vertical) sash
79     virtual void DrawSplitterSash( wxWindow *win,
80         wxDC& dc,
81         const wxSize& size,
82         wxCoord position,
83         wxOrientation orient,
84         int flags = 0 );
85 
86     virtual void DrawCheckBox(wxWindow *win,
87                               wxDC& dc,
88                               const wxRect& rect,
89                               int flags = 0);
90 
91     virtual wxSize GetCheckBoxSize(wxWindow* win);
92 
93     virtual void DrawComboBoxDropButton(wxWindow *win,
94                                         wxDC& dc,
95                                         const wxRect& rect,
96                                         int flags = 0);
97 
98     virtual void DrawPushButton(wxWindow *win,
99                                 wxDC& dc,
100                                 const wxRect& rect,
101                                 int flags = 0);
102 
103     virtual void DrawItemSelectionRect(wxWindow *win,
104                                        wxDC& dc,
105                                        const wxRect& rect,
106                                        int flags = 0);
107 
108     virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
109 
110     virtual void DrawChoice(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0);
111 
112     virtual void DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0);
113 
114     virtual void DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0);
115 
116     virtual void DrawRadioBitmap(wxWindow* win, wxDC& dc, const wxRect& rect, int flags=0);
117 
118 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
119     virtual void DrawTitleBarBitmap(wxWindow *win,
120                                     wxDC& dc,
121                                     const wxRect& rect,
122                                     wxTitleBarButton button,
123                                     int flags = 0);
124 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
125 
126     virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
127 
128 private:
129     void DrawMacThemeButton(wxWindow *win,
130                             wxDC& dc,
131                             const wxRect& rect,
132                             int flags,
133                             int kind,
134                             int adornment);
135 
136     // the tree buttons
137     wxBitmap m_bmpTreeExpanded;
138     wxBitmap m_bmpTreeCollapsed;
139 };
140 
141 // ============================================================================
142 // implementation
143 // ============================================================================
144 
145 // static
GetDefault()146 wxRendererNative& wxRendererNative::GetDefault()
147 {
148     static wxRendererMac s_rendererMac;
149 
150     return s_rendererMac;
151 }
152 
DrawHeaderButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,wxHeaderSortIconType sortArrow,wxHeaderButtonParams * params)153 int wxRendererMac::DrawHeaderButton( wxWindow *win,
154     wxDC& dc,
155     const wxRect& rect,
156     int flags,
157     wxHeaderSortIconType sortArrow,
158     wxHeaderButtonParams* params )
159 {
160     const wxCoord x = rect.x;
161     const wxCoord y = rect.y;
162     const wxCoord w = rect.width;
163     const wxCoord h = rect.height;
164 
165     dc.SetBrush( *wxTRANSPARENT_BRUSH );
166 
167     HIRect headerRect = CGRectMake( x, y, w, h );
168     if ( !wxHasCGContext(win, dc) )
169     {
170         win->Refresh( &rect );
171     }
172     else
173     {
174         CGContextRef cgContext;
175         wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
176 
177         cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
178 
179         {
180             HIThemeButtonDrawInfo drawInfo;
181             HIRect labelRect;
182 
183             memset( &drawInfo, 0, sizeof(drawInfo) );
184             drawInfo.version = 0;
185             drawInfo.kind = kThemeListHeaderButton;
186             drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
187             drawInfo.value = (flags & wxCONTROL_PRESSED) ? kThemeButtonOn : kThemeButtonOff;
188             drawInfo.adornment = kThemeAdornmentNone;
189 
190             // The down arrow is drawn automatically, change it to an up arrow if needed.
191             if ( sortArrow == wxHDR_SORT_ICON_UP )
192                 drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
193 
194             HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
195 
196             // If we don't want any arrows we need to draw over the one already there
197             if ( (flags & wxCONTROL_PRESSED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
198             {
199                 // clip to the header rectangle
200                 CGContextSaveGState( cgContext );
201                 CGContextClipToRect( cgContext, headerRect );
202                 // but draw bigger than that so the arrow will get clipped off
203                 headerRect.size.width += 25;
204                 HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
205                 CGContextRestoreGState( cgContext );
206             }
207         }
208     }
209 
210     // Reserve room for the arrows before writing the label, and turn off the
211     // flags we've already handled
212     wxRect newRect(rect);
213     if ( (flags & wxCONTROL_PRESSED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
214     {
215         newRect.width -= 12;
216         sortArrow = wxHDR_SORT_ICON_NONE;
217     }
218     flags &= ~wxCONTROL_PRESSED;
219 
220     return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
221 }
222 
223 
GetHeaderButtonHeight(wxWindow * WXUNUSED (win))224 int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
225 {
226     SInt32      standardHeight;
227     OSStatus        errStatus;
228 
229     errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
230     if (errStatus == noErr)
231     {
232         return standardHeight;
233     }
234     return -1;
235 }
236 
GetHeaderButtonMargin(wxWindow * WXUNUSED (win))237 int wxRendererMac::GetHeaderButtonMargin(wxWindow *WXUNUSED(win))
238 {
239     wxFAIL_MSG( "GetHeaderButtonMargin() not implemented" );
240     return -1;
241 }
242 
DrawTreeItemButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)243 void wxRendererMac::DrawTreeItemButton( wxWindow *win,
244     wxDC& dc,
245     const wxRect& rect,
246     int flags )
247 {
248     // now the wxGCDC is using native transformations
249     const wxCoord x = rect.x;
250     const wxCoord y = rect.y;
251     const wxCoord w = rect.width;
252     const wxCoord h = rect.height;
253 
254     dc.SetBrush( *wxTRANSPARENT_BRUSH );
255 
256     HIRect headerRect = CGRectMake( x, y, w, h );
257     if ( !wxHasCGContext(win, dc) )
258     {
259         win->Refresh( &rect );
260     }
261     else
262     {
263         CGContextRef cgContext;
264 
265         wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
266         cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
267 
268         HIThemeButtonDrawInfo drawInfo;
269         HIRect labelRect;
270 
271         memset( &drawInfo, 0, sizeof(drawInfo) );
272         drawInfo.version = 0;
273         drawInfo.kind = kThemeDisclosureButton;
274         drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
275         // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
276         // We need to set the value using the 'old' DrawThemeButton constants instead.
277         drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
278         drawInfo.adornment = kThemeAdornmentNone;
279 
280         HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
281     }
282 }
283 
284 wxSplitterRenderParams
GetSplitterParams(const wxWindow * win)285 wxRendererMac::GetSplitterParams(const wxWindow *win)
286 {
287     // see below
288     SInt32 sashWidth,
289             border;
290 #if wxOSX_USE_COCOA
291     if ( win->HasFlag(wxSP_3DSASH) )
292         GetThemeMetric( kThemeMetricPaneSplitterHeight, &sashWidth ); // Cocoa == Carbon == 7
293     else if ( win->HasFlag(wxSP_NOSASH) ) // actually Cocoa doesn't allow 0
294         sashWidth = 0;
295     else // no 3D effect - Cocoa [NSSplitView dividerThickNess] for NSSplitViewDividerStyleThin
296         sashWidth = 1;
297 #else // Carbon
298     if ( win->HasFlag(wxSP_3DSASH) )
299         GetThemeMetric( kThemeMetricPaneSplitterHeight, &sashWidth );
300     else if ( win->HasFlag(wxSP_NOSASH) )
301         sashWidth = 0;
302     else // no 3D effect
303         GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &sashWidth );
304 #endif // Cocoa/Carbon
305 
306     if ( win->HasFlag(wxSP_3DBORDER) )
307         border = 2;
308     else // no 3D effect
309         border = 0;
310 
311     return wxSplitterRenderParams(sashWidth, border, false);
312 }
313 
314 
DrawSplitterSash(wxWindow * win,wxDC & dc,const wxSize & size,wxCoord position,wxOrientation orient,int WXUNUSED (flags))315 void wxRendererMac::DrawSplitterSash( wxWindow *win,
316     wxDC& dc,
317     const wxSize& size,
318     wxCoord position,
319     wxOrientation orient,
320     int WXUNUSED(flags) )
321 {
322     bool hasMetal = win->MacGetTopLevelWindow()->GetExtraStyle() & wxFRAME_EX_METAL;
323     SInt32 height;
324 
325     height = wxRendererNative::Get().GetSplitterParams(win).widthSash;
326 
327     HIRect splitterRect;
328     if (orient == wxVERTICAL)
329         splitterRect = CGRectMake( position, 0, height, size.y );
330     else
331         splitterRect = CGRectMake( 0, position, size.x, height );
332 
333     // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
334     // strange redraw errors occur if we don't do this
335 
336     if ( !wxHasCGContext(win, dc) )
337     {
338         wxRect rect( (int) splitterRect.origin.x, (int) splitterRect.origin.y, (int) splitterRect.size.width,
339                      (int) splitterRect.size.height );
340         win->RefreshRect( rect );
341     }
342     else
343     {
344         CGContextRef cgContext;
345         wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
346         cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
347 
348         HIThemeBackgroundDrawInfo bgdrawInfo;
349         bgdrawInfo.version = 0;
350         bgdrawInfo.state = kThemeStateActive;
351         bgdrawInfo.kind = hasMetal ? kThemeBackgroundMetal : kThemeBackgroundPlacard;
352 
353         if ( hasMetal )
354             HIThemeDrawBackground(&splitterRect, &bgdrawInfo, cgContext, kHIThemeOrientationNormal);
355         else
356         {
357             CGContextSetFillColorWithColor(cgContext,win->GetBackgroundColour().GetCGColor());
358             CGContextFillRect(cgContext,splitterRect);
359         }
360 
361         if ( win->HasFlag(wxSP_3DSASH) )
362         {
363             HIThemeSplitterDrawInfo drawInfo;
364             drawInfo.version = 0;
365             drawInfo.state = kThemeStateActive;
366             drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
367             HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
368         }
369     }
370 }
371 
372 void
DrawItemSelectionRect(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)373 wxRendererMac::DrawItemSelectionRect(wxWindow * WXUNUSED(win),
374                                      wxDC& dc,
375                                      const wxRect& rect,
376                                      int flags)
377 {
378     if ( !(flags & wxCONTROL_SELECTED) )
379         return;
380 
381     wxColour col( wxMacCreateCGColorFromHITheme( (flags & wxCONTROL_FOCUSED) ?
382                                                  kThemeBrushAlternatePrimaryHighlightColor
383                                                                              : kThemeBrushSecondaryHighlightColor ) );
384     wxBrush selBrush( col );
385 
386     dc.SetPen( *wxTRANSPARENT_PEN );
387     dc.SetBrush( selBrush );
388     dc.DrawRectangle( rect );
389 }
390 
391 
392 void
DrawMacThemeButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,int kind,int adornment)393 wxRendererMac::DrawMacThemeButton(wxWindow *win,
394                                   wxDC& dc,
395                                   const wxRect& rect,
396                                   int flags,
397                                   int kind,
398                                   int adornment)
399 {
400     // now the wxGCDC is using native transformations
401     const wxCoord x = rect.x;
402     const wxCoord y = rect.y;
403     const wxCoord w = rect.width;
404     const wxCoord h = rect.height;
405 
406     dc.SetBrush( *wxTRANSPARENT_BRUSH );
407 
408     HIRect headerRect = CGRectMake( x, y, w, h );
409     if ( !wxHasCGContext(win, dc) )
410     {
411         win->Refresh( &rect );
412     }
413     else
414     {
415         wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
416         CGContextRef cgContext;
417         cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext();
418 
419         HIThemeButtonDrawInfo drawInfo;
420         HIRect labelRect;
421 
422         memset( &drawInfo, 0, sizeof(drawInfo) );
423         drawInfo.version = 0;
424         drawInfo.kind = kind;
425         drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
426         drawInfo.value = (flags & wxCONTROL_PRESSED) ? kThemeButtonOn : kThemeButtonOff;
427         if (flags & wxCONTROL_UNDETERMINED)
428             drawInfo.value = kThemeButtonMixed;
429         drawInfo.adornment = adornment;
430         if (flags & wxCONTROL_FOCUSED)
431             drawInfo.adornment |= kThemeAdornmentFocus;
432 
433         HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
434     }
435 }
436 
437 void
DrawCheckBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)438 wxRendererMac::DrawCheckBox(wxWindow *win,
439                             wxDC& dc,
440                             const wxRect& rect,
441                             int flags)
442 {
443     if (flags & wxCONTROL_CHECKED)
444         flags |= wxCONTROL_PRESSED;
445 
446     int kind;
447 
448     if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
449         (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
450         kind = kThemeCheckBoxSmall;
451     else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
452              (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
453         kind = kThemeCheckBoxMini;
454     else
455         kind = kThemeCheckBox;
456 
457 
458     DrawMacThemeButton(win, dc, rect, flags,
459                        kind, kThemeAdornmentNone);
460 }
461 
GetCheckBoxSize(wxWindow * WXUNUSED (win))462 wxSize wxRendererMac::GetCheckBoxSize(wxWindow* WXUNUSED(win))
463 {
464     wxSize size;
465     SInt32 width, height;
466     OSStatus errStatus;
467 
468     errStatus = GetThemeMetric(kThemeMetricCheckBoxWidth, &width);
469     if (errStatus == noErr)
470     {
471         size.SetWidth(width);
472     }
473 
474     errStatus = GetThemeMetric(kThemeMetricCheckBoxHeight, &height);
475     if (errStatus == noErr)
476     {
477         size.SetHeight(height);
478     }
479 
480     return size;
481 }
482 
483 void
DrawComboBoxDropButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)484 wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
485                               wxDC& dc,
486                               const wxRect& rect,
487                               int flags)
488 {
489     int kind;
490     if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
491         kind = kThemeArrowButtonSmall;
492     else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
493         kind = kThemeArrowButtonMini;
494     else
495         kind = kThemeArrowButton;
496 
497     DrawMacThemeButton(win, dc, rect, flags,
498                        kind, kThemeAdornmentArrowDownArrow);
499 }
500 
501 void
DrawPushButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)502 wxRendererMac::DrawPushButton(wxWindow *win,
503                               wxDC& dc,
504                               const wxRect& rect,
505                               int flags)
506 {
507     int kind;
508     if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
509         kind = kThemeBevelButtonSmall;
510     // There is no kThemeBevelButtonMini, but in this case, use Small
511     else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
512         kind = kThemeBevelButtonSmall;
513     else
514         kind = kThemeBevelButton;
515 
516     DrawMacThemeButton(win, dc, rect, flags,
517                        kind, kThemeAdornmentNone);
518 }
519 
520 void
DrawFocusRect(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)521 wxRendererMac::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
522 {
523     if (!win)
524     {
525         wxDelegateRendererNative::DrawFocusRect(win, dc, rect, flags);
526         return;
527     }
528 
529     CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
530 
531     HIThemeFrameDrawInfo info ;
532 
533     memset( &info, 0 , sizeof(info) ) ;
534 
535     info.version = 0 ;
536     info.kind = 0 ;
537     info.state = kThemeStateActive;
538     info.isFocused = true ;
539 
540     CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
541     wxASSERT( cgContext ) ;
542 
543     HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
544 }
545 
DrawChoice(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)546 void wxRendererMac::DrawChoice(wxWindow* win, wxDC& dc,
547                            const wxRect& rect, int flags)
548 {
549     int kind;
550 
551     if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
552         (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
553         kind = kThemePopupButtonSmall;
554     else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
555              (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
556         kind = kThemePopupButtonMini;
557     else
558         kind = kThemePopupButton;
559 
560     DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone);
561 }
562 
563 
DrawComboBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)564 void wxRendererMac::DrawComboBox(wxWindow* win, wxDC& dc,
565                              const wxRect& rect, int flags)
566 {
567     int kind;
568 
569     if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
570         (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
571         kind = kThemeComboBoxSmall;
572     else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
573              (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
574         kind = kThemeComboBoxMini;
575     else
576         kind = kThemeComboBox;
577 
578     DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone);
579 }
580 
DrawRadioBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)581 void wxRendererMac::DrawRadioBitmap(wxWindow* win, wxDC& dc,
582                                 const wxRect& rect, int flags)
583 {
584     int kind;
585 
586     if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
587         (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
588         kind = kThemeRadioButtonSmall;
589     else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
590              (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
591         kind = kThemeRadioButtonMini;
592     else
593         kind = kThemeRadioButton;
594 
595     if (flags & wxCONTROL_CHECKED)
596         flags |= wxCONTROL_PRESSED;
597 
598     DrawMacThemeButton(win, dc, rect, flags,
599                           kind, kThemeAdornmentNone);
600 }
601 
DrawTextCtrl(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)602 void wxRendererMac::DrawTextCtrl(wxWindow* win, wxDC& dc,
603                              const wxRect& rect, int flags)
604 {
605     const wxCoord x = rect.x;
606     const wxCoord y = rect.y;
607     const wxCoord w = rect.width;
608     const wxCoord h = rect.height;
609 
610     dc.SetBrush( *wxWHITE_BRUSH );
611     dc.SetPen( *wxTRANSPARENT_PEN );
612     dc.DrawRectangle(rect);
613 
614     dc.SetBrush( *wxTRANSPARENT_BRUSH );
615 
616     HIRect hiRect = CGRectMake( x, y, w, h );
617     if ( !wxHasCGContext(win, dc) )
618     {
619         win->Refresh( &rect );
620     }
621     else
622     {
623         CGContextRef cgContext;
624 
625         cgContext = (CGContextRef) static_cast<wxGCDCImpl*>(dc.GetImpl())->GetGraphicsContext()->GetNativeContext();
626 
627         {
628             HIThemeFrameDrawInfo drawInfo;
629 
630             memset( &drawInfo, 0, sizeof(drawInfo) );
631             drawInfo.version = 0;
632             drawInfo.kind = kHIThemeFrameTextFieldSquare;
633             drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
634             if (flags & wxCONTROL_FOCUSED)
635                 drawInfo.isFocused = true;
636 
637             HIThemeDrawFrame( &hiRect, &drawInfo, cgContext, kHIThemeOrientationNormal);
638         }
639     }
640 }
641 
642 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
643 
DrawTitleBarBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,wxTitleBarButton button,int flags)644 void wxRendererMac::DrawTitleBarBitmap(wxWindow *win,
645                                        wxDC& dc,
646                                        const wxRect& rect,
647                                        wxTitleBarButton button,
648                                        int flags)
649 {
650     // the files below were converted from the originals in art/osx/close*.png
651     // using misc/scripts/png2c.py script -- we must use PNG and not XPM for
652     // them because they use transparency and don't look right without it
653 
654     /* close.png - 400 bytes */
655     static const unsigned char close_png[] = {
656       0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
657       0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
658       0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e,
659       0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x48, 0x2d,
660       0xd1, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47,
661       0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0,
662       0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70,
663       0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00,
664       0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc,
665       0x00, 0x00, 0x00, 0x09, 0x76, 0x70, 0x41, 0x67,
666       0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e,
667       0x00, 0xb1, 0x5b, 0xf1, 0xf7, 0x00, 0x00, 0x00,
668       0xef, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0xa5,
669       0xd2, 0x31, 0x4a, 0x03, 0x41, 0x18, 0xc5, 0xf1,
670       0xdf, 0xc6, 0x55, 0x02, 0xb2, 0x18, 0xb0, 0x33,
671       0x8d, 0xd8, 0x6e, 0x8a, 0x14, 0xa6, 0xb2, 0xc9,
672       0x21, 0x72, 0x0b, 0xdb, 0x5c, 0x45, 0x98, 0x3b,
673       0x24, 0xc7, 0x99, 0x6d, 0x2d, 0x04, 0xd3, 0x09,
674       0x42, 0x48, 0x65, 0x60, 0x6c, 0x76, 0x65, 0x1c,
675       0x14, 0x45, 0x5f, 0x35, 0xfc, 0xe7, 0x3d, 0xe6,
676       0x9b, 0x8f, 0x57, 0xf9, 0xac, 0x06, 0x97, 0x98,
677       0xe0, 0xbc, 0x67, 0x07, 0xbc, 0xe2, 0x05, 0xfb,
678       0xc1, 0x58, 0x65, 0xa1, 0x2b, 0x4c, 0xb3, 0x40,
679       0xa9, 0x03, 0x9e, 0xb1, 0x83, 0x93, 0x2c, 0x74,
680       0x83, 0xb1, 0xef, 0x75, 0x86, 0x0b, 0x1c, 0xb1,
681       0x1f, 0xf5, 0xe3, 0x4d, 0x51, 0x43, 0x08, 0xe1,
682       0xb6, 0x4c, 0x64, 0xac, 0xee, 0xbd, 0x0d, 0x5c,
683       0x63, 0x89, 0x65, 0x08, 0x61, 0x9d, 0x52, 0x4a,
684       0x31, 0xc6, 0xcd, 0xc0, 0x62, 0x8c, 0x9b, 0x94,
685       0x52, 0x0a, 0x21, 0xac, 0x07, 0xd6, 0x67, 0xcc,
686       0x33, 0xf0, 0x61, 0x8c, 0x31, 0x6e, 0xf2, 0x73,
687       0xee, 0xc1, 0xbc, 0xc2, 0x1d, 0x4e, 0xf3, 0xd1,
688       0x62, 0x8c, 0xf7, 0x6d, 0xdb, 0xae, 0xa0, 0xeb,
689       0xba, 0xed, 0x6c, 0x36, 0x7b, 0x28, 0xa6, 0x7f,
690       0x1b, 0xf9, 0xa3, 0xea, 0x7e, 0xcd, 0x93, 0xf2,
691       0xb5, 0xae, 0xeb, 0xb6, 0xd0, 0xb6, 0xed, 0x2a,
692       0xc6, 0xa8, 0x78, 0xf5, 0xf0, 0xaf, 0xe5, 0x34,
693       0x58, 0xe4, 0xe1, 0x62, 0x11, 0x25, 0x5b, 0xa0,
694       0x19, 0x9a, 0x33, 0x14, 0xa0, 0xfe, 0xe1, 0x6b,
695       0x47, 0x3c, 0x62, 0x37, 0x34, 0x67, 0xdf, 0xc3,
696       0x71, 0xdf, 0x90, 0xaf, 0x74, 0xc0, 0x93, 0xbe,
697       0x72, 0x55, 0x71, 0xf9, 0xeb, 0x92, 0xbf, 0x03,
698       0x70, 0x33, 0x76, 0x58, 0xe5, 0x41, 0xfb, 0x6d,
699       0x00, 0x00, 0x00, 0x20, 0x7a, 0x54, 0x58, 0x74,
700       0x74, 0x69, 0x66, 0x66, 0x3a, 0x72, 0x6f, 0x77,
701       0x73, 0x2d, 0x70, 0x65, 0x72, 0x2d, 0x73, 0x74,
702       0x72, 0x69, 0x70, 0x00, 0x00, 0x78, 0xda, 0x33,
703       0xb5, 0x30, 0x05, 0x00, 0x01, 0x47, 0x00, 0xa3,
704       0x38, 0xda, 0x77, 0x3b, 0x00, 0x00, 0x00, 0x00,
705       0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
706     };
707 
708     /* close_current.png - 421 bytes */
709     static const unsigned char close_current_png[] = {
710       0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
711       0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
712       0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e,
713       0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x48, 0x2d,
714       0xd1, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47,
715       0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0,
716       0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70,
717       0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00,
718       0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc,
719       0x00, 0x00, 0x00, 0x09, 0x76, 0x70, 0x41, 0x67,
720       0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e,
721       0x00, 0xb1, 0x5b, 0xf1, 0xf7, 0x00, 0x00, 0x01,
722       0x04, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x9d,
723       0xd2, 0xbd, 0x4a, 0x43, 0x31, 0x00, 0xc5, 0xf1,
724       0xdf, 0x8d, 0x56, 0x44, 0x04, 0x45, 0xd0, 0xc5,
725       0x55, 0xdc, 0x0a, 0x8e, 0xed, 0xec, 0xe4, 0xec,
726       0x24, 0xd4, 0x67, 0x29, 0x59, 0xfa, 0x16, 0x9d,
727       0x7c, 0x07, 0x1d, 0x5c, 0xba, 0xa5, 0xa3, 0x28,
728       0x22, 0x94, 0xae, 0x2e, 0x1d, 0x4a, 0x5d, 0x55,
729       0xb8, 0x2e, 0x09, 0x5c, 0x4b, 0xfd, 0xa0, 0x67,
730       0x0a, 0x27, 0x39, 0xc9, 0x49, 0xf2, 0xaf, 0x7c,
731       0xd7, 0x01, 0x8e, 0x71, 0x84, 0xfd, 0xec, 0x2d,
732       0x30, 0xc3, 0x2b, 0xe6, 0x65, 0x61, 0xd5, 0x08,
733       0x9d, 0xe0, 0x14, 0x7b, 0x56, 0xeb, 0x0d, 0x13,
734       0x4c, 0x61, 0xa3, 0x11, 0x3a, 0xc3, 0x8e, 0x9f,
735       0xb5, 0x9d, 0x9b, 0xbc, 0x63, 0x1e, 0x72, 0xbd,
736       0x53, 0xb4, 0x20, 0xc6, 0xd8, 0x5e, 0x4e, 0x34,
737       0xbc, 0x56, 0x5e, 0x7b, 0x00, 0x6d, 0x5c, 0xe1,
738       0x2a, 0xc6, 0x38, 0xa8, 0xeb, 0xba, 0x4e, 0x29,
739       0xdd, 0x16, 0x2f, 0xa5, 0x74, 0x5b, 0xd7, 0x75,
740       0x1d, 0x63, 0x1c, 0x14, 0x0f, 0xed, 0x0a, 0xe7,
741       0xb9, 0x02, 0x48, 0x29, 0x5d, 0x77, 0x3a, 0x9d,
742       0x8b, 0xf1, 0x78, 0x7c, 0x07, 0x65, 0xdc, 0xed,
743       0x76, 0x6f, 0x1a, 0x25, 0x66, 0x15, 0x2e, 0xb1,
744       0xd5, 0xac, 0x56, 0xc2, 0xb0, 0x22, 0x04, 0xef,
745       0xc1, 0x9a, 0xda, 0xcc, 0xff, 0xf4, 0x6b, 0xd5,
746       0x94, 0x92, 0xa5, 0x53, 0x17, 0x6b, 0x3f, 0xce,
747       0x06, 0x3e, 0x71, 0x88, 0xed, 0xd1, 0x68, 0x34,
748       0x0b, 0x21, 0x4c, 0x7a, 0xbd, 0xde, 0x7d, 0xd9,
749       0x7a, 0x38, 0x1c, 0x3e, 0x86, 0x10, 0x26, 0xfd,
750       0x7e, 0xff, 0xa9, 0x01, 0xc2, 0x4b, 0x21, 0xa7,
751       0x00, 0xd0, 0xfa, 0xe3, 0x6a, 0x1f, 0x78, 0xc0,
752       0xb4, 0x90, 0x33, 0xcf, 0x44, 0xec, 0x66, 0x42,
753       0x56, 0xe9, 0x0d, 0xcf, 0x32, 0x72, 0xd5, 0xd2,
754       0xe4, 0xbf, 0x21, 0xff, 0x02, 0x4d, 0xb5, 0x74,
755       0x79, 0x60, 0x9f, 0x78, 0x78, 0x00, 0x00, 0x00,
756       0x20, 0x7a, 0x54, 0x58, 0x74, 0x74, 0x69, 0x66,
757       0x66, 0x3a, 0x72, 0x6f, 0x77, 0x73, 0x2d, 0x70,
758       0x65, 0x72, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x70,
759       0x00, 0x00, 0x78, 0xda, 0x33, 0xb5, 0x30, 0x05,
760       0x00, 0x01, 0x47, 0x00, 0xa3, 0x38, 0xda, 0x77,
761       0x3b, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
762       0x44, 0xae, 0x42, 0x60, 0x82};
763 
764     /* close_pressed.png - 458 bytes */
765     static const unsigned char close_pressed_png[] = {
766       0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
767       0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
768       0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e,
769       0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x48, 0x2d,
770       0xd1, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47,
771       0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0,
772       0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70,
773       0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00,
774       0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc,
775       0x00, 0x00, 0x00, 0x09, 0x76, 0x70, 0x41, 0x67,
776       0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e,
777       0x00, 0xb1, 0x5b, 0xf1, 0xf7, 0x00, 0x00, 0x01,
778       0x29, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x9d,
779       0x92, 0x31, 0x6a, 0xc3, 0x40, 0x14, 0x44, 0x9f,
780       0x2c, 0xe1, 0xc2, 0x10, 0x08, 0xc4, 0xe0, 0x22,
781       0x76, 0x21, 0x04, 0x29, 0x13, 0xf0, 0x05, 0x54,
782       0xa5, 0x8a, 0x0f, 0xb2, 0x8d, 0x0e, 0xa0, 0x23,
783       0xa8, 0x56, 0xa3, 0x03, 0xe8, 0x08, 0xba, 0x80,
784       0xba, 0xb0, 0x45, 0x0a, 0x97, 0x02, 0x23, 0x58,
785       0x83, 0x40, 0x60, 0x61, 0x08, 0x11, 0x04, 0x57,
786       0x69, 0xf6, 0xc3, 0x46, 0x38, 0x24, 0x64, 0xca,
787       0xd9, 0x19, 0xe6, 0xff, 0xfd, 0xe3, 0xf1, 0x1d,
788       0x2b, 0x20, 0x02, 0x36, 0xc0, 0xd2, 0x72, 0x27,
789       0xe0, 0x08, 0x1c, 0x80, 0x5e, 0x84, 0x9e, 0x63,
790       0x7a, 0x04, 0xb6, 0xc0, 0x1d, 0xd7, 0x31, 0x00,
791       0x6f, 0xc0, 0x1e, 0xc0, 0x77, 0x4c, 0x31, 0x70,
792       0xc3, 0xcf, 0x58, 0xd8, 0x49, 0x3e, 0x81, 0x7e,
793       0x66, 0xc7, 0xdb, 0x02, 0x73, 0x80, 0xdd, 0x6e,
794       0xb7, 0x9a, 0x3a, 0x1c, 0x6e, 0x6e, 0xb5, 0x2b,
795       0x1f, 0x78, 0x02, 0x1e, 0x44, 0x90, 0x65, 0xd9,
796       0x8b, 0xef, 0xfb, 0xef, 0x5a, 0xeb, 0x33, 0x40,
797       0x92, 0x24, 0x51, 0x9a, 0xa6, 0xcf, 0xc6, 0x98,
798       0xae, 0x69, 0x9a, 0xd1, 0x26, 0x8f, 0x81, 0x8d,
799       0x07, 0xa0, 0xaa, 0xaa, 0x3e, 0x0c, 0xc3, 0x5a,
800       0x29, 0x15, 0x0b, 0xa7, 0x94, 0x8a, 0x8b, 0xa2,
801       0xa8, 0xab, 0xaa, 0xea, 0x9d, 0x21, 0x36, 0x81,
802       0xf3, 0x7b, 0x00, 0xe4, 0x79, 0x7e, 0x10, 0x03,
803       0x40, 0x51, 0x14, 0xb5, 0x70, 0x0e, 0x96, 0x33,
804       0xfe, 0x89, 0xc0, 0xde, 0x69, 0x2d, 0x44, 0x92,
805       0x24, 0x91, 0x8c, 0xe7, 0x26, 0x4f, 0x52, 0x4f,
806       0x81, 0x3d, 0xee, 0x5a, 0x3e, 0x47, 0x4c, 0xae,
807       0x50, 0x29, 0x15, 0xb7, 0x6d, 0xfb, 0xe1, 0xec,
808       0x79, 0xf4, 0x81, 0x0b, 0x70, 0x0f, 0x2c, 0x9a,
809       0xa6, 0x19, 0x8d, 0x31, 0x5d, 0x59, 0x96, 0x47,
810       0x31, 0x69, 0xad, 0xcf, 0xc6, 0x98, 0xce, 0x31,
811       0x0d, 0x80, 0x96, 0xe6, 0x48, 0x01, 0xe6, 0xbf,
812       0xac, 0x76, 0x01, 0x6a, 0x60, 0x2f, 0xcd, 0xe9,
813       0x6d, 0x23, 0x6e, 0xed, 0x9d, 0xae, 0x61, 0x00,
814       0x5e, 0xb1, 0x95, 0xf3, 0x26, 0x8f, 0x7f, 0x2e,
815       0xf9, 0x17, 0x50, 0x59, 0x74, 0x13, 0x34, 0x41,
816       0x04, 0x5a, 0x00, 0x00, 0x00, 0x20, 0x7a, 0x54,
817       0x58, 0x74, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x72,
818       0x6f, 0x77, 0x73, 0x2d, 0x70, 0x65, 0x72, 0x2d,
819       0x73, 0x74, 0x72, 0x69, 0x70, 0x00, 0x00, 0x78,
820       0xda, 0x33, 0xb5, 0x30, 0x05, 0x00, 0x01, 0x47,
821       0x00, 0xa3, 0x38, 0xda, 0x77, 0x3b, 0x00, 0x00,
822       0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
823       0x60, 0x82};
824 
825     // currently we only support the close bitmap here
826     if ( button != wxTITLEBAR_BUTTON_CLOSE )
827     {
828         m_rendererNative.DrawTitleBarBitmap(win, dc, rect, button, flags);
829         return;
830     }
831 
832     // choose the correct image depending on flags
833     const void *data;
834     size_t len;
835 
836     if ( flags & wxCONTROL_PRESSED )
837     {
838         data = close_pressed_png;
839         len = WXSIZEOF(close_pressed_png);
840     }
841     else if ( flags & wxCONTROL_CURRENT )
842     {
843         data = close_current_png;
844         len = WXSIZEOF(close_current_png);
845     }
846     else
847     {
848         data = close_png;
849         len = WXSIZEOF(close_png);
850     }
851 
852     // load it
853     wxMemoryInputStream mis(data, len);
854     wxImage image(mis, wxBITMAP_TYPE_PNG);
855     wxBitmap bmp(image);
856     wxASSERT_MSG( bmp.IsOk(), "failed to load embedded PNG image?" );
857 
858     // and draw it centering it in the provided rectangle: we don't scale the
859     // image because this is really not going to look good for such a small
860     // (14*14) bitmap
861     dc.DrawBitmap(bmp, wxRect(bmp.GetSize()).CenterIn(rect).GetPosition());
862 }
863 
864 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
865 
866 #endif
867