From c37dd6dad7f53b8f5f4c4a8d6434c2851cd2b9e4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 16 Jun 2009 19:31:50 +0000 Subject: [PATCH] implement wxGTK wxBitmapButton in terms of wxButton git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61081 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/bmpbuttn.h | 4 +- include/wx/gtk/bmpbuttn.h | 47 ++------ src/gtk/bmpbuttn.cpp | 246 -------------------------------------- src/gtk/button.cpp | 62 ++++++++-- 4 files changed, 68 insertions(+), 291 deletions(-) diff --git a/include/wx/bmpbuttn.h b/include/wx/bmpbuttn.h index 2591933610..e33b1831af 100644 --- a/include/wx/bmpbuttn.h +++ b/include/wx/bmpbuttn.h @@ -18,10 +18,10 @@ #include "wx/button.h" -// FIXME: right now only wxMSW implements bitmap support in wxButton +// FIXME: right now only wxMSW and wxGTK implement bitmap support in wxButton // itself, this shouldn't be used for the other platforms neither // when all of them do it -#ifdef __WXMSW__ +#if defined(__WXMSW__) || defined(__WXGTK__) #define wxHAS_BUTTON_BITMAP #endif diff --git a/include/wx/gtk/bmpbuttn.h b/include/wx/gtk/bmpbuttn.h index a8a396b8c5..47ee62fc2b 100644 --- a/include/wx/gtk/bmpbuttn.h +++ b/include/wx/gtk/bmpbuttn.h @@ -14,22 +14,20 @@ // wxBitmapButton // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_CORE wxBitmapButton: public wxBitmapButtonBase +class WXDLLIMPEXP_CORE wxBitmapButton : public wxBitmapButtonBase { public: - wxBitmapButton() { Init(); } + wxBitmapButton() { } wxBitmapButton(wxWindow *parent, wxWindowID id, const wxBitmap& bitmap, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = wxBU_AUTODRAW, + long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxButtonNameStr) { - Init(); - Create(parent, id, bitmap, pos, size, style, validator, name); } @@ -38,40 +36,21 @@ public: const wxBitmap& bitmap, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = wxBU_AUTODRAW, + long style = 0, const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxButtonNameStr); - - void SetLabel( const wxString &label ); - virtual void SetLabel( const wxBitmap& bitmap ) { SetBitmapLabel(bitmap); } - - virtual bool Enable(bool enable = true); - - // implementation - // -------------- - - void GTKMouseEnters(); - void GTKMouseLeaves(); - void GTKPressed(); - void GTKReleased(); - -protected: - virtual void OnSetBitmap(); - virtual wxSize DoGetBestSize() const; - void DoApplyWidgetStyle(GtkRcStyle *style); - - void Init(); + const wxString& name = wxButtonNameStr) + { + if ( !wxBitmapButtonBase::Create(parent, id, "", + pos, size, style, + validator, name) ) + return false; -private: - void OnFocusChange(wxFocusEvent& event); + SetBitmapLabel(bitmap); - // true iff mouse hovers over the button - bool m_mouseHovers; - // true iff the button is in pressed state - bool m_isPressed; + return true; + } DECLARE_DYNAMIC_CLASS(wxBitmapButton) - DECLARE_EVENT_TABLE() }; #endif // _WX_GTK_BMPBUTTON_H_ diff --git a/src/gtk/bmpbuttn.cpp b/src/gtk/bmpbuttn.cpp index c6b94b5699..5dcd049394 100644 --- a/src/gtk/bmpbuttn.cpp +++ b/src/gtk/bmpbuttn.cpp @@ -14,252 +14,6 @@ #include "wx/bmpbuttn.h" -#include - -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxBitmapButton; - -//----------------------------------------------------------------------------- -// data -//----------------------------------------------------------------------------- - -extern bool g_blockEventsOnDrag; - -//----------------------------------------------------------------------------- -// "clicked" -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_bmpbutton_clicked_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button ) -{ - if (!button->m_hasVMT) return; - if (g_blockEventsOnDrag) return; - - wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, button->GetId()); - event.SetEventObject(button); - button->HandleWindowEvent(event); -} -} - -//----------------------------------------------------------------------------- -// "enter" -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_bmpbutton_enter_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button ) -{ - if (!button->m_hasVMT) return; - if (g_blockEventsOnDrag) return; - - button->GTKMouseEnters(); -} -} - -//----------------------------------------------------------------------------- -// "leave" -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_bmpbutton_leave_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button ) -{ - if (!button->m_hasVMT) return; - if (g_blockEventsOnDrag) return; - - button->GTKMouseLeaves(); -} -} - -//----------------------------------------------------------------------------- -// "pressed" -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_bmpbutton_press_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button ) -{ - if (!button->m_hasVMT) return; - if (g_blockEventsOnDrag) return; - - button->GTKPressed(); -} -} - -//----------------------------------------------------------------------------- -// "released" -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_bmpbutton_release_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button ) -{ - if (!button->m_hasVMT) return; - if (g_blockEventsOnDrag) return; - - button->GTKReleased(); -} -} - -//----------------------------------------------------------------------------- -// wxBitmapButton -//----------------------------------------------------------------------------- - IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton,wxButton) -BEGIN_EVENT_TABLE(wxBitmapButton, wxButton) - EVT_SET_FOCUS(wxBitmapButton::OnFocusChange) - EVT_KILL_FOCUS(wxBitmapButton::OnFocusChange) -END_EVENT_TABLE() - - -void wxBitmapButton::Init() -{ - m_mouseHovers = - m_isPressed = false; -} - -bool wxBitmapButton::Create( wxWindow *parent, - wxWindowID id, - const wxBitmap& bitmap, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator& validator, - const wxString &name ) -{ - if (!PreCreation( parent, pos, size ) || - !CreateBase( parent, id, pos, size, style, validator, name )) - { - wxFAIL_MSG( wxT("wxBitmapButton creation failed") ); - return false; - } - - m_bitmaps[State_Normal] = bitmap; - - m_widget = gtk_button_new(); - g_object_ref(m_widget); - - if (style & wxNO_BORDER) - gtk_button_set_relief( GTK_BUTTON(m_widget), GTK_RELIEF_NONE ); - - if (bitmap.IsOk()) - { - OnSetBitmap(); - } - - g_signal_connect_after (m_widget, "clicked", - G_CALLBACK (gtk_bmpbutton_clicked_callback), - this); - - g_signal_connect (m_widget, "enter", - G_CALLBACK (gtk_bmpbutton_enter_callback), this); - g_signal_connect (m_widget, "leave", - G_CALLBACK (gtk_bmpbutton_leave_callback), this); - g_signal_connect (m_widget, "pressed", - G_CALLBACK (gtk_bmpbutton_press_callback), this); - g_signal_connect (m_widget, "released", - G_CALLBACK (gtk_bmpbutton_release_callback), this); - - m_parent->DoAddChild( this ); - - PostCreation(size); - - return true; -} - -void wxBitmapButton::SetLabel( const wxString &label ) -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid button") ); - - wxControl::SetLabel( label ); -} - -void wxBitmapButton::DoApplyWidgetStyle(GtkRcStyle *style) -{ - if (!GTK_BIN(m_widget)->child) - return; - - wxButton::DoApplyWidgetStyle(style); -} - -void wxBitmapButton::OnSetBitmap() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid bitmap button") ); - - InvalidateBestSize(); - - wxBitmap the_one; - if (!IsThisEnabled()) - the_one = GetBitmapDisabled(); - else if (m_isPressed) - the_one = GetBitmapPressed(); - else if (m_mouseHovers) - the_one = GetBitmapHover(); - else if (HasFocus()) - the_one = GetBitmapFocus(); - - if (!the_one.IsOk()) - { - the_one = GetBitmapLabel(); - if (!the_one.IsOk()) - return; - } - - GtkWidget* image = GTK_BIN(m_widget)->child; - if (image == NULL) - { - image = gtk_image_new(); - gtk_widget_show(image); - gtk_container_add(GTK_CONTAINER(m_widget), image); - } - // always use pixbuf, because pixmap mask does not - // work with disabled images in some themes - gtk_image_set_from_pixbuf(GTK_IMAGE(image), the_one.GetPixbuf()); -} - -wxSize wxBitmapButton::DoGetBestSize() const -{ - return wxControl::DoGetBestSize(); -} - -bool wxBitmapButton::Enable( bool enable ) -{ - if ( !wxWindow::Enable(enable) ) - return false; - - OnSetBitmap(); - - return true; -} - -void wxBitmapButton::GTKMouseEnters() -{ - m_mouseHovers = true; - OnSetBitmap(); -} - -void wxBitmapButton::GTKMouseLeaves() -{ - m_mouseHovers = false; - OnSetBitmap(); -} - -void wxBitmapButton::GTKPressed() -{ - m_isPressed = true; - OnSetBitmap(); -} - -void wxBitmapButton::GTKReleased() -{ - m_isPressed = false; - OnSetBitmap(); -} - -void wxBitmapButton::OnFocusChange(wxFocusEvent& event) -{ - event.Skip(); - OnSetBitmap(); -} - #endif // wxUSE_BMPBUTTON diff --git a/src/gtk/button.cpp b/src/gtk/button.cpp index 0b7a033626..198a46a72d 100644 --- a/src/gtk/button.cpp +++ b/src/gtk/button.cpp @@ -123,7 +123,23 @@ 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 = !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; @@ -140,7 +156,8 @@ 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 ); @@ -392,15 +409,35 @@ void wxButton::GTKDoShowBitmap(const wxBitmap& bitmap) { wxASSERT_MSG( bitmap.IsOk(), "invalid bitmap" ); -#ifdef __WXGTK26__ - if ( !gtk_check_version(2,6,0) ) + GtkWidget *image; + if ( GetLabel().empty() ) { - GtkWidget *image = gtk_button_get_image(GTK_BUTTON(m_widget)); - wxCHECK_RET( image, "must have image widget" ); - - gtk_image_set_from_pixbuf(GTK_IMAGE(image), bitmap.GetPixbuf()); + image = GTK_BIN(m_widget)->child; } + else // have both label and bitmap + { +#ifdef __WXGTK26__ + if ( !gtk_check_version(2,6,0) ) + { + image = gtk_button_get_image(GTK_BUTTON(m_widget)); + } + else #endif // __WXGTK26__ + { + // buttons with both label and bitmap are only supported with GTK+ + // 2.6 so far + // + // it shouldn't be difficult to implement them ourselves for the + // previous GTK+ versions by stuffing a container with a label and + // an image inside GtkButton but there doesn't seem to be much + // point in doing this for ancient GTK+ versions + return; + } + } + + wxCHECK_RET( image && GTK_IS_IMAGE(image), "must have image widget" ); + + gtk_image_set_from_pixbuf(GTK_IMAGE(image), bitmap.GetPixbuf()); } wxBitmap wxButton::DoGetBitmap(State which) const @@ -413,10 +450,17 @@ void wxButton::DoSetBitmap(const wxBitmap& bitmap, State which) switch ( which ) { case State_Normal: + if ( GetLabel().empty() ) + { + // we only have the bitmap in this button, never remove it but + // do invalidate the best size when the bitmap (and presumably + // its size) changes + InvalidateBestSize(); + } #ifdef __WXGTK26__ // normal image is special: setting it enables images for the button and // resetting it to nothing disables all of them - if ( !gtk_check_version(2,6,0) ) + else if ( !gtk_check_version(2,6,0) ) { GtkWidget *image = gtk_button_get_image(GTK_BUTTON(m_widget)); if ( image && !bitmap.IsOk() ) -- 2.45.2