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: renderer.cpp 54486 2008-07-04 14:23:38Z SC $
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/graphics.h"
30#include "wx/mac/uma.h"
31
32
33// check if we're currently in a paint event
34inline bool wxInPaintEvent(wxWindow* win, wxDC& dc)
35{
36    return
37#if wxMAC_USE_CORE_GRAPHICS
38        win->MacGetCGContextRef() != NULL ||
39#endif
40         // wxMemoryDC derives from wxPaintDC so it is okay too.
41        dc.IsKindOf( CLASSINFO(wxPaintDC) );
42}
43
44
45
46class WXDLLEXPORT wxRendererMac : public wxDelegateRendererNative
47{
48public:
49    // draw the header control button (used by wxListCtrl)
50    virtual int DrawHeaderButton( wxWindow *win,
51        wxDC& dc,
52        const wxRect& rect,
53        int flags = 0,
54        wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
55        wxHeaderButtonParams* params = NULL );
56
57    virtual int GetHeaderButtonHeight(wxWindow *win);
58
59    // draw the expanded/collapsed icon for a tree control item
60    virtual void DrawTreeItemButton( wxWindow *win,
61        wxDC& dc,
62        const wxRect& rect,
63        int flags = 0 );
64
65    // draw a (vertical) sash
66    virtual void DrawSplitterSash( wxWindow *win,
67        wxDC& dc,
68        const wxSize& size,
69        wxCoord position,
70        wxOrientation orient,
71        int flags = 0 );
72
73    virtual void DrawCheckBox(wxWindow *win,
74                              wxDC& dc,
75                              const wxRect& rect,
76                              int flags = 0);
77
78    virtual void DrawComboBoxDropButton(wxWindow *win,
79                                        wxDC& dc,
80                                        const wxRect& rect,
81                                        int flags = 0);
82
83    virtual void DrawPushButton(wxWindow *win,
84                                wxDC& dc,
85                                const wxRect& rect,
86                                int flags = 0);
87
88    virtual void DrawItemSelectionRect(wxWindow *win,
89                                       wxDC& dc,
90                                       const wxRect& rect,
91                                       int flags = 0);
92
93private:
94    void DrawMacThemeButton(wxWindow *win,
95                            wxDC& dc,
96                            const wxRect& rect,
97                            int flags,
98                            int kind,
99                            int adornment);
100
101    // the tree buttons
102    wxBitmap m_bmpTreeExpanded;
103    wxBitmap m_bmpTreeCollapsed;
104
105    friend void wxRenderer_DrawRadioButton(wxWindow* win, wxDC& dc,
106                                           const wxRect& rect, int flags);
107    friend void wxRenderer_DrawChoice(wxWindow* win, wxDC& dc,
108                                      const wxRect& rect, int flags);
109    friend void wxRenderer_DrawComboBox(wxWindow* win, wxDC& dc,
110                                        const wxRect& rect, int flags);
111};
112
113// ============================================================================
114// implementation
115// ============================================================================
116
117// static
118wxRendererNative& wxRendererNative::GetDefault()
119{
120    static wxRendererMac s_rendererMac;
121
122    return s_rendererMac;
123}
124
125int wxRendererMac::DrawHeaderButton( wxWindow *win,
126    wxDC& dc,
127    const wxRect& rect,
128    int flags,
129    wxHeaderSortIconType sortArrow,
130    wxHeaderButtonParams* params )
131{
132#if !wxMAC_USE_CORE_GRAPHICS
133    const wxCoord x = dc.LogicalToDeviceX(rect.x);
134    const wxCoord y = dc.LogicalToDeviceY(rect.y);
135    const wxCoord w = dc.LogicalToDeviceXRel(rect.width);
136    const wxCoord h = dc.LogicalToDeviceYRel(rect.height);
137#else
138    // now the wxGCDC is using native transformations
139    const wxCoord x = rect.x;
140    const wxCoord y = rect.y;
141    const wxCoord w = rect.width;
142    const wxCoord h = rect.height;
143#endif
144
145    dc.SetBrush( *wxTRANSPARENT_BRUSH );
146
147    HIRect headerRect = CGRectMake( x, y, w, h );
148    if ( !wxInPaintEvent(win, dc) )
149    {
150        Rect r =
151        {
152            (short) headerRect.origin.y, (short) headerRect.origin.x,
153            (short) (headerRect.origin.y + headerRect.size.height),
154            (short) (headerRect.origin.x + headerRect.size.width)
155        };
156
157        RgnHandle updateRgn = NewRgn();
158        RectRgn( updateRgn, &r );
159        HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
160        DisposeRgn( updateRgn );
161    }
162    else
163    {
164        CGContextRef cgContext;
165
166#if wxMAC_USE_CORE_GRAPHICS
167        cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
168#else
169        Rect bounds;
170
171        GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
172        QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
173
174        CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
175        CGContextScaleCTM( cgContext, 1, -1 );
176
177        HIShapeRef shape = HIShapeCreateWithQDRgn( (RgnHandle) dc.m_macCurrentClipRgn );
178        if ( shape != 0 )
179        {
180            HIShapeReplacePathInCGContext( shape , cgContext );
181            CFRelease( shape );
182            CGContextClip( cgContext );
183        }
184        HIViewConvertRect( &headerRect, (HIViewRef) win->GetHandle(), (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
185#endif
186
187        {
188            HIThemeButtonDrawInfo drawInfo;
189            HIRect labelRect;
190
191            memset( &drawInfo, 0, sizeof(drawInfo) );
192            drawInfo.version = 0;
193            drawInfo.kind = kThemeListHeaderButton;
194            drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
195            drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
196            drawInfo.adornment = kThemeAdornmentNone;
197
198            // The down arrow is drawn automatically, change it to an up arrow if needed.
199            if ( sortArrow == wxHDR_SORT_ICON_UP )
200                drawInfo.adornment = kThemeAdornmentHeaderButtonSortUp;
201
202            HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
203
204            // If we don't want any arrows we need to draw over the one already there
205            if ( (flags & wxCONTROL_SELECTED) && (sortArrow == wxHDR_SORT_ICON_NONE) )
206            {
207                // clip to the header rectangle
208                CGContextSaveGState( cgContext );
209                CGContextClipToRect( cgContext, headerRect );
210                // but draw bigger than that so the arrow will get clipped off
211                headerRect.size.width += 25;
212                HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
213                CGContextRestoreGState( cgContext );
214            }
215        }
216
217#if wxMAC_USE_CORE_GRAPHICS
218#else
219        QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
220#endif
221    }
222
223    // Reserve room for the arrows before writing the label, and turn off the
224    // flags we've already handled
225    wxRect newRect(rect);
226    if ( (flags & wxCONTROL_SELECTED) && (sortArrow != wxHDR_SORT_ICON_NONE) )
227    {
228        newRect.width -= 12;
229        sortArrow = wxHDR_SORT_ICON_NONE;
230    }
231    flags &= ~wxCONTROL_SELECTED;
232
233    return DrawHeaderButtonContents(win, dc, newRect, flags, sortArrow, params);
234}
235
236
237int wxRendererMac::GetHeaderButtonHeight(wxWindow* WXUNUSED(win))
238{
239    SInt32		standardHeight;
240    OSStatus		errStatus;
241
242    errStatus = GetThemeMetric( kThemeMetricListHeaderHeight, &standardHeight );
243    if (errStatus == noErr)
244    {
245        return standardHeight;
246    }
247    return -1;
248}
249
250void wxRendererMac::DrawTreeItemButton( wxWindow *win,
251    wxDC& dc,
252    const wxRect& rect,
253    int flags )
254{
255#if !wxMAC_USE_CORE_GRAPHICS
256    const wxCoord x = dc.LogicalToDeviceX(rect.x);
257    const wxCoord y = dc.LogicalToDeviceY(rect.y);
258    const wxCoord w = dc.LogicalToDeviceXRel(rect.width);
259    const wxCoord h = dc.LogicalToDeviceYRel(rect.height);
260#else
261    // now the wxGCDC is using native transformations
262    const wxCoord x = rect.x;
263    const wxCoord y = rect.y;
264    const wxCoord w = rect.width;
265    const wxCoord h = rect.height;
266#endif
267
268    dc.SetBrush( *wxTRANSPARENT_BRUSH );
269
270    HIRect headerRect = CGRectMake( x, y, w, h );
271    if ( !wxInPaintEvent(win, dc) )
272    {
273        Rect r =
274    {
275            (short) headerRect.origin.y, (short) headerRect.origin.x,
276            (short) (headerRect.origin.y + headerRect.size.height),
277            (short) (headerRect.origin.x + headerRect.size.width)
278        };
279
280        RgnHandle updateRgn = NewRgn();
281        RectRgn( updateRgn, &r );
282        HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
283        DisposeRgn( updateRgn );
284    }
285    else
286    {
287        CGContextRef cgContext;
288
289#if wxMAC_USE_CORE_GRAPHICS
290        cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
291#else
292        Rect bounds;
293
294        GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
295        QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
296
297        CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
298        CGContextScaleCTM( cgContext, 1, -1 );
299
300        HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle) dc.m_macCurrentClipRgn ), cgContext );
301        CGContextClip( cgContext );
302        HIViewConvertRect( &headerRect, (HIViewRef) win->GetHandle(), (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
303#endif
304
305    {
306            HIThemeButtonDrawInfo drawInfo;
307            HIRect labelRect;
308
309            memset( &drawInfo, 0, sizeof(drawInfo) );
310            drawInfo.version = 0;
311            drawInfo.kind = kThemeDisclosureButton;
312            drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
313            // Apple mailing list posts say to use the arrow adornment constants, but those don't work.
314            // We need to set the value using the 'old' DrawThemeButton constants instead.
315            drawInfo.value = (flags & wxCONTROL_EXPANDED) ? kThemeDisclosureDown : kThemeDisclosureRight;
316            drawInfo.adornment = kThemeAdornmentNone;
317
318            HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
319
320        }
321
322#if wxMAC_USE_CORE_GRAPHICS
323#else
324        QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
325#endif
326    }
327}
328
329void wxRendererMac::DrawSplitterSash( wxWindow *win,
330    wxDC& dc,
331    const wxSize& size,
332    wxCoord position,
333    wxOrientation orient,
334    int WXUNUSED(flags) )
335{
336    bool hasMetal = win->MacGetTopLevelWindow()->MacGetMetalAppearance();
337    SInt32 height;
338    GetThemeMetric( kThemeMetricSmallPaneSplitterHeight, &height );
339    HIRect splitterRect;
340    if (orient == wxVERTICAL)
341        splitterRect = CGRectMake( position, 0, height, size.y );
342    else
343        splitterRect = CGRectMake( 0, position, size.x, height );
344
345#if !wxMAC_USE_CORE_GRAPHICS
346    HIViewConvertRect(
347        &splitterRect,
348        (HIViewRef) win->GetHandle(),
349        (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
350#endif
351
352    // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
353    // strange redraw errors occur if we don't do this
354
355    if ( !wxInPaintEvent(win, dc) )
356    {
357        Rect r =
358        {
359            (short) splitterRect.origin.y,
360            (short) splitterRect.origin.x,
361            (short) (splitterRect.origin.y + splitterRect.size.height),
362            (short) (splitterRect.origin.x + splitterRect.size.width)
363        };
364
365        RgnHandle updateRgn = NewRgn();
366        RectRgn( updateRgn, &r );
367        HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
368        DisposeRgn( updateRgn );
369    }
370    else
371    {
372        CGContextRef cgContext;
373
374#if wxMAC_USE_CORE_GRAPHICS
375        cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
376#else
377        Rect bounds;
378        GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
379        QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
380        CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
381        CGContextScaleCTM( cgContext, 1, -1 );
382#endif
383
384        HIThemeSplitterDrawInfo drawInfo;
385        drawInfo.version = 0;
386        drawInfo.state = kThemeStateActive;
387        drawInfo.adornment = hasMetal ? kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
388        HIThemeDrawPaneSplitter( &splitterRect, &drawInfo, cgContext, kHIThemeOrientationNormal );
389
390#if wxMAC_USE_CORE_GRAPHICS
391#else
392        QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
393#endif
394    }
395}
396
397void
398wxRendererMac::DrawItemSelectionRect(wxWindow *win,
399                                     wxDC& dc,
400                                     const wxRect& rect,
401                                     int flags )
402{
403    RGBColor selColor;
404    if (flags & wxCONTROL_SELECTED)
405    {
406        if (flags & wxCONTROL_FOCUSED)
407            GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor, 32, true, &selColor);
408        else
409            GetThemeBrushAsColor(kThemeBrushSecondaryHighlightColor, 32, true, &selColor);
410    }
411
412    wxBrush selBrush = wxBrush( wxColour( selColor.red >> 8, selColor.green >> 8, selColor.blue >> 8 ), wxSOLID );
413
414    dc.SetPen( *wxTRANSPARENT_PEN );
415    dc.SetBrush( selBrush );
416    dc.DrawRectangle( rect );
417}
418
419
420void
421wxRendererMac::DrawMacThemeButton(wxWindow *win,
422                                  wxDC& dc,
423                                  const wxRect& rect,
424                                  int flags,
425                                  int kind,
426                                  int adornment)
427{
428#if !wxMAC_USE_CORE_GRAPHICS
429    const wxCoord x = dc.LogicalToDeviceX(rect.x);
430    const wxCoord y = dc.LogicalToDeviceY(rect.y);
431    const wxCoord w = dc.LogicalToDeviceXRel(rect.width);
432    const wxCoord h = dc.LogicalToDeviceYRel(rect.height);
433#else
434    // now the wxGCDC is using native transformations
435    const wxCoord x = rect.x;
436    const wxCoord y = rect.y;
437    const wxCoord w = rect.width;
438    const wxCoord h = rect.height;
439#endif
440
441    dc.SetBrush( *wxTRANSPARENT_BRUSH );
442
443    HIRect headerRect = CGRectMake( x, y, w, h );
444    if ( !wxInPaintEvent(win, dc) )
445    {
446        Rect r =
447        {
448            (short) headerRect.origin.y, (short) headerRect.origin.x,
449            (short) (headerRect.origin.y + headerRect.size.height),
450            (short) (headerRect.origin.x + headerRect.size.width)
451        };
452
453        RgnHandle updateRgn = NewRgn();
454        RectRgn( updateRgn, &r );
455        HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
456        DisposeRgn( updateRgn );
457    }
458    else
459    {
460        CGContextRef cgContext;
461
462#if wxMAC_USE_CORE_GRAPHICS
463        cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
464#else
465        Rect bounds;
466
467        GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
468        QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
469
470        CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
471        CGContextScaleCTM( cgContext, 1, -1 );
472
473        HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle) dc.m_macCurrentClipRgn ), cgContext );
474        CGContextClip( cgContext );
475        HIViewConvertRect( &headerRect, (HIViewRef) win->GetHandle(), (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
476#endif
477
478        {
479            HIThemeButtonDrawInfo drawInfo;
480            HIRect labelRect;
481
482            memset( &drawInfo, 0, sizeof(drawInfo) );
483            drawInfo.version = 0;
484            drawInfo.kind = kind;
485            drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
486            drawInfo.value = (flags & wxCONTROL_SELECTED) ? kThemeButtonOn : kThemeButtonOff;
487            if (flags & wxCONTROL_UNDETERMINED)
488                drawInfo.value = kThemeButtonMixed;
489            drawInfo.adornment = adornment;
490            if (flags & wxCONTROL_FOCUSED)
491                drawInfo.adornment |= kThemeAdornmentFocus;
492
493            HIThemeDrawButton( &headerRect, &drawInfo, cgContext, kHIThemeOrientationNormal, &labelRect );
494        }
495
496#if wxMAC_USE_CORE_GRAPHICS
497#else
498        QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
499#endif
500    }
501}
502
503void
504wxRendererMac::DrawCheckBox(wxWindow *win,
505                            wxDC& dc,
506                            const wxRect& rect,
507                            int flags)
508{
509    int kind;
510
511    if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
512        (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
513        kind = kThemeSmallCheckBox;
514    else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
515             (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
516        kind = kThemeMiniCheckBox;
517    else
518        kind = kThemeCheckBox;
519
520    if (flags & wxCONTROL_CHECKED)
521        flags |= wxCONTROL_SELECTED;
522
523    DrawMacThemeButton(win, dc, rect, flags,
524                       kind, kThemeAdornmentNone);
525}
526
527void
528wxRendererMac::DrawComboBoxDropButton(wxWindow *win,
529                              wxDC& dc,
530                              const wxRect& rect,
531                              int flags)
532{
533    int kind;
534    if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
535        kind = kThemeArrowButtonSmall;
536    else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
537        kind = kThemeArrowButtonMini;
538    else
539        kind = kThemeArrowButton;
540
541    DrawMacThemeButton(win, dc, rect, flags,
542                       kind, kThemeAdornmentArrowDownArrow);
543}
544
545void
546wxRendererMac::DrawPushButton(wxWindow *win,
547                              wxDC& dc,
548                              const wxRect& rect,
549                              int flags)
550{
551    int kind;
552#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
553    if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
554        kind = kThemeBevelButtonSmall;
555    // There is no kThemeBevelButtonMini, but in this case, use Small
556    else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
557        kind = kThemeBevelButtonSmall;
558    else
559#endif
560        kind = kThemeBevelButton;
561
562    DrawMacThemeButton(win, dc, rect, flags,
563                       kind, kThemeAdornmentNone);
564}
565
566
567
568
569void wxRenderer_DrawChoice(wxWindow* win, wxDC& dc,
570                           const wxRect& rect, int flags)
571{
572    wxRendererMac& r = (wxRendererMac&)wxRendererNative::Get();
573    int kind;
574
575    if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
576        (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
577        kind = kThemePopupButtonSmall;
578    else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
579             (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
580        kind = kThemePopupButtonMini;
581    else
582        kind = kThemePopupButton;
583
584    r.DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone);
585}
586
587
588void wxRenderer_DrawComboBox(wxWindow* win, wxDC& dc,
589                             const wxRect& rect, int flags)
590{
591    wxRendererMac& r = (wxRendererMac&)wxRendererNative::Get();
592    int kind;
593
594    if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
595        (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
596        kind = kThemeComboBoxSmall;
597    else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
598             (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
599        kind = kThemeComboBoxMini;
600    else
601        kind = kThemeComboBox;
602
603    r.DrawMacThemeButton(win, dc, rect, flags, kind, kThemeAdornmentNone);
604}
605
606void wxRenderer_DrawRadioButton(wxWindow* win, wxDC& dc,
607                                const wxRect& rect, int flags)
608{
609    wxRendererMac& r = (wxRendererMac&)wxRendererNative::Get();
610    int kind;
611
612    if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL ||
613        (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
614        kind = kThemeSmallRadioButton;
615    else if (win->GetWindowVariant() == wxWINDOW_VARIANT_MINI ||
616             (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_MINI))
617        kind = kThemeMiniRadioButton;
618    else
619        kind = kThemeRadioButton;
620
621    if (flags & wxCONTROL_CHECKED)
622        flags |= wxCONTROL_SELECTED;
623
624    r.DrawMacThemeButton(win, dc, rect, flags,
625                          kind, kThemeAdornmentNone);
626}
627
628
629
630void wxRenderer_DrawTextCtrl(wxWindow* win, wxDC& dc,
631                             const wxRect& rect, int flags)
632{
633#if !wxMAC_USE_CORE_GRAPHICS
634    const wxCoord x = dc.LogicalToDeviceX(rect.x);
635    const wxCoord y = dc.LogicalToDeviceY(rect.y);
636    const wxCoord w = dc.LogicalToDeviceXRel(rect.width);
637    const wxCoord h = dc.LogicalToDeviceYRel(rect.height);
638#else
639    // now the wxGCDC is using native transformations
640    const wxCoord x = rect.x;
641    const wxCoord y = rect.y;
642    const wxCoord w = rect.width;
643    const wxCoord h = rect.height;
644#endif
645
646    dc.SetBrush( *wxWHITE_BRUSH );
647    dc.SetPen( *wxTRANSPARENT_PEN );
648    dc.DrawRectangle(rect);
649
650    dc.SetBrush( *wxTRANSPARENT_BRUSH );
651
652    HIRect hiRect = CGRectMake( x, y, w, h );
653    if ( !wxInPaintEvent(win, dc) )
654    {
655        Rect r =
656        {
657            (short) hiRect.origin.y, (short) hiRect.origin.x,
658            (short) (hiRect.origin.y + hiRect.size.height),
659            (short) (hiRect.origin.x + hiRect.size.width)
660        };
661
662        RgnHandle updateRgn = NewRgn();
663        RectRgn( updateRgn, &r );
664        HIViewSetNeedsDisplayInRegion( (HIViewRef) win->GetHandle(), updateRgn, true );
665        DisposeRgn( updateRgn );
666    }
667    else
668    {
669        CGContextRef cgContext;
670
671#if wxMAC_USE_CORE_GRAPHICS
672        cgContext = (CGContextRef) dc.GetGraphicsContext()->GetNativeContext();
673#else
674        Rect bounds;
675
676        GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
677        QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
678
679        CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
680        CGContextScaleCTM( cgContext, 1, -1 );
681
682        HIShapeReplacePathInCGContext( HIShapeCreateWithQDRgn( (RgnHandle) dc.m_macCurrentClipRgn ), cgContext );
683        CGContextClip( cgContext );
684        HIViewConvertRect( &hiRect, (HIViewRef) win->GetHandle(), (HIViewRef) win->MacGetTopLevelWindow()->GetHandle() );
685#endif
686
687        {
688            HIThemeFrameDrawInfo drawInfo;
689
690            memset( &drawInfo, 0, sizeof(drawInfo) );
691            drawInfo.version = 0;
692            drawInfo.kind = kHIThemeFrameTextFieldSquare;
693            drawInfo.state = (flags & wxCONTROL_DISABLED) ? kThemeStateInactive : kThemeStateActive;
694            if (flags & wxCONTROL_FOCUSED)
695                drawInfo.isFocused = true;
696
697            HIThemeDrawFrame( &hiRect, &drawInfo, cgContext, kHIThemeOrientationNormal);
698        }
699
700#if wxMAC_USE_CORE_GRAPHICS
701#else
702        QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
703#endif
704    }
705}
706
707
708