X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/593ac8df8eea35e4e0402a7ab0fbba13440b20bf..7d6a4d96961eac84d05db8bb24c64d39003f6e54:/src/gtk/button.cpp?ds=sidebyside diff --git a/src/gtk/button.cpp b/src/gtk/button.cpp index 12e0807e50..6e496d75bb 100644 --- a/src/gtk/button.cpp +++ b/src/gtk/button.cpp @@ -18,85 +18,60 @@ #include "wx/stockitem.h" +#include #include "wx/gtk/private.h" +#include "wx/gtk/private/gtk2-compat.h" +#include "wx/gtk/private/list.h" -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxButton; - -//----------------------------------------------------------------------------- -// data -//----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// GTK callbacks +// ---------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; - -//----------------------------------------------------------------------------- -// "clicked" -//----------------------------------------------------------------------------- +extern "C" +{ -extern "C" { -static void gtk_button_clicked_callback( GtkWidget *WXUNUSED(widget), wxButton *button ) +static void +wxgtk_button_clicked_callback(GtkWidget *WXUNUSED(widget), wxButton *button) { - if (!button->m_hasVMT) return; - if (g_blockEventsOnDrag) return; + if ( button->GTKShouldIgnoreEvent() ) + return; wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, button->GetId()); event.SetEventObject(button); - button->GetEventHandler()->ProcessEvent(event); -} + button->HandleWindowEvent(event); } //----------------------------------------------------------------------------- // "style_set" from m_widget //----------------------------------------------------------------------------- -static gint -gtk_button_style_set_callback( GtkWidget *m_widget, GtkStyle *WXUNUSED(style), wxButton *win ) +static void +wxgtk_button_style_set_callback(GtkWidget* widget, GtkStyle*, wxButton* win) { - int left_border = 0; - int right_border = 0; - int top_border = 0; - int bottom_border = 0; - /* the default button has a border around it */ - if (GTK_WIDGET_CAN_DEFAULT(m_widget)) + wxWindow* parent = win->GetParent(); + if (parent && parent->m_wxwindow && gtk_widget_get_can_default(widget)) { - GtkBorder *default_border = NULL; - gtk_widget_style_get( m_widget, "default_border", &default_border, NULL ); - if (default_border) + GtkBorder* border = NULL; + gtk_widget_style_get(widget, "default_border", &border, NULL); + if (border) { - left_border += default_border->left; - right_border += default_border->right; - top_border += default_border->top; - bottom_border += default_border->bottom; - gtk_border_free( default_border ); + win->MoveWindow( + win->m_x - border->left, + win->m_y - border->top, + win->m_width + border->left + border->right, + win->m_height + border->top + border->bottom); + gtk_border_free(border); } - win->MoveWindow( - win->m_x - left_border, - win->m_y - top_border, - win->m_width + left_border + right_border, - win->m_height + top_border + bottom_border); } - - return FALSE; } +} // extern "C" + //----------------------------------------------------------------------------- // wxButton //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxButton,wxControl) - -wxButton::wxButton() -{ -} - -wxButton::~wxButton() -{ -} - bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString &label, @@ -113,7 +88,25 @@ bool wxButton::Create(wxWindow *parent, return false; } - m_widget = gtk_button_new_with_mnemonic(""); + // create either a standard button with text label (which may still contain + // an image under GTK+ 2.6+) or a bitmap-only button if we don't have any + // label + const bool + useLabel = !(style & wxBU_NOTEXT) && (!label.empty() || wxIsStockID(id)); + if ( useLabel ) + { + m_widget = gtk_button_new_with_mnemonic(""); + } + else // no label, suppose we will have a bitmap + { + m_widget = gtk_button_new(); + + GtkWidget *image = gtk_image_new(); + gtk_widget_show(image); + gtk_container_add(GTK_CONTAINER(m_widget), image); + } + + g_object_ref(m_widget); float x_alignment = 0.5; if (HasFlag(wxBU_LEFT)) @@ -129,17 +122,18 @@ bool wxButton::Create(wxWindow *parent, gtk_button_set_alignment(GTK_BUTTON(m_widget), x_alignment, y_alignment); - SetLabel(label); + if ( useLabel ) + SetLabel(label); if (style & wxNO_BORDER) gtk_button_set_relief( GTK_BUTTON(m_widget), GTK_RELIEF_NONE ); g_signal_connect_after (m_widget, "clicked", - G_CALLBACK (gtk_button_clicked_callback), + G_CALLBACK (wxgtk_button_clicked_callback), this); g_signal_connect_after (m_widget, "style_set", - G_CALLBACK (gtk_button_style_set_callback), + G_CALLBACK (wxgtk_button_style_set_callback), this); m_parent->DoAddChild( this ); @@ -154,11 +148,11 @@ wxWindow *wxButton::SetDefault() { wxWindow *oldDefault = wxButtonBase::SetDefault(); - GTK_WIDGET_SET_FLAGS( m_widget, GTK_CAN_DEFAULT ); + gtk_widget_set_can_default(m_widget, TRUE); gtk_widget_grab_default( m_widget ); // resize for default border - gtk_button_style_set_callback( m_widget, NULL, this ); + wxgtk_button_style_set_callback( m_widget, NULL, this ); return oldDefault; } @@ -182,7 +176,12 @@ wxSize wxButtonBase::GetDefaultSize() gtk_container_add(GTK_CONTAINER(box), btn); gtk_container_add(GTK_CONTAINER(wnd), box); GtkRequisition req; +#ifdef __WXGTK3__ + gtk_widget_get_preferred_height(btn, NULL, &req.height); + gtk_widget_get_preferred_width_for_height(btn, req.height, NULL, &req.width); +#else gtk_widget_size_request(btn, &req); +#endif gint minwidth, minheight; gtk_widget_style_get(box, @@ -207,9 +206,11 @@ void wxButton::SetLabel( const wxString &lbl ) if (label.empty() && wxIsStockID(m_windowId)) label = wxGetStockLabel(m_windowId); - wxControl::SetLabel(label); + wxAnyButton::SetLabel(label); - const wxString labelGTK = GTKConvertMnemonics(label); + // don't use label if it was explicitly disabled + if ( HasFlag(wxBU_NOTEXT) ) + return; if (wxIsStockID(m_windowId) && wxIsStockLabel(m_windowId, label)) { @@ -222,59 +223,107 @@ void wxButton::SetLabel( const wxString &lbl ) } } + // this call is necessary if the button had been initially created without + // a (text) label -- then we didn't use gtk_button_new_with_mnemonic() and + // so "use-underline" GtkButton property remained unset + gtk_button_set_use_underline(GTK_BUTTON(m_widget), TRUE); + const wxString labelGTK = GTKConvertMnemonics(label); gtk_button_set_label(GTK_BUTTON(m_widget), wxGTK_CONV(labelGTK)); gtk_button_set_use_stock(GTK_BUTTON(m_widget), FALSE); - ApplyWidgetStyle( false ); + GTKApplyWidgetStyle( false ); } -bool wxButton::Enable( bool enable ) +#if wxUSE_MARKUP +bool wxButton::DoSetLabelMarkup(const wxString& markup) { - if ( !wxControl::Enable( enable ) ) + wxCHECK_MSG( m_widget != NULL, false, "invalid button" ); + + const wxString stripped = RemoveMarkup(markup); + if ( stripped.empty() && !markup.empty() ) return false; - gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable); + wxControl::SetLabel(stripped); + + GtkLabel * const label = GTKGetLabel(); + wxCHECK_MSG( label, false, "no label in this button?" ); + + GTKSetLabelWithMarkupForLabel(label, markup); return true; } -GdkWindow *wxButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const +GtkLabel *wxButton::GTKGetLabel() const { - return GTK_BUTTON(m_widget)->event_window; + GtkWidget* child = gtk_bin_get_child(GTK_BIN(m_widget)); + if ( GTK_IS_ALIGNMENT(child) ) + { + GtkWidget* box = gtk_bin_get_child(GTK_BIN(child)); + GtkLabel* label = NULL; + wxGtkList list(gtk_container_get_children(GTK_CONTAINER(box))); + for (GList* item = list; item; item = item->next) + { + if (GTK_IS_LABEL(item->data)) + label = GTK_LABEL(item->data); + } + + return label; + } + + return GTK_LABEL(child); } +#endif // wxUSE_MARKUP void wxButton::DoApplyWidgetStyle(GtkRcStyle *style) { - gtk_widget_modify_style(m_widget, style); - gtk_widget_modify_style(GTK_BIN(m_widget)->child, style); + GTKApplyStyle(m_widget, style); + GtkWidget* child = gtk_bin_get_child(GTK_BIN(m_widget)); + GTKApplyStyle(child, style); + + // for buttons with images, the path to the label is (at least in 2.12) + // GtkButton -> GtkAlignment -> GtkHBox -> GtkLabel + if ( GTK_IS_ALIGNMENT(child) ) + { + GtkWidget* box = gtk_bin_get_child(GTK_BIN(child)); + if ( GTK_IS_BOX(box) ) + { + wxGtkList list(gtk_container_get_children(GTK_CONTAINER(box))); + for (GList* item = list; item; item = item->next) + { + GTKApplyStyle(GTK_WIDGET(item->data), style); + } + } + } } wxSize wxButton::DoGetBestSize() const { // the default button in wxGTK is bigger than the other ones because of an // extra border around it, but we don't want to take it into account in - // our size calculations (otherwsie the result is visually ugly), so + // our size calculations (otherwise the result is visually ugly), so // always return the size of non default button from here - const bool isDefault = GTK_WIDGET_HAS_DEFAULT(m_widget); + const bool isDefault = gtk_widget_has_default(m_widget) != 0; if ( isDefault ) { // temporarily unset default flag - GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_DEFAULT ); + gtk_widget_set_can_default(m_widget, FALSE); } - wxSize ret( wxControl::DoGetBestSize() ); + wxSize ret( wxAnyButton::DoGetBestSize() ); if ( isDefault ) { // set it back again - GTK_WIDGET_SET_FLAGS( m_widget, GTK_CAN_DEFAULT ); + gtk_widget_set_can_default(m_widget, TRUE); } if (!HasFlag(wxBU_EXACTFIT)) { wxSize defaultSize = GetDefaultSize(); - if (ret.x < defaultSize.x) ret.x = defaultSize.x; - if (ret.y < defaultSize.y) ret.y = defaultSize.y; + if (ret.x < defaultSize.x) + ret.x = defaultSize.x; + if (ret.y < defaultSize.y) + ret.y = defaultSize.y; } CacheBestSize(ret);