]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/infobar.cpp
Make wxMSW stack walking methods work with Unicode identifiers.
[wxWidgets.git] / src / gtk / infobar.cpp
CommitLineData
ed8efd46
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/infobar.cpp
3// Purpose: wxInfoBar implementation for GTK
4// Author: Vadim Zeitlin
5// Created: 2009-09-27
ed8efd46
VZ
6// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
18// for compilers that support precompilation, includes "wx.h".
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#include "wx/infobar.h"
26
27#if wxUSE_INFOBAR && defined(wxHAS_NATIVE_INFOBAR)
28
29#ifndef WX_PRECOMP
30#endif // WX_PRECOMP
31
e6b2aae1 32#include "wx/vector.h"
ff7485d8 33#include "wx/stockitem.h"
e6b2aae1 34
ed8efd46
VZ
35#include "wx/gtk/private.h"
36#include "wx/gtk/private/messagetype.h"
37
e6b2aae1
VZ
38// ----------------------------------------------------------------------------
39// local classes
40// ----------------------------------------------------------------------------
41
42class wxInfoBarGTKImpl
43{
44public:
45 wxInfoBarGTKImpl()
46 {
47 m_label = NULL;
6a3f8b4f 48 m_close = NULL;
e6b2aae1
VZ
49 }
50
6a3f8b4f 51 // label for the text shown in the bar
e6b2aae1
VZ
52 GtkWidget *m_label;
53
6a3f8b4f
VZ
54 // the default close button, NULL if not needed (m_buttons is not empty) or
55 // not created yet
56 GtkWidget *m_close;
57
58 // information about the buttons added using AddButton()
e6b2aae1
VZ
59 struct Button
60 {
61 Button(GtkWidget *button_, int id_)
62 : button(button_),
63 id(id_)
64 {
65 }
66
67 GtkWidget *button;
68 int id;
69 };
70 typedef wxVector<Button> Buttons;
71
72 Buttons m_buttons;
73};
74
ed8efd46
VZ
75// ----------------------------------------------------------------------------
76// local functions
77// ----------------------------------------------------------------------------
78
79namespace
80{
81
82inline bool UseNative()
83{
9dc44eff
PC
84#ifdef __WXGTK3__
85 return true;
86#else
ed8efd46
VZ
87 // native GtkInfoBar widget is only available in GTK+ 2.18 and later
88 return gtk_check_version(2, 18, 0) == 0;
9dc44eff 89#endif
ed8efd46
VZ
90}
91
92} // anonymous namespace
93
94extern "C"
95{
96
97static void wxgtk_infobar_response(GtkInfoBar * WXUNUSED(infobar),
98 gint btnid,
99 wxInfoBar *win)
100{
101 win->GTKResponse(btnid);
102}
103
104static void wxgtk_infobar_close(GtkInfoBar * WXUNUSED(infobar),
105 wxInfoBar *win)
106{
107 win->GTKResponse(wxID_CANCEL);
108}
109
110} // extern "C" section with GTK+ callbacks
111
112// ============================================================================
113// wxInfoBar implementation
114// ============================================================================
115
116bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid)
117{
118 if ( !UseNative() )
119 return wxInfoBarGeneric::Create(parent, winid);
120
e6b2aae1
VZ
121 m_impl = new wxInfoBarGTKImpl;
122
ed8efd46
VZ
123 // this control is created initially hidden
124 Hide();
125 if ( !CreateBase(parent, winid) )
126 return false;
127
128 // create the info bar widget itself
129 m_widget = gtk_info_bar_new();
130 wxCHECK_MSG( m_widget, false, "failed to create GtkInfoBar" );
131 g_object_ref(m_widget);
132
133 // also create a label which will be used to show our message
e6b2aae1
VZ
134 m_impl->m_label = gtk_label_new("");
135 gtk_widget_show(m_impl->m_label);
ed8efd46
VZ
136
137 GtkWidget * const
138 contentArea = gtk_info_bar_get_content_area(GTK_INFO_BAR(m_widget));
139 wxCHECK_MSG( contentArea, false, "failed to get GtkInfoBar content area" );
e6b2aae1 140 gtk_container_add(GTK_CONTAINER(contentArea), m_impl->m_label);
ed8efd46
VZ
141
142 // finish creation and connect to all the signals we're interested in
143 m_parent->DoAddChild(this);
144
145 PostCreation(wxDefaultSize);
146
147 GTKConnectWidget("response", G_CALLBACK(wxgtk_infobar_response));
148 GTKConnectWidget("close", G_CALLBACK(wxgtk_infobar_close));
149
ff7485d8 150 return true;
ed8efd46
VZ
151}
152
e6b2aae1
VZ
153wxInfoBar::~wxInfoBar()
154{
155 delete m_impl;
156}
157
ed8efd46
VZ
158void wxInfoBar::ShowMessage(const wxString& msg, int flags)
159{
160 if ( !UseNative() )
161 {
162 wxInfoBarGeneric::ShowMessage(msg, flags);
163 return;
164 }
165
6a3f8b4f
VZ
166 // if we don't have any buttons, create a standard close one to give the
167 // user at least some way to close the bar
168 if ( m_impl->m_buttons.empty() && !m_impl->m_close )
169 {
170 m_impl->m_close = GTKAddButton(wxID_CLOSE);
171 }
172
ed8efd46
VZ
173 GtkMessageType type;
174 if ( wxGTKImpl::ConvertMessageTypeFromWX(flags, &type) )
175 gtk_info_bar_set_message_type(GTK_INFO_BAR(m_widget), type);
e6b2aae1 176 gtk_label_set_text(GTK_LABEL(m_impl->m_label), wxGTK_CONV(msg));
ed8efd46
VZ
177
178 if ( !IsShown() )
179 Show();
180
181 UpdateParent();
182}
183
0b1add25
VZ
184void wxInfoBar::Dismiss()
185{
186 if ( !UseNative() )
187 {
188 wxInfoBarGeneric::Dismiss();
189 return;
190 }
191
192 Hide();
193
194 UpdateParent();
195}
196
c0945eb2 197void wxInfoBar::GTKResponse(int btnid)
ed8efd46 198{
ce7fe42e 199 wxCommandEvent event(wxEVT_BUTTON, btnid);
c0945eb2 200 event.SetEventObject(this);
ed8efd46 201
c0945eb2 202 if ( !HandleWindowEvent(event) )
0b1add25 203 Dismiss();
ed8efd46
VZ
204}
205
6a3f8b4f 206GtkWidget *wxInfoBar::GTKAddButton(wxWindowID btnid, const wxString& label)
ed8efd46 207{
6a3f8b4f
VZ
208 // as GTK+ lays out the buttons vertically, adding another button changes
209 // our best size (at least in vertical direction)
210 InvalidateBestSize();
ed8efd46 211
e6b2aae1
VZ
212 GtkWidget *button = gtk_info_bar_add_button
213 (
214 GTK_INFO_BAR(m_widget),
c7193f28 215 (label.empty()
e6b2aae1 216 ? GTKConvertMnemonics(wxGetStockGtkID(btnid))
c7193f28 217 : label).utf8_str(),
e6b2aae1
VZ
218 btnid
219 );
e6b2aae1 220
6a3f8b4f
VZ
221 wxASSERT_MSG( button, "unexpectedly failed to add button to info bar" );
222
223 return button;
224}
225
226void wxInfoBar::AddButton(wxWindowID btnid, const wxString& label)
227{
228 if ( !UseNative() )
229 {
230 wxInfoBarGeneric::AddButton(btnid, label);
231 return;
232 }
233
234 // if we had created the default close button before, remove it now that we
235 // have some user-defined button
236 if ( m_impl->m_close )
237 {
238 gtk_widget_destroy(m_impl->m_close);
239 m_impl->m_close = NULL;
240 }
241
242 GtkWidget * const button = GTKAddButton(btnid, label);
243 if ( button )
244 m_impl->m_buttons.push_back(wxInfoBarGTKImpl::Button(button, btnid));
e6b2aae1
VZ
245}
246
247void wxInfoBar::RemoveButton(wxWindowID btnid)
248{
249 if ( !UseNative() )
250 {
251 wxInfoBarGeneric::RemoveButton(btnid);
252 return;
253 }
254
255 // as in the generic version, look for the button starting from the end
256 wxInfoBarGTKImpl::Buttons& buttons = m_impl->m_buttons;
257 for ( wxInfoBarGTKImpl::Buttons::reverse_iterator i = buttons.rbegin();
258 i != buttons.rend();
259 ++i )
260 {
ff7485d8
PC
261 if (i->id == btnid)
262 {
263 gtk_widget_destroy(i->button);
264 buttons.erase(i.base());
6a3f8b4f 265
ff7485d8
PC
266 // see comment in GTKAddButton()
267 InvalidateBestSize();
6a3f8b4f 268
ff7485d8
PC
269 return;
270 }
e6b2aae1
VZ
271 }
272
273 wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) );
ed8efd46
VZ
274}
275
4026acf1
VZ
276void wxInfoBar::DoApplyWidgetStyle(GtkRcStyle *style)
277{
278 wxInfoBarGeneric::DoApplyWidgetStyle(style);
279
280 if ( UseNative() )
9dc44eff 281 GTKApplyStyle(m_impl->m_label, style);
4026acf1
VZ
282}
283
ed8efd46 284#endif // wxUSE_INFOBAR