1
///////////////////////////////////////////////////////////////////////////////
2
// Name: src/generic/infobar.cpp
3
// Purpose: generic wxInfoBar implementation
4
// Author: Vadim Zeitlin
6
// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
7
// Licence: wxWindows licence
8
///////////////////////////////////////////////////////////////////////////////
10
// ============================================================================
12
// ============================================================================
14
// ----------------------------------------------------------------------------
16
// ----------------------------------------------------------------------------
18
// for compilers that support precompilation, includes "wx.h".
19
#include "wx/wxprec.h"
27
#include "wx/infobar.h"
30
#include "wx/bmpbuttn.h"
31
#include "wx/button.h"
32
#include "wx/dcmemory.h"
33
#include "wx/settings.h"
34
#include "wx/statbmp.h"
35
#include "wx/stattext.h"
39
#include "wx/artprov.h"
40
#include "wx/scopeguard.h"
42
BEGIN_EVENT_TABLE(wxInfoBarGeneric, wxInfoBarBase)
43
EVT_BUTTON(wxID_ANY, wxInfoBarGeneric::OnButton)
46
// ============================================================================
48
// ============================================================================
50
void wxInfoBarGeneric::Init()
57
m_hideEffect = wxSHOW_EFFECT_MAX;
59
// use default effect duration
63
bool wxInfoBarGeneric::Create(wxWindow *parent, wxWindowID winid)
65
// calling Hide() before Create() ensures that we're created initially
68
if ( !wxWindow::Create(parent, winid) )
71
// use special, easy to notice, colours
72
const wxColour colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK);
73
SetBackgroundColour(colBg);
74
SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
76
// create the controls: icon, text and the button to dismiss the
79
// the icon is not shown unless it's assigned a valid bitmap
80
m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
82
m_text = new wxStaticText(this, wxID_ANY, "");
84
m_button = wxBitmapButton::NewCloseButton(this, wxID_ANY);
85
m_button->SetToolTip(_("Hide this notification message."));
87
// center the text inside the sizer with an icon to the left of it and a
88
// button at the very right
90
// NB: AddButton() relies on the button being the last control in the sizer
91
// and being preceded by a spacer
92
wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL);
93
sizer->Add(m_icon, wxSizerFlags().Centre().Border());
94
sizer->Add(m_text, wxSizerFlags().Centre());
95
sizer->AddStretchSpacer();
96
sizer->Add(m_button, wxSizerFlags().Centre().Border());
102
bool wxInfoBarGeneric::SetFont(const wxFont& font)
104
if ( !wxInfoBarBase::SetFont(font) )
107
// check that we're not called before Create()
109
m_text->SetFont(font);
114
wxInfoBarGeneric::BarPlacement wxInfoBarGeneric::GetBarPlacement() const
116
wxSizer * const sizer = GetContainingSizer();
118
return BarPlacement_Unknown;
120
// FIXME-VC6: can't compare "const wxInfoBarGeneric *" and "wxWindow *",
121
// so need this workaround
122
wxWindow * const self = const_cast<wxInfoBarGeneric *>(this);
123
const wxSizerItemList& siblings = sizer->GetChildren();
124
if ( siblings.GetFirst()->GetData()->GetWindow() == self )
125
return BarPlacement_Top;
126
else if ( siblings.GetLast()->GetData()->GetWindow() == self )
127
return BarPlacement_Bottom;
129
return BarPlacement_Unknown;
132
wxShowEffect wxInfoBarGeneric::GetShowEffect() const
134
if ( m_showEffect != wxSHOW_EFFECT_MAX )
137
switch ( GetBarPlacement() )
139
case BarPlacement_Top:
140
return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
142
case BarPlacement_Bottom:
143
return wxSHOW_EFFECT_SLIDE_TO_TOP;
146
wxFAIL_MSG( "unknown info bar placement" );
149
case BarPlacement_Unknown:
150
return wxSHOW_EFFECT_NONE;
154
wxShowEffect wxInfoBarGeneric::GetHideEffect() const
156
if ( m_hideEffect != wxSHOW_EFFECT_MAX )
159
switch ( GetBarPlacement() )
161
case BarPlacement_Top:
162
return wxSHOW_EFFECT_SLIDE_TO_TOP;
164
case BarPlacement_Bottom:
165
return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
168
wxFAIL_MSG( "unknown info bar placement" );
171
case BarPlacement_Unknown:
172
return wxSHOW_EFFECT_NONE;
176
void wxInfoBarGeneric::UpdateParent()
178
wxWindow * const parent = GetParent();
182
void wxInfoBarGeneric::DoHide()
184
HideWithEffect(GetHideEffect(), GetEffectDuration());
189
void wxInfoBarGeneric::DoShow()
191
// re-layout the parent first so that the window expands into an already
192
// unoccupied by the other controls area: for this we need to change our
193
// internal visibility flag to force Layout() to take us into account (an
194
// alternative solution to this hack would be to temporarily set
195
// wxRESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really batter)
197
// just change the internal flag indicating that the window is visible,
198
// without really showing it
199
wxWindowBase::Show();
201
// adjust the parent layout to account for us
204
// reset the flag back before really showing the window or it wouldn't be
205
// shown at all because it would believe itself already visible
206
wxWindowBase::Show(false);
209
// finally do really show the window.
210
ShowWithEffect(GetShowEffect(), GetEffectDuration());
213
void wxInfoBarGeneric::ShowMessage(const wxString& msg, int flags)
215
// first update the controls
216
const int icon = flags & wxICON_MASK;
217
if ( !icon || (icon == wxICON_NONE) )
221
else // do show an icon
223
m_icon->SetBitmap(wxArtProvider::GetBitmap(
224
wxArtProvider::GetMessageBoxIconId(flags),
229
// notice the use of EscapeMnemonics() to ensure that "&" come through
231
m_text->SetLabel(wxControl::EscapeMnemonics(msg));
234
// then show this entire window if not done yet
239
else // we're already shown
241
// just update the layout to correspond to the new message
246
void wxInfoBarGeneric::Dismiss()
251
void wxInfoBarGeneric::AddButton(wxWindowID btnid, const wxString& label)
253
wxSizer * const sizer = GetSizer();
254
wxCHECK_RET( sizer, "must be created first" );
256
// user-added buttons replace the standard close button so remove it if we
257
// hadn't done it yet
258
if ( sizer->Detach(m_button) )
263
wxButton * const button = new wxButton(this, btnid, label);
266
// smaller buttons look better in the (narrow) info bar under OS X
267
button->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
270
sizer->Add(button, wxSizerFlags().Centre().DoubleBorder());
273
void wxInfoBarGeneric::RemoveButton(wxWindowID btnid)
275
wxSizer * const sizer = GetSizer();
276
wxCHECK_RET( sizer, "must be created first" );
278
// iterate over the sizer items in reverse order to find the last added
279
// button with this id (ids of all buttons should be unique anyhow but if
280
// they are repeated removing the last added one probably makes more sense)
281
const wxSizerItemList& items = sizer->GetChildren();
282
for ( wxSizerItemList::compatibility_iterator node = items.GetLast();
283
node != items.GetFirst();
284
node = node->GetPrevious() )
286
const wxSizerItem * const item = node->GetData();
288
// if we reached the spacer separating the buttons from the text
289
// preceding them without finding our button, it must mean it's not
291
if ( item->IsSpacer() )
293
wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) );
297
// check if we found our button
298
if ( item->GetWindow()->GetId() == btnid )
300
delete item->GetWindow();
305
// check if there are any custom buttons left
306
if ( sizer->GetChildren().GetLast()->GetData()->IsSpacer() )
308
// if the last item is the spacer, none are left so restore the
309
// standard close button
310
sizer->Add(m_button, wxSizerFlags().Centre().DoubleBorder());
315
void wxInfoBarGeneric::OnButton(wxCommandEvent& WXUNUSED(event))
320
#endif // wxUSE_INFOBAR