// 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
///////////////////////////////////////////////////////////////////////////////
#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
// ----------------------------------------------------------------------------
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
if ( !UseNative() )
return wxInfoBarGeneric::Create(parent, winid);
+ m_impl = new wxInfoBarGTKImpl;
+
// this control is created initially hidden
Hide();
if ( !CreateBase(parent, 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);
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)
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();
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() )
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