X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ed8efd46d9c8fa3bf5d10b2a6efd295a6dd71bdb..fb8d7eb7a880f1f2e32d8830f9c5e12b2536e05f:/src/gtk/infobar.cpp?ds=sidebyside diff --git a/src/gtk/infobar.cpp b/src/gtk/infobar.cpp index 604838abfc..defc0738aa 100644 --- a/src/gtk/infobar.cpp +++ b/src/gtk/infobar.cpp @@ -3,7 +3,7 @@ // Purpose: wxInfoBar implementation for GTK // Author: Vadim Zeitlin // Created: 2009-09-27 -// RCS-ID: $Id: wxhead.cpp,v 1.10 2009-06-29 10:23:04 zeitlin Exp $ +// RCS-ID: $Id$ // Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org> // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -30,9 +30,49 @@ #ifndef WX_PRECOMP #endif // WX_PRECOMP +#include "wx/vector.h" +#include "wx/stockitem.h" + #include "wx/gtk/private.h" #include "wx/gtk/private/messagetype.h" +// ---------------------------------------------------------------------------- +// local classes +// ---------------------------------------------------------------------------- + +class wxInfoBarGTKImpl +{ +public: + wxInfoBarGTKImpl() + { + m_label = NULL; + m_close = NULL; + } + + // label for the text shown in the bar + GtkWidget *m_label; + + // the default close button, NULL if not needed (m_buttons is not empty) or + // not created yet + GtkWidget *m_close; + + // information about the buttons added using AddButton() + struct Button + { + Button(GtkWidget *button_, int id_) + : button(button_), + id(id_) + { + } + + GtkWidget *button; + int id; + }; + typedef wxVector<Button> Buttons; + + Buttons m_buttons; +}; + // ---------------------------------------------------------------------------- // local functions // ---------------------------------------------------------------------------- @@ -42,8 +82,12 @@ namespace inline bool UseNative() { +#ifdef __WXGTK3__ + return true; +#else // native GtkInfoBar widget is only available in GTK+ 2.18 and later return gtk_check_version(2, 18, 0) == 0; +#endif } } // anonymous namespace @@ -75,6 +119,8 @@ bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid) if ( !UseNative() ) return wxInfoBarGeneric::Create(parent, winid); + m_impl = new wxInfoBarGTKImpl; + // this control is created initially hidden Hide(); if ( !CreateBase(parent, winid) ) @@ -86,13 +132,13 @@ bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid) g_object_ref(m_widget); // also create a label which will be used to show our message - m_label = gtk_label_new(""); - gtk_widget_show(m_label); + m_impl->m_label = gtk_label_new(""); + gtk_widget_show(m_impl->m_label); GtkWidget * const contentArea = gtk_info_bar_get_content_area(GTK_INFO_BAR(m_widget)); wxCHECK_MSG( contentArea, false, "failed to get GtkInfoBar content area" ); - gtk_container_add(GTK_CONTAINER(contentArea), m_label); + gtk_container_add(GTK_CONTAINER(contentArea), m_impl->m_label); // finish creation and connect to all the signals we're interested in m_parent->DoAddChild(this); @@ -102,7 +148,12 @@ bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid) GTKConnectWidget("response", G_CALLBACK(wxgtk_infobar_response)); GTKConnectWidget("close", G_CALLBACK(wxgtk_infobar_close)); - return false; + return true; +} + +wxInfoBar::~wxInfoBar() +{ + delete m_impl; } void wxInfoBar::ShowMessage(const wxString& msg, int flags) @@ -113,10 +164,17 @@ void wxInfoBar::ShowMessage(const wxString& msg, int flags) return; } + // if we don't have any buttons, create a standard close one to give the + // user at least some way to close the bar + if ( m_impl->m_buttons.empty() && !m_impl->m_close ) + { + m_impl->m_close = GTKAddButton(wxID_CLOSE); + } + GtkMessageType type; if ( wxGTKImpl::ConvertMessageTypeFromWX(flags, &type) ) gtk_info_bar_set_message_type(GTK_INFO_BAR(m_widget), type); - gtk_label_set_text(GTK_LABEL(m_label), wxGTK_CONV(msg)); + gtk_label_set_text(GTK_LABEL(m_impl->m_label), wxGTK_CONV(msg)); if ( !IsShown() ) Show(); @@ -124,13 +182,48 @@ void wxInfoBar::ShowMessage(const wxString& msg, int flags) UpdateParent(); } -void wxInfoBar::GTKResponse(int WXUNUSED(btnid)) +void wxInfoBar::Dismiss() { + if ( !UseNative() ) + { + wxInfoBarGeneric::Dismiss(); + return; + } + Hide(); UpdateParent(); } +void wxInfoBar::GTKResponse(int btnid) +{ + wxCommandEvent event(wxEVT_BUTTON, btnid); + event.SetEventObject(this); + + if ( !HandleWindowEvent(event) ) + Dismiss(); +} + +GtkWidget *wxInfoBar::GTKAddButton(wxWindowID btnid, const wxString& label) +{ + // as GTK+ lays out the buttons vertically, adding another button changes + // our best size (at least in vertical direction) + InvalidateBestSize(); + + GtkWidget *button = gtk_info_bar_add_button + ( + GTK_INFO_BAR(m_widget), + (label.empty() + ? GTKConvertMnemonics(wxGetStockGtkID(btnid)) + : label).utf8_str(), + btnid + ); + + wxASSERT_MSG( button, "unexpectedly failed to add button to info bar" ); + + return button; +} + void wxInfoBar::AddButton(wxWindowID btnid, const wxString& label) { if ( !UseNative() ) @@ -139,12 +232,54 @@ void wxInfoBar::AddButton(wxWindowID btnid, const wxString& label) return; } - gtk_info_bar_add_button - ( - GTK_INFO_BAR(m_widget), - label.empty() ? GTKConvertMnemonics(wxGetStockGtkID(btnid)) : label, - btnid - ); + // if we had created the default close button before, remove it now that we + // have some user-defined button + if ( m_impl->m_close ) + { + gtk_widget_destroy(m_impl->m_close); + m_impl->m_close = NULL; + } + + GtkWidget * const button = GTKAddButton(btnid, label); + if ( button ) + m_impl->m_buttons.push_back(wxInfoBarGTKImpl::Button(button, btnid)); +} + +void wxInfoBar::RemoveButton(wxWindowID btnid) +{ + if ( !UseNative() ) + { + wxInfoBarGeneric::RemoveButton(btnid); + return; + } + + // as in the generic version, look for the button starting from the end + wxInfoBarGTKImpl::Buttons& buttons = m_impl->m_buttons; + for ( wxInfoBarGTKImpl::Buttons::reverse_iterator i = buttons.rbegin(); + i != buttons.rend(); + ++i ) + { + if (i->id == btnid) + { + gtk_widget_destroy(i->button); + buttons.erase(i.base()); + + // see comment in GTKAddButton() + InvalidateBestSize(); + + return; + } + } + + wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) ); +} + +void wxInfoBar::DoApplyWidgetStyle(GtkRcStyle *style) +{ + wxInfoBarGeneric::DoApplyWidgetStyle(style); + + if ( UseNative() ) + GTKApplyStyle(m_impl->m_label, style); } #endif // wxUSE_INFOBAR