]> git.saurik.com Git - wxWidgets.git/blame - src/generic/infobar.cpp
Add wxApp::GTKIsUsingGlobalMenu() helper to wxGTK.
[wxWidgets.git] / src / generic / infobar.cpp
CommitLineData
a92b5dfe
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/generic/infobar.cpp
3// Purpose: generic wxInfoBar implementation
4// Author: Vadim Zeitlin
5// Created: 2009-07-28
65391c8f 6// RCS-ID: $Id$
a92b5dfe
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#if wxUSE_INFOBAR
27
65391c8f
PC
28#include "wx/infobar.h"
29
a92b5dfe 30#ifndef WX_PRECOMP
a92b5dfe 31 #include "wx/bmpbuttn.h"
374ae80f 32 #include "wx/button.h"
a8e87569 33 #include "wx/dcmemory.h"
a92b5dfe
VZ
34 #include "wx/settings.h"
35 #include "wx/statbmp.h"
36 #include "wx/stattext.h"
65391c8f 37 #include "wx/sizer.h"
a92b5dfe
VZ
38#endif // WX_PRECOMP
39
ed8efd46 40#include "wx/artprov.h"
a92b5dfe 41#include "wx/scopeguard.h"
a92b5dfe 42
cc7033c2
VZ
43BEGIN_EVENT_TABLE(wxInfoBarGeneric, wxInfoBarBase)
44 EVT_BUTTON(wxID_ANY, wxInfoBarGeneric::OnButton)
45END_EVENT_TABLE()
46
a92b5dfe
VZ
47// ============================================================================
48// implementation
49// ============================================================================
50
ed8efd46 51void wxInfoBarGeneric::Init()
a92b5dfe
VZ
52{
53 m_icon = NULL;
54 m_text = NULL;
55 m_button = NULL;
56
3996b21a
VZ
57 m_showEffect =
58 m_hideEffect = wxSHOW_EFFECT_MAX;
a92b5dfe
VZ
59
60 // use default effect duration
61 m_effectDuration = 0;
62}
63
ed8efd46 64bool wxInfoBarGeneric::Create(wxWindow *parent, wxWindowID winid)
a92b5dfe
VZ
65{
66 // calling Hide() before Create() ensures that we're created initially
67 // hidden
68 Hide();
69 if ( !wxWindow::Create(parent, winid) )
70 return false;
71
72 // use special, easy to notice, colours
cc260804
VZ
73 const wxColour colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK);
74 SetBackgroundColour(colBg);
a92b5dfe
VZ
75 SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
76
77 // create the controls: icon, text and the button to dismiss the
78 // message.
79
80 // the icon is not shown unless it's assigned a valid bitmap
81 m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
82
a92b5dfe 83 m_text = new wxStaticText(this, wxID_ANY, "");
a92b5dfe 84
a68fb3fc 85 m_button = wxBitmapButton::NewCloseButton(this, wxID_ANY);
a92b5dfe
VZ
86 m_button->SetToolTip(_("Hide this notification message."));
87
374ae80f
VZ
88 // center the text inside the sizer with an icon to the left of it and a
89 // button at the very right
90 //
91 // NB: AddButton() relies on the button being the last control in the sizer
92 // and being preceded by a spacer
a92b5dfe 93 wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL);
bc061c8e
VZ
94 sizer->Add(m_icon, wxSizerFlags().Centre().Border());
95 sizer->Add(m_text, wxSizerFlags().Centre());
a92b5dfe 96 sizer->AddStretchSpacer();
bc061c8e 97 sizer->Add(m_button, wxSizerFlags().Centre().Border());
a92b5dfe
VZ
98 SetSizer(sizer);
99
100 return true;
101}
102
ed8efd46 103bool wxInfoBarGeneric::SetFont(const wxFont& font)
df8c364b
VZ
104{
105 if ( !wxInfoBarBase::SetFont(font) )
106 return false;
107
108 // check that we're not called before Create()
109 if ( m_text )
110 m_text->SetFont(font);
111
112 return true;
113}
114
3996b21a
VZ
115wxInfoBarGeneric::BarPlacement wxInfoBarGeneric::GetBarPlacement() const
116{
117 wxSizer * const sizer = GetContainingSizer();
118 if ( !sizer )
119 return BarPlacement_Unknown;
120
21d5ec7d
VZ
121 // FIXME-VC6: can't compare "const wxInfoBarGeneric *" and "wxWindow *",
122 // so need this workaround
123 wxWindow * const self = const_cast<wxInfoBarGeneric *>(this);
3996b21a 124 const wxSizerItemList& siblings = sizer->GetChildren();
21d5ec7d 125 if ( siblings.GetFirst()->GetData()->GetWindow() == self )
3996b21a 126 return BarPlacement_Top;
21d5ec7d 127 else if ( siblings.GetLast()->GetData()->GetWindow() == self )
3996b21a
VZ
128 return BarPlacement_Bottom;
129 else
130 return BarPlacement_Unknown;
131}
132
133wxShowEffect wxInfoBarGeneric::GetShowEffect() const
134{
135 if ( m_showEffect != wxSHOW_EFFECT_MAX )
136 return m_showEffect;
137
138 switch ( GetBarPlacement() )
139 {
140 case BarPlacement_Top:
141 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
142
143 case BarPlacement_Bottom:
144 return wxSHOW_EFFECT_SLIDE_TO_TOP;
145
146 default:
147 wxFAIL_MSG( "unknown info bar placement" );
148 // fall through
149
150 case BarPlacement_Unknown:
151 return wxSHOW_EFFECT_NONE;
152 }
153}
154
155wxShowEffect wxInfoBarGeneric::GetHideEffect() const
156{
157 if ( m_hideEffect != wxSHOW_EFFECT_MAX )
158 return m_hideEffect;
159
160 switch ( GetBarPlacement() )
161 {
162 case BarPlacement_Top:
163 return wxSHOW_EFFECT_SLIDE_TO_TOP;
164
165 case BarPlacement_Bottom:
166 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
167
168 default:
169 wxFAIL_MSG( "unknown info bar placement" );
170 // fall through
171
172 case BarPlacement_Unknown:
173 return wxSHOW_EFFECT_NONE;
174 }
175}
176
ed8efd46 177void wxInfoBarGeneric::UpdateParent()
a92b5dfe 178{
f0bae4ba 179 wxWindow * const parent = GetParent();
a92b5dfe
VZ
180 parent->Layout();
181}
182
ed8efd46 183void wxInfoBarGeneric::DoHide()
a92b5dfe 184{
3996b21a 185 HideWithEffect(GetHideEffect(), GetEffectDuration());
15ea6e20 186
a92b5dfe
VZ
187 UpdateParent();
188}
189
ed8efd46 190void wxInfoBarGeneric::DoShow()
a92b5dfe
VZ
191{
192 // re-layout the parent first so that the window expands into an already
193 // unoccupied by the other controls area: for this we need to change our
194 // internal visibility flag to force Layout() to take us into account (an
195 // alternative solution to this hack would be to temporarily set
196 // wxRESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really batter)
197
198 // just change the internal flag indicating that the window is visible,
199 // without really showing it
200 wxWindowBase::Show();
201
a92b5dfe
VZ
202 // adjust the parent layout to account for us
203 UpdateParent();
204
205 // reset the flag back before really showing the window or it wouldn't be
206 // shown at all because it would believe itself already visible
207 wxWindowBase::Show(false);
208
209
210 // finally do really show the window.
3996b21a 211 ShowWithEffect(GetShowEffect(), GetEffectDuration());
a92b5dfe
VZ
212}
213
ed8efd46 214void wxInfoBarGeneric::ShowMessage(const wxString& msg, int flags)
a92b5dfe
VZ
215{
216 // first update the controls
217 const int icon = flags & wxICON_MASK;
218 if ( !icon || (icon == wxICON_NONE) )
219 {
220 m_icon->Hide();
221 }
222 else // do show an icon
223 {
bc061c8e
VZ
224 m_icon->SetBitmap(wxArtProvider::GetBitmap(
225 wxArtProvider::GetMessageBoxIconId(flags),
5c67a53d 226 wxART_BUTTON));
a92b5dfe
VZ
227 m_icon->Show();
228 }
229
230 // notice the use of EscapeMnemonics() to ensure that "&" come through
231 // correctly
232 m_text->SetLabel(wxControl::EscapeMnemonics(msg));
233
234
235 // then show this entire window if not done yet
236 if ( !IsShown() )
237 {
238 DoShow();
239 }
240 else // we're already shown
241 {
242 // just update the layout to correspond to the new message
243 Layout();
244 }
245}
246
0b1add25
VZ
247void wxInfoBarGeneric::Dismiss()
248{
249 DoHide();
250}
251
ed8efd46 252void wxInfoBarGeneric::AddButton(wxWindowID btnid, const wxString& label)
374ae80f
VZ
253{
254 wxSizer * const sizer = GetSizer();
255 wxCHECK_RET( sizer, "must be created first" );
256
6a3f8b4f
VZ
257 // user-added buttons replace the standard close button so remove it if we
258 // hadn't done it yet
259 if ( sizer->Detach(m_button) )
260 {
261 m_button->Hide();
262 }
263
bccb042c
VZ
264 wxButton * const button = new wxButton(this, btnid, label);
265
266#ifdef __WXMAC__
267 // smaller buttons look better in the (narrow) info bar under OS X
268 button->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
269#endif // __WXMAC__
270
271 sizer->Add(button, wxSizerFlags().Centre().DoubleBorder());
374ae80f
VZ
272}
273
e6b2aae1
VZ
274void wxInfoBarGeneric::RemoveButton(wxWindowID btnid)
275{
276 wxSizer * const sizer = GetSizer();
277 wxCHECK_RET( sizer, "must be created first" );
278
279 // iterate over the sizer items in reverse order to find the last added
280 // button with this id (ids of all buttons should be unique anyhow but if
281 // they are repeated removing the last added one probably makes more sense)
282 const wxSizerItemList& items = sizer->GetChildren();
283 for ( wxSizerItemList::compatibility_iterator node = items.GetLast();
284 node != items.GetFirst();
285 node = node->GetPrevious() )
286 {
e6b2aae1
VZ
287 const wxSizerItem * const item = node->GetData();
288
289 // if we reached the spacer separating the buttons from the text
290 // preceding them without finding our button, it must mean it's not
291 // there at all
292 if ( item->IsSpacer() )
293 {
294 wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) );
295 return;
296 }
297
298 // check if we found our button
299 if ( item->GetWindow()->GetId() == btnid )
300 {
301 delete item->GetWindow();
302 break;
303 }
304 }
6a3f8b4f
VZ
305
306 // check if there are any custom buttons left
307 if ( sizer->GetChildren().GetLast()->GetData()->IsSpacer() )
308 {
309 // if the last item is the spacer, none are left so restore the
310 // standard close button
311 sizer->Add(m_button, wxSizerFlags().Centre().DoubleBorder());
312 m_button->Show();
313 }
e6b2aae1
VZ
314}
315
ed8efd46 316void wxInfoBarGeneric::OnButton(wxCommandEvent& WXUNUSED(event))
a92b5dfe
VZ
317{
318 DoHide();
319}
320
321#endif // wxUSE_INFOBAR