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