diff --git a/include/wx/renderer.h b/include/wx/renderer.h index dde8523906..3e9e67c509 100644 --- a/include/wx/renderer.h +++ b/include/wx/renderer.h @@ -412,7 +412,7 @@ wxRendererNative& wxRendererNative::GetDefault() // they are standalone functions here to protect the ABI. // ---------------------------------------------------------------------------- -#if defined(__WXMSW__) || defined(__WXMAC__) +#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK20__) #if wxABI_VERSION >= 20804 // Draw a native wxChoice diff --git a/samples/render/render.cpp b/samples/render/render.cpp index b08be85b46..f553dfa551 100644 --- a/samples/render/render.cpp +++ b/samples/render/render.cpp @@ -134,7 +134,7 @@ public: dc.DrawText(_T("using the current renderer:"), 10, 40); wxRendererNative::Get().DrawHeaderButton(this, dc, - wxRect(20, 70, 100, 60)); + wxRect(20, 70, 100, 25)); // Draw some check boxes in various states dc.SetBrush(*wxBLACK_BRUSH); @@ -148,6 +148,22 @@ public: wxRendererNative::Get().DrawCheckBox(this, dc, wxRect(60, 170, 16, 16), 0); // Checked and Disabled wxRendererNative::Get().DrawCheckBox(this, dc, wxRect(80, 170, 16, 16), wxCONTROL_CHECKED | wxCONTROL_DISABLED); + + + dc.DrawText(_T("Draw wxTextCtrl (without text)"), 10, 200); + wxRenderer_DrawTextCtrl( this, dc, wxRect(20,220,60,24), 0); + wxRenderer_DrawTextCtrl( this, dc, wxRect(120,220,60,24), wxCONTROL_CURRENT ); + + dc.DrawText(_T("Draw wxComboBox (without text)"), 10, 250); + wxRenderer_DrawComboBox( this, dc, wxRect(20,270,80,24), 0); + + dc.DrawText(_T("Draw wxChoice (without text)"), 10, 300); + wxRenderer_DrawChoice( this, dc, wxRect(20,320,80,24), 0); + + dc.DrawText(_T("Draw wxRadioButton (without text)"), 10, 350); + wxRenderer_DrawRadioButton( this, dc, wxRect(20,370,24,24), 0); + wxRenderer_DrawRadioButton( this, dc, wxRect(40,370,24,24), wxCONTROL_CHECKED ); + } diff --git a/src/gtk/renderer.cpp b/src/gtk/renderer.cpp index bf7f2911af..a593464879 100644 --- a/src/gtk/renderer.cpp +++ b/src/gtk/renderer.cpp @@ -94,7 +94,7 @@ public: virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win); -private: +// private: // FIXME: shouldn't we destroy these windows somewhere? // used by DrawPushButton and DrawDropArrow @@ -106,8 +106,17 @@ private: // used by DrawCheckBox() static GtkWidget *GetCheckButtonWidget(); + // used by DrawRadioButton() + static GtkWidget *GetRadioButtonWidget(); + // Used by DrawHeaderButton static GtkWidget *GetHeaderButtonWidget(); + + // Used by DrawTextCtrl + static GtkWidget *GetTextEntryWidget(); + + // Used by DrawComboBox + static GtkWidget *GetComboBoxWidget(); }; GdkWindow* wxGetGdkWindowForDC(wxWindow* win, wxDC& dc) @@ -167,6 +176,42 @@ wxRendererGTK::GetButtonWidget() return s_button; } +GtkWidget * +wxRendererGTK::GetTextEntryWidget() +{ + static GtkWidget *s_button = NULL; + static GtkWidget *s_window = NULL; + + if ( !s_button ) + { + s_window = gtk_window_new( GTK_WINDOW_POPUP ); + gtk_widget_realize( s_window ); + s_button = gtk_entry_new(); + gtk_container_add( GTK_CONTAINER(s_window), s_button ); + gtk_widget_realize( s_button ); + } + + return s_button; +} + +GtkWidget * +wxRendererGTK::GetComboBoxWidget() +{ + static GtkWidget *s_button = NULL; + static GtkWidget *s_window = NULL; + + if ( !s_button ) + { + s_window = gtk_window_new( GTK_WINDOW_POPUP ); + gtk_widget_realize( s_window ); + s_button = gtk_combo_box_new(); + gtk_container_add( GTK_CONTAINER(s_window), s_button ); + gtk_widget_realize( s_button ); + } + + return s_button; +} + GtkWidget * wxRendererGTK::GetCheckButtonWidget() { @@ -185,6 +230,24 @@ wxRendererGTK::GetCheckButtonWidget() return s_button; } +GtkWidget * +wxRendererGTK::GetRadioButtonWidget() +{ + static GtkWidget *s_button = NULL; + static GtkWidget *s_window = NULL; + + if ( !s_button ) + { + s_window = gtk_window_new( GTK_WINDOW_POPUP ); + gtk_widget_realize( s_window ); + s_button = gtk_radio_button_new(NULL); + gtk_container_add( GTK_CONTAINER(s_window), s_button ); + gtk_widget_realize( s_button ); + } + + return s_button; +} + GtkWidget * wxRendererGTK::GetTreeWidget() { @@ -525,7 +588,10 @@ wxRendererGTK::DrawPushButton(wxWindow* win, NULL, button, "button", - rect.x, rect.y, rect.width, rect.height + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, + rect.height ); } @@ -575,3 +641,162 @@ wxRendererGTK::DrawItemSelectionRect(wxWindow *win, rect.height ); } } + + +// ---------------------------------------------------------------------------- +// Other renderer functions to be merged in to wxRenderer class in 2.9, but +// they are standalone functions here to protect the ABI. +// ---------------------------------------------------------------------------- + +// Uses the theme to draw the border and fill for something like a wxTextCtrl +void wxRenderer_DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + GtkWidget *entry = wxRendererGTK::GetTextEntryWidget(); + + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); + + GtkStateType state = GTK_STATE_NORMAL; + if ( flags & wxCONTROL_DISABLED ) + state = GTK_STATE_INSENSITIVE; + + if (flags & wxCONTROL_CURRENT ) + GTK_WIDGET_SET_FLAGS( entry, GTK_HAS_FOCUS ); + else + GTK_WIDGET_UNSET_FLAGS( entry, GTK_HAS_FOCUS ); + + gtk_paint_shadow + ( + entry->style, + gdk_window, + state, + GTK_SHADOW_OUT, + NULL, + entry, + "entry", + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, + rect.height + ); +} + +// Draw the equivallent of a wxComboBox +void wxRenderer_DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + GtkWidget *combo = wxRendererGTK::GetComboBoxWidget(); + + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); + + GtkStateType state = GTK_STATE_NORMAL; + if ( flags & wxCONTROL_DISABLED ) + state = GTK_STATE_INSENSITIVE; + + if (flags & wxCONTROL_CURRENT ) + GTK_WIDGET_SET_FLAGS( combo, GTK_HAS_FOCUS ); + else + GTK_WIDGET_UNSET_FLAGS( combo, GTK_HAS_FOCUS ); + + gtk_paint_shadow + ( + combo->style, + gdk_window, + state, + GTK_SHADOW_OUT, + NULL, + combo, + "combobox", + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, + rect.height + ); + + wxRect r = rect; + int extent = rect.height / 2; + r.x += rect.width - extent - extent/2; + r.y += extent/2; + r.width = extent; + r.height = extent; + + gtk_paint_arrow + ( + combo->style, + gdk_window, + state, + GTK_SHADOW_OUT, + NULL, + combo, + "arrow", + GTK_ARROW_DOWN, + TRUE, + dc.LogicalToDeviceX(r.x), + dc.LogicalToDeviceY(r.y), + r.width, + r.height + ); + + r = rect; + r.x += rect.width - 2*extent; + r.width = 2; + + gtk_paint_box + ( + combo->style, + gdk_window, + state, + GTK_SHADOW_ETCHED_OUT, + NULL, + combo, + "vseparator", + dc.LogicalToDeviceX(r.x), + dc.LogicalToDeviceY(r.y+1), + r.width, + r.height-2 + ); +} + + +void wxRenderer_DrawChoice(wxWindow* win, wxDC& dc, + const wxRect& rect, int flags) +{ + wxRenderer_DrawComboBox( win, dc, rect, flags ); +} + + +// Draw a themed radio button +void wxRenderer_DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) +{ + GtkWidget *button = wxRendererGTK::GetRadioButtonWidget(); + + GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); + + GtkShadowType shadow_type = GTK_SHADOW_OUT; + if ( flags & wxCONTROL_CHECKED ) + shadow_type = GTK_SHADOW_IN; + else if ( flags & wxCONTROL_UNDETERMINED ) + shadow_type = GTK_SHADOW_ETCHED_IN; + + GtkStateType state = GTK_STATE_NORMAL; + if ( flags & wxCONTROL_DISABLED ) + state = GTK_STATE_INSENSITIVE; + if ( flags & wxCONTROL_PRESSED ) + state = GTK_STATE_ACTIVE; +/* + Don't know when to set this + state_type = GTK_STATE_PRELIGHT; +*/ + + gtk_paint_option + ( + button->style, + gdk_window, + state, + shadow_type, + NULL, + button, + "radiobutton", + dc.LogicalToDeviceX(rect.x), + dc.LogicalToDeviceY(rect.y), + rect.width, rect.height + ); +}