1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/infobar.cpp
3 // Purpose: generic wxInfoBar implementation
4 // Author: Vadim Zeitlin
6 // RCS-ID: $Id: wxhead.cpp,v 1.10 2009-06-29 10:23:04 zeitlin Exp $
7 // Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
29 #include "wx/bmpbuttn.h"
30 #include "wx/button.h"
31 #include "wx/settings.h"
32 #include "wx/statbmp.h"
33 #include "wx/stattext.h"
36 #include "wx/infobar.h"
38 #include "wx/artprov.h"
39 #include "wx/scopeguard.h"
42 BEGIN_EVENT_TABLE(wxInfoBarGeneric
, wxInfoBarBase
)
43 EVT_BUTTON(wxID_ANY
, wxInfoBarGeneric::OnButton
)
46 // ============================================================================
48 // ============================================================================
50 void wxInfoBarGeneric::Init()
56 m_showEffect
= wxSHOW_EFFECT_SLIDE_TO_BOTTOM
;
57 m_hideEffect
= wxSHOW_EFFECT_SLIDE_TO_TOP
;
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 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK
));
73 SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT
));
75 // create the controls: icon, text and the button to dismiss the
78 // the icon is not shown unless it's assigned a valid bitmap
79 m_icon
= new wxStaticBitmap(this, wxID_ANY
, wxNullBitmap
);
81 // by default, the text uses a larger, more noticeable, font
82 m_text
= new wxStaticText(this, wxID_ANY
, "");
83 m_text
->SetFont(m_text
->GetFont().Bold().Larger());
85 m_button
= new wxBitmapButton
89 wxArtProvider::GetBitmap(wxART_CROSS_MARK
),
94 m_button
->SetToolTip(_("Hide this notification message."));
96 // center the text inside the sizer with an icon to the left of it and a
97 // button at the very right
99 // NB: AddButton() relies on the button being the last control in the sizer
100 // and being preceded by a spacer
101 wxSizer
* const sizer
= new wxBoxSizer(wxHORIZONTAL
);
102 sizer
->AddStretchSpacer();
103 sizer
->Add(m_icon
, wxSizerFlags().Centre().DoubleBorder());
104 sizer
->Add(m_text
, wxSizerFlags().Centre().DoubleBorder());
105 sizer
->AddStretchSpacer();
106 sizer
->Add(m_button
, wxSizerFlags().Centre().DoubleBorder());
112 bool wxInfoBarGeneric::SetFont(const wxFont
& font
)
114 if ( !wxInfoBarBase::SetFont(font
) )
117 // check that we're not called before Create()
119 m_text
->SetFont(font
);
124 void wxInfoBarGeneric::UpdateParent()
126 wxWindow
* const parent
= wxGetTopLevelParent(GetParent());
130 void wxInfoBarGeneric::ChangeParentBackground()
132 wxWindow
* const parent
= GetParent();
133 m_origParentBgCol
= parent
->GetBackgroundColour();
135 wxSizer
* const sizer
= GetContainingSizer();
139 wxWindow
*sibling
= NULL
;
140 for ( wxSizerItemList::compatibility_iterator
141 node
= sizer
->GetChildren().GetFirst();
143 node
= node
->GetNext() )
145 if ( node
->GetData()->GetWindow() == this )
147 // find the next window following us
148 for ( node
= node
->GetNext();
150 node
= node
->GetNext() )
152 wxSizerItem
* const item
= node
->GetData();
153 if ( item
->IsWindow() )
155 sibling
= item
->GetWindow();
165 parent
->SetOwnBackgroundColour(sibling
->GetBackgroundColour());
168 void wxInfoBarGeneric::RestoreParentBackground()
170 GetParent()->SetOwnBackgroundColour(m_origParentBgCol
);
173 void wxInfoBarGeneric::DoHide()
175 ChangeParentBackground();
176 wxON_BLOCK_EXIT_THIS0( wxInfoBarGeneric::RestoreParentBackground
);
178 HideWithEffect(m_hideEffect
, m_effectDuration
);
182 void wxInfoBarGeneric::DoShow()
184 // re-layout the parent first so that the window expands into an already
185 // unoccupied by the other controls area: for this we need to change our
186 // internal visibility flag to force Layout() to take us into account (an
187 // alternative solution to this hack would be to temporarily set
188 // wxRESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really batter)
190 // just change the internal flag indicating that the window is visible,
191 // without really showing it
192 wxWindowBase::Show();
194 // an extra hack: we want the temporarily uncovered area in which we're
195 // going to expand to look like part of this sibling for a better effect so
196 // temporarily change the background of our parent to the same colour
197 ChangeParentBackground();
198 wxON_BLOCK_EXIT_THIS0( wxInfoBarGeneric::RestoreParentBackground
);
200 // adjust the parent layout to account for us
203 // reset the flag back before really showing the window or it wouldn't be
204 // shown at all because it would believe itself already visible
205 wxWindowBase::Show(false);
208 // finally do really show the window.
209 ShowWithEffect(m_showEffect
, m_effectDuration
);
212 void wxInfoBarGeneric::ShowMessage(const wxString
& msg
, int flags
)
214 // first update the controls
215 const int icon
= flags
& wxICON_MASK
;
216 if ( !icon
|| (icon
== wxICON_NONE
) )
220 else // do show an icon
222 m_icon
->SetBitmap(wxArtProvider::GetMessageBoxIcon(icon
));
226 // notice the use of EscapeMnemonics() to ensure that "&" come through
228 m_text
->SetLabel(wxControl::EscapeMnemonics(msg
));
231 // then show this entire window if not done yet
236 else // we're already shown
238 // just update the layout to correspond to the new message
243 void wxInfoBarGeneric::AddButton(wxWindowID btnid
, const wxString
& label
)
245 wxSizer
* const sizer
= GetSizer();
246 wxCHECK_RET( sizer
, "must be created first" );
248 // user-added buttons replace the standard close button so remove it if we
249 // hadn't done it yet
250 if ( sizer
->Detach(m_button
) )
255 sizer
->Add(new wxButton(this, btnid
, label
),
256 wxSizerFlags().Centre().DoubleBorder());
259 void wxInfoBarGeneric::RemoveButton(wxWindowID btnid
)
261 wxSizer
* const sizer
= GetSizer();
262 wxCHECK_RET( sizer
, "must be created first" );
264 // iterate over the sizer items in reverse order to find the last added
265 // button with this id (ids of all buttons should be unique anyhow but if
266 // they are repeated removing the last added one probably makes more sense)
267 const wxSizerItemList
& items
= sizer
->GetChildren();
268 for ( wxSizerItemList::compatibility_iterator node
= items
.GetLast();
269 node
!= items
.GetFirst();
270 node
= node
->GetPrevious() )
272 const wxSizerItem
* const item
= node
->GetData();
274 // if we reached the spacer separating the buttons from the text
275 // preceding them without finding our button, it must mean it's not
277 if ( item
->IsSpacer() )
279 wxFAIL_MSG( wxString::Format("button with id %d not found", btnid
) );
283 // check if we found our button
284 if ( item
->GetWindow()->GetId() == btnid
)
286 delete item
->GetWindow();
291 // check if there are any custom buttons left
292 if ( sizer
->GetChildren().GetLast()->GetData()->IsSpacer() )
294 // if the last item is the spacer, none are left so restore the
295 // standard close button
296 sizer
->Add(m_button
, wxSizerFlags().Centre().DoubleBorder());
301 void wxInfoBarGeneric::OnButton(wxCommandEvent
& WXUNUSED(event
))
306 #endif // wxUSE_INFOBAR