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