1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/renderer.cpp
3 // Purpose: implementation of wxRendererNative for wxGTK
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
26 #include "wx/renderer.h"
29 #include "wx/window.h"
30 #include "wx/dcclient.h"
31 #include "wx/settings.h"
32 #include "wx/module.h"
35 #include "wx/dcgraph.h"
37 #include "wx/gtk/dc.h"
41 #include "wx/gtk/private.h"
42 #include "wx/gtk/private/gtk2-compat.h"
44 // ----------------------------------------------------------------------------
45 // wxRendererGTK: our wxRendererNative implementation
46 // ----------------------------------------------------------------------------
48 class WXDLLEXPORT wxRendererGTK
: public wxDelegateRendererNative
51 // draw the header control button (used by wxListCtrl)
52 virtual int DrawHeaderButton(wxWindow
*win
,
56 wxHeaderSortIconType sortArrow
= wxHDR_SORT_ICON_NONE
,
57 wxHeaderButtonParams
* params
= NULL
);
59 virtual int GetHeaderButtonHeight(wxWindow
*win
);
61 virtual int GetHeaderButtonMargin(wxWindow
*win
);
64 // draw the expanded/collapsed icon for a tree control item
65 virtual void DrawTreeItemButton(wxWindow
*win
,
70 virtual void DrawSplitterBorder(wxWindow
*win
,
74 virtual void DrawSplitterSash(wxWindow
*win
,
81 virtual void DrawComboBoxDropButton(wxWindow
*win
,
86 virtual void DrawDropArrow(wxWindow
*win
,
91 virtual void DrawCheckBox(wxWindow
*win
,
96 virtual void DrawPushButton(wxWindow
*win
,
101 virtual void DrawItemSelectionRect(wxWindow
*win
,
106 virtual void DrawChoice(wxWindow
* win
,
111 virtual void DrawComboBox(wxWindow
* win
,
116 virtual void DrawTextCtrl(wxWindow
* win
,
121 virtual void DrawRadioBitmap(wxWindow
* win
,
126 virtual void DrawFocusRect(wxWindow
* win
, wxDC
& dc
, const wxRect
& rect
, int flags
= 0);
128 virtual wxSize
GetCheckBoxSize(wxWindow
*win
);
130 virtual wxSplitterRenderParams
GetSplitterParams(const wxWindow
*win
);
133 // ============================================================================
135 // ============================================================================
138 wxRendererNative
& wxRendererNative::GetDefault()
140 static wxRendererGTK s_rendererGTK
;
142 return s_rendererGTK
;
147 typedef cairo_t wxGTKDrawable
;
149 static cairo_t
* wxGetGTKDrawable(wxWindow
*, const wxDC
& dc
)
151 wxGraphicsContext
* gc
= dc
.GetGraphicsContext();
152 wxCHECK_MSG(gc
, NULL
, "cannot use wxRendererNative on wxDC of this type");
153 return static_cast<cairo_t
*>(gc
->GetNativeContext());
156 static const GtkStateFlags stateTypeToFlags
[] = {
157 GTK_STATE_FLAG_NORMAL
, GTK_STATE_FLAG_ACTIVE
, GTK_STATE_FLAG_PRELIGHT
,
158 GTK_STATE_FLAG_SELECTED
, GTK_STATE_FLAG_INSENSITIVE
, GTK_STATE_FLAG_INCONSISTENT
,
159 GTK_STATE_FLAG_FOCUSED
163 #define NULL_RECT NULL,
164 typedef GdkWindow wxGTKDrawable
;
166 static GdkWindow
* wxGetGTKDrawable(wxWindow
* win
, wxDC
& dc
)
168 GdkWindow
* gdk_window
= NULL
;
170 #if wxUSE_GRAPHICS_CONTEXT
171 if ( wxDynamicCast(&dc
, wxGCDC
) )
172 gdk_window
= win
->GTKGetDrawingWindow();
176 wxDCImpl
*impl
= dc
.GetImpl();
177 wxGTKDCImpl
*gtk_impl
= wxDynamicCast( impl
, wxGTKDCImpl
);
179 gdk_window
= gtk_impl
->GetGDKWindow();
181 wxFAIL_MSG("cannot use wxRendererNative on wxDC of this type");
184 #if !wxUSE_GRAPHICS_CONTEXT
192 // ----------------------------------------------------------------------------
193 // list/tree controls drawing
194 // ----------------------------------------------------------------------------
197 wxRendererGTK::DrawHeaderButton(wxWindow
*win
,
201 wxHeaderSortIconType sortArrow
,
202 wxHeaderButtonParams
* params
)
204 GtkWidget
*button
= wxGTKPrivate::GetHeaderButtonWidget();
205 if (flags
& wxCONTROL_SPECIAL
)
206 button
= wxGTKPrivate::GetHeaderButtonWidgetFirst();
207 if (flags
& wxCONTROL_DIRTY
)
208 button
= wxGTKPrivate::GetHeaderButtonWidgetLast();
211 if (win
->GetLayoutDirection() == wxLayout_RightToLeft
)
214 GtkStateType state
= GTK_STATE_NORMAL
;
215 if (flags
& wxCONTROL_DISABLED
)
216 state
= GTK_STATE_INSENSITIVE
;
219 if (flags
& wxCONTROL_CURRENT
)
220 state
= GTK_STATE_PRELIGHT
;
224 cairo_t
* cr
= wxGetGTKDrawable(win
, dc
);
227 GtkStyleContext
* sc
= gtk_widget_get_style_context(button
);
228 gtk_style_context_save(sc
);
229 gtk_style_context_set_state(sc
, stateTypeToFlags
[state
]);
230 gtk_render_background(sc
, cr
, rect
.x
- x_diff
+4, rect
.y
+4, rect
.width
-8, rect
.height
-8);
231 gtk_render_frame(sc
, cr
, rect
.x
- x_diff
+4, rect
.y
+4, rect
.width
-8, rect
.height
-8);
232 gtk_style_context_restore(sc
);
235 GdkWindow
* gdk_window
= wxGetGTKDrawable(win
, dc
);
238 gtk_widget_get_style(button
),
245 dc
.LogicalToDeviceX(rect
.x
) - x_diff
, rect
.y
, rect
.width
, rect
.height
249 return DrawHeaderButtonContents(win
, dc
, rect
, flags
, sortArrow
, params
);
252 int wxRendererGTK::GetHeaderButtonHeight(wxWindow
*WXUNUSED(win
))
254 GtkWidget
*button
= wxGTKPrivate::GetHeaderButtonWidget();
258 gtk_widget_get_preferred_height(button
, NULL
, &req
.height
);
260 GTK_WIDGET_GET_CLASS(button
)->size_request(button
, &req
);
266 int wxRendererGTK::GetHeaderButtonMargin(wxWindow
*WXUNUSED(win
))
268 wxFAIL_MSG( "GetHeaderButtonMargin() not implemented" );
273 // draw a ">" or "v" button
275 wxRendererGTK::DrawTreeItemButton(wxWindow
* win
,
276 wxDC
& dc
, const wxRect
& rect
, int flags
)
278 GtkWidget
*tree
= wxGTKPrivate::GetTreeWidget();
281 if ( flags
& wxCONTROL_CURRENT
)
282 state
= GTK_STATE_PRELIGHT
;
284 state
= GTK_STATE_NORMAL
;
287 if (win
->GetLayoutDirection() == wxLayout_RightToLeft
)
291 cairo_t
* cr
= wxGetGTKDrawable(win
, dc
);
294 gtk_widget_set_state_flags(tree
, stateTypeToFlags
[state
], true);
295 GtkStyleContext
* sc
= gtk_widget_get_style_context(tree
);
296 gtk_render_expander(sc
, cr
, rect
.x
- x_diff
, rect
.y
, rect
.width
, rect
.height
);
299 // x and y parameters specify the center of the expander
300 GdkWindow
* gdk_window
= wxGetGTKDrawable(win
, dc
);
301 if (gdk_window
== NULL
)
305 gtk_widget_get_style(tree
),
311 dc
.LogicalToDeviceX(rect
.x
) + rect
.width
/ 2 - x_diff
,
312 dc
.LogicalToDeviceY(rect
.y
) + rect
.height
/ 2,
313 flags
& wxCONTROL_EXPANDED
? GTK_EXPANDER_EXPANDED
314 : GTK_EXPANDER_COLLAPSED
320 // ----------------------------------------------------------------------------
321 // splitter sash drawing
322 // ----------------------------------------------------------------------------
324 static int GetGtkSplitterFullSize(GtkWidget
* widget
)
327 gtk_widget_style_get(widget
, "handle_size", &handle_size
, NULL
);
332 wxSplitterRenderParams
333 wxRendererGTK::GetSplitterParams(const wxWindow
*WXUNUSED(win
))
335 // we don't draw any border, hence 0 for the second field
336 return wxSplitterRenderParams
338 GetGtkSplitterFullSize(wxGTKPrivate::GetSplitterWidget()),
340 true // hot sensitive
345 wxRendererGTK::DrawSplitterBorder(wxWindow
* WXUNUSED(win
),
347 const wxRect
& WXUNUSED(rect
),
354 wxRendererGTK::DrawSplitterSash(wxWindow
* win
,
358 wxOrientation orient
,
361 if (gtk_widget_get_window(win
->m_wxwindow
) == NULL
)
363 // window not realized yet
367 wxGTKDrawable
* drawable
= wxGetGTKDrawable(win
, dc
);
368 if (drawable
== NULL
)
371 // are we drawing vertical or horizontal splitter?
372 const bool isVert
= orient
== wxVERTICAL
;
374 GtkWidget
* widget
= wxGTKPrivate::GetSplitterWidget(orient
);
375 const int full_size
= GetGtkSplitterFullSize(widget
);
383 rect
.width
= full_size
;
384 rect
.height
= size
.y
;
390 rect
.height
= full_size
;
395 if (win
->GetLayoutDirection() == wxLayout_RightToLeft
)
399 cairo_t
* cr
= wxGetGTKDrawable(win
, dc
);
402 gtk_widget_set_state_flags(widget
, stateTypeToFlags
[flags
& wxCONTROL_CURRENT
? GTK_STATE_PRELIGHT
: GTK_STATE_NORMAL
], true);
403 GtkStyleContext
* sc
= gtk_widget_get_style_context(widget
);
404 gtk_render_handle(sc
, cr
, rect
.x
- x_diff
, rect
.y
, rect
.width
, rect
.height
);
407 GdkWindow
* gdk_window
= wxGetGTKDrawable(win
, dc
);
408 if (gdk_window
== NULL
)
412 gtk_widget_get_style(win
->m_wxwindow
),
414 flags
& wxCONTROL_CURRENT
? GTK_STATE_PRELIGHT
: GTK_STATE_NORMAL
,
416 NULL
/* no clipping */,
419 dc
.LogicalToDeviceX(rect
.x
) - x_diff
,
420 dc
.LogicalToDeviceY(rect
.y
),
423 isVert
? GTK_ORIENTATION_VERTICAL
: GTK_ORIENTATION_HORIZONTAL
429 wxRendererGTK::DrawDropArrow(wxWindow
* win
,
434 GtkWidget
*button
= wxGTKPrivate::GetButtonWidget();
436 // If we give WX_PIZZA(win->m_wxwindow)->bin_window as
437 // a window for gtk_paint_xxx function, then it won't
438 // work for wxMemoryDC. So that is why we assume wxDC
439 // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC
440 // are derived from it) and use its m_window.
442 // draw arrow so that there is even space horizontally
444 const int size
= rect
.width
/ 2;
445 const int x
= rect
.x
+ (size
+ 1) / 2;
446 const int y
= rect
.y
+ (rect
.height
- size
+ 1) / 2;
450 if ( flags
& wxCONTROL_PRESSED
)
451 state
= GTK_STATE_ACTIVE
;
452 else if ( flags
& wxCONTROL_DISABLED
)
453 state
= GTK_STATE_INSENSITIVE
;
454 else if ( flags
& wxCONTROL_CURRENT
)
455 state
= GTK_STATE_PRELIGHT
;
457 state
= GTK_STATE_NORMAL
;
460 cairo_t
* cr
= wxGetGTKDrawable(win
, dc
);
463 gtk_widget_set_state_flags(button
, stateTypeToFlags
[state
], true);
464 GtkStyleContext
* sc
= gtk_widget_get_style_context(button
);
465 gtk_render_arrow(sc
, cr
, G_PI
, x
, y
, size
);
468 GdkWindow
* gdk_window
= wxGetGTKDrawable(win
, dc
);
469 if (gdk_window
== NULL
)
471 // draw arrow on button
474 gtk_widget_get_style(button
),
477 flags
& wxCONTROL_PRESSED
? GTK_SHADOW_IN
: GTK_SHADOW_OUT
,
490 wxRendererGTK::DrawComboBoxDropButton(wxWindow
*win
,
495 DrawPushButton(win
,dc
,rect
,flags
);
496 DrawDropArrow(win
,dc
,rect
);
500 wxRendererGTK::GetCheckBoxSize(wxWindow
*WXUNUSED(win
))
502 gint indicator_size
, indicator_spacing
;
503 gtk_widget_style_get(wxGTKPrivate::GetCheckButtonWidget(),
504 "indicator_size", &indicator_size
,
505 "indicator_spacing", &indicator_spacing
,
508 int size
= indicator_size
+ indicator_spacing
* 2;
509 return wxSize(size
, size
);
513 wxRendererGTK::DrawCheckBox(wxWindow
* win
,
518 GtkWidget
*button
= wxGTKPrivate::GetCheckButtonWidget();
520 gint indicator_size
, indicator_spacing
;
521 gtk_widget_style_get(button
,
522 "indicator_size", &indicator_size
,
523 "indicator_spacing", &indicator_spacing
,
529 if ( flags
& wxCONTROL_PRESSED
)
530 state
= GTK_STATE_ACTIVE
;
531 else if ( flags
& wxCONTROL_DISABLED
)
532 state
= GTK_STATE_INSENSITIVE
;
533 else if ( flags
& wxCONTROL_CURRENT
)
534 state
= GTK_STATE_PRELIGHT
;
536 state
= GTK_STATE_NORMAL
;
538 GtkShadowType shadow_type
;
540 if ( flags
& wxCONTROL_UNDETERMINED
)
541 shadow_type
= GTK_SHADOW_ETCHED_IN
;
542 else if ( flags
& wxCONTROL_CHECKED
)
543 shadow_type
= GTK_SHADOW_IN
;
545 shadow_type
= GTK_SHADOW_OUT
;
549 cairo_t
* cr
= wxGetGTKDrawable(win
, dc
);
552 int stateFlags
= GTK_STATE_FLAG_NORMAL
;
553 if (flags
& wxCONTROL_CHECKED
)
554 stateFlags
= GTK_STATE_FLAG_ACTIVE
;
555 if (flags
& wxCONTROL_DISABLED
)
556 stateFlags
|= GTK_STATE_FLAG_INSENSITIVE
;
557 if (flags
& wxCONTROL_UNDETERMINED
)
558 stateFlags
|= GTK_STATE_FLAG_INCONSISTENT
;
559 if (flags
& wxCONTROL_CURRENT
)
560 stateFlags
|= GTK_STATE_FLAG_PRELIGHT
;
561 GtkStyleContext
* sc
= gtk_widget_get_style_context(button
);
562 gtk_style_context_save(sc
);
563 gtk_style_context_set_state(sc
, GtkStateFlags(stateFlags
));
564 gtk_style_context_add_class(sc
, GTK_STYLE_CLASS_CHECK
);
565 gtk_render_check(sc
, cr
,
566 rect
.x
+ (rect
.width
- indicator_size
) / 2,
567 rect
.y
+ (rect
.height
- indicator_size
) / 2,
568 indicator_size
, indicator_size
);
569 gtk_style_context_restore(sc
);
572 GdkWindow
* gdk_window
= wxGetGTKDrawable(win
, dc
);
573 if (gdk_window
== NULL
)
578 gtk_widget_get_style(button
),
585 dc
.LogicalToDeviceX(rect
.x
) + indicator_spacing
,
586 dc
.LogicalToDeviceY(rect
.y
) + indicator_spacing
,
587 indicator_size
, indicator_size
593 wxRendererGTK::DrawPushButton(wxWindow
* win
,
598 GtkWidget
*button
= wxGTKPrivate::GetButtonWidget();
603 if ( flags
& wxCONTROL_PRESSED
)
604 state
= GTK_STATE_ACTIVE
;
605 else if ( flags
& wxCONTROL_DISABLED
)
606 state
= GTK_STATE_INSENSITIVE
;
607 else if ( flags
& wxCONTROL_CURRENT
)
608 state
= GTK_STATE_PRELIGHT
;
610 state
= GTK_STATE_NORMAL
;
613 cairo_t
* cr
= wxGetGTKDrawable(win
, dc
);
616 GtkStyleContext
* sc
= gtk_widget_get_style_context(button
);
617 gtk_style_context_save(sc
);
618 gtk_style_context_set_state(sc
, stateTypeToFlags
[state
]);
619 gtk_render_background(sc
, cr
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
620 gtk_render_frame(sc
, cr
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
621 gtk_style_context_restore(sc
);
624 GdkWindow
* gdk_window
= wxGetGTKDrawable(win
, dc
);
625 if (gdk_window
== NULL
)
630 gtk_widget_get_style(button
),
633 flags
& wxCONTROL_PRESSED
? GTK_SHADOW_IN
: GTK_SHADOW_OUT
,
637 dc
.LogicalToDeviceX(rect
.x
),
638 dc
.LogicalToDeviceY(rect
.y
),
646 wxRendererGTK::DrawItemSelectionRect(wxWindow
* win
,
651 wxGTKDrawable
* drawable
= wxGetGTKDrawable(win
, dc
);
652 if (drawable
== NULL
)
655 if (flags
& wxCONTROL_SELECTED
)
658 if (win
->GetLayoutDirection() == wxLayout_RightToLeft
)
661 GtkWidget
* treeWidget
= wxGTKPrivate::GetTreeWidget();
664 GtkStyleContext
* sc
= gtk_widget_get_style_context(treeWidget
);
665 gtk_style_context_save(sc
);
666 gtk_style_context_set_state(sc
, GTK_STATE_FLAG_SELECTED
);
667 gtk_style_context_add_class(sc
, GTK_STYLE_CLASS_CELL
);
668 gtk_render_background(sc
, drawable
, rect
.x
- x_diff
, rect
.y
, rect
.width
, rect
.height
);
669 gtk_style_context_restore(sc
);
671 // the wxCONTROL_FOCUSED state is deduced
672 // directly from the m_wxwindow by GTK+
673 gtk_paint_flat_box(gtk_widget_get_style(treeWidget
),
680 dc
.LogicalToDeviceX(rect
.x
) - x_diff
,
681 dc
.LogicalToDeviceY(rect
.y
),
687 if ((flags
& wxCONTROL_CURRENT
) && (flags
& wxCONTROL_FOCUSED
))
688 DrawFocusRect(win
, dc
, rect
, flags
);
691 void wxRendererGTK::DrawFocusRect(wxWindow
* win
, wxDC
& dc
, const wxRect
& rect
, int flags
)
693 wxGTKDrawable
* drawable
= wxGetGTKDrawable(win
, dc
);
694 if (drawable
== NULL
)
698 if (flags
& wxCONTROL_SELECTED
)
699 state
= GTK_STATE_SELECTED
;
701 state
= GTK_STATE_NORMAL
;
704 GtkStyleContext
* sc
= gtk_widget_get_style_context(win
->m_widget
);
705 gtk_style_context_save(sc
);
706 gtk_style_context_set_state(sc
, stateTypeToFlags
[state
]);
707 gtk_render_focus(sc
, drawable
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
708 gtk_style_context_restore(sc
);
710 gtk_paint_focus( gtk_widget_get_style(win
->m_widget
),
716 dc
.LogicalToDeviceX(rect
.x
),
717 dc
.LogicalToDeviceY(rect
.y
),
723 // Uses the theme to draw the border and fill for something like a wxTextCtrl
724 void wxRendererGTK::DrawTextCtrl(wxWindow
* win
, wxDC
& dc
, const wxRect
& rect
, int flags
)
726 wxGTKDrawable
* drawable
= wxGetGTKDrawable(win
, dc
);
727 if (drawable
== NULL
)
730 GtkWidget
* entry
= wxGTKPrivate::GetTextEntryWidget();
732 GtkStateType state
= GTK_STATE_NORMAL
;
733 if ( flags
& wxCONTROL_DISABLED
)
734 state
= GTK_STATE_INSENSITIVE
;
736 gtk_widget_set_can_focus(entry
, (flags
& wxCONTROL_CURRENT
) != 0);
739 GtkStyleContext
* sc
= gtk_widget_get_style_context(entry
);
740 gtk_style_context_save(sc
);
741 gtk_style_context_set_state(sc
, stateTypeToFlags
[state
]);
742 gtk_render_background(sc
, drawable
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
743 gtk_render_frame(sc
, drawable
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
744 gtk_style_context_restore(sc
);
748 gtk_widget_get_style(entry
),
755 dc
.LogicalToDeviceX(rect
.x
),
756 dc
.LogicalToDeviceY(rect
.y
),
763 // Draw the equivalent of a wxComboBox
764 void wxRendererGTK::DrawComboBox(wxWindow
* win
, wxDC
& dc
, const wxRect
& rect
, int flags
)
766 wxGTKDrawable
* drawable
= wxGetGTKDrawable(win
, dc
);
767 if (drawable
== NULL
)
770 GtkWidget
* combo
= wxGTKPrivate::GetComboBoxWidget();
772 GtkStateType state
= GTK_STATE_NORMAL
;
773 if ( flags
& wxCONTROL_DISABLED
)
774 state
= GTK_STATE_INSENSITIVE
;
776 gtk_widget_set_can_focus(combo
, (flags
& wxCONTROL_CURRENT
) != 0);
779 GtkStyleContext
* sc
= gtk_widget_get_style_context(combo
);
780 gtk_style_context_save(sc
);
781 gtk_style_context_set_state(sc
, stateTypeToFlags
[state
]);
782 gtk_render_background(sc
, drawable
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
783 gtk_render_frame(sc
, drawable
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
784 gtk_style_context_restore(sc
);
786 r
.x
+= r
.width
- r
.height
;
788 DrawComboBoxDropButton(win
, dc
, r
, flags
);
792 gtk_widget_get_style(combo
),
799 dc
.LogicalToDeviceX(rect
.x
),
800 dc
.LogicalToDeviceY(rect
.y
),
806 int extent
= rect
.height
/ 2;
807 r
.x
+= rect
.width
- extent
- extent
/2;
814 gtk_widget_get_style(combo
),
823 dc
.LogicalToDeviceX(r
.x
),
824 dc
.LogicalToDeviceY(r
.y
),
830 r
.x
+= rect
.width
- 2*extent
;
835 gtk_widget_get_style(combo
),
838 GTK_SHADOW_ETCHED_OUT
,
842 dc
.LogicalToDeviceX(r
.x
),
843 dc
.LogicalToDeviceY(r
.y
+1),
850 void wxRendererGTK::DrawChoice(wxWindow
* win
, wxDC
& dc
,
851 const wxRect
& rect
, int flags
)
853 DrawComboBox( win
, dc
, rect
, flags
);
857 // Draw a themed radio button
858 void wxRendererGTK::DrawRadioBitmap(wxWindow
* win
, wxDC
& dc
, const wxRect
& rect
, int flags
)
860 wxGTKDrawable
* drawable
= wxGetGTKDrawable(win
, dc
);
861 if (drawable
== NULL
)
864 GtkWidget
* button
= wxGTKPrivate::GetRadioButtonWidget();
867 int state
= GTK_STATE_FLAG_NORMAL
;
868 if (flags
& wxCONTROL_CHECKED
)
869 state
= GTK_STATE_FLAG_ACTIVE
;
870 else if (flags
& wxCONTROL_UNDETERMINED
)
871 state
= GTK_STATE_FLAG_INCONSISTENT
;
872 if (flags
& wxCONTROL_DISABLED
)
873 state
|= GTK_STATE_FLAG_INSENSITIVE
;
875 GtkStyleContext
* sc
= gtk_widget_get_style_context(button
);
876 gtk_style_context_save(sc
);
877 gtk_style_context_add_class(sc
, GTK_STYLE_CLASS_RADIO
);
878 gtk_style_context_set_state(sc
, GtkStateFlags(state
));
879 gtk_render_option(sc
, drawable
, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
880 gtk_style_context_restore(sc
);
882 GtkShadowType shadow_type
= GTK_SHADOW_OUT
;
883 if ( flags
& wxCONTROL_CHECKED
)
884 shadow_type
= GTK_SHADOW_IN
;
885 else if ( flags
& wxCONTROL_UNDETERMINED
)
886 shadow_type
= GTK_SHADOW_ETCHED_IN
;
888 GtkStateType state
= GTK_STATE_NORMAL
;
889 if ( flags
& wxCONTROL_DISABLED
)
890 state
= GTK_STATE_INSENSITIVE
;
891 if ( flags
& wxCONTROL_PRESSED
)
892 state
= GTK_STATE_ACTIVE
;
894 Don't know when to set this
895 state_type = GTK_STATE_PRELIGHT;
900 gtk_widget_get_style(button
),
907 dc
.LogicalToDeviceX(rect
.x
),
908 dc
.LogicalToDeviceY(rect
.y
),
909 rect
.width
, rect
.height