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/renderer.h"
40 #include "wx/scopeguard.h"
43 BEGIN_EVENT_TABLE(wxInfoBarGeneric
, wxInfoBarBase
)
44 EVT_BUTTON(wxID_ANY
, wxInfoBarGeneric::OnButton
)
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
54 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
57 GetCloseButtonBitmap(wxWindow
*win
,
59 const wxColour
& colBg
,
64 dc
.SetBackground(colBg
);
66 wxRendererNative::Get().
67 DrawTitleBarBitmap(win
, dc
, size
, wxTITLEBAR_BUTTON_CLOSE
, flags
);
71 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
73 } // anonymous namespace
75 // ============================================================================
77 // ============================================================================
79 void wxInfoBarGeneric::Init()
86 m_hideEffect
= wxSHOW_EFFECT_MAX
;
88 // use default effect duration
92 bool wxInfoBarGeneric::Create(wxWindow
*parent
, wxWindowID winid
)
94 // calling Hide() before Create() ensures that we're created initially
97 if ( !wxWindow::Create(parent
, winid
) )
100 // use special, easy to notice, colours
101 const wxColour colBg
= wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK
);
102 SetBackgroundColour(colBg
);
103 SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT
));
105 // create the controls: icon, text and the button to dismiss the
108 // the icon is not shown unless it's assigned a valid bitmap
109 m_icon
= new wxStaticBitmap(this, wxID_ANY
, wxNullBitmap
);
111 m_text
= new wxStaticText(this, wxID_ANY
, "");
113 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
114 const wxSize sizeBmp
= wxArtProvider::GetSizeHint(wxART_BUTTON
);
115 wxBitmap bmp
= GetCloseButtonBitmap(this, sizeBmp
, colBg
);
116 #else // !wxHAS_DRAW_TITLE_BAR_BITMAP
117 wxBitmap bmp
= wxArtProvider::GetBitmap(wxART_CLOSE
, wxART_BUTTON
);
118 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
119 m_button
= new wxBitmapButton
129 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
130 m_button
->SetBitmapPressed(
131 GetCloseButtonBitmap(this, sizeBmp
, colBg
, wxCONTROL_PRESSED
));
133 m_button
->SetBitmapCurrent(
134 GetCloseButtonBitmap(this, sizeBmp
, colBg
, wxCONTROL_CURRENT
));
135 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
137 m_button
->SetBackgroundColour(colBg
);
138 m_button
->SetToolTip(_("Hide this notification message."));
140 // center the text inside the sizer with an icon to the left of it and a
141 // button at the very right
143 // NB: AddButton() relies on the button being the last control in the sizer
144 // and being preceded by a spacer
145 wxSizer
* const sizer
= new wxBoxSizer(wxHORIZONTAL
);
146 sizer
->Add(m_icon
, wxSizerFlags().Centre().Border());
147 sizer
->Add(m_text
, wxSizerFlags().Centre());
148 sizer
->AddStretchSpacer();
149 sizer
->Add(m_button
, wxSizerFlags().Centre().Border());
155 bool wxInfoBarGeneric::SetFont(const wxFont
& font
)
157 if ( !wxInfoBarBase::SetFont(font
) )
160 // check that we're not called before Create()
162 m_text
->SetFont(font
);
167 wxInfoBarGeneric::BarPlacement
wxInfoBarGeneric::GetBarPlacement() const
169 wxSizer
* const sizer
= GetContainingSizer();
171 return BarPlacement_Unknown
;
173 const wxSizerItemList
& siblings
= sizer
->GetChildren();
174 if ( siblings
.GetFirst()->GetData()->GetWindow() == this )
175 return BarPlacement_Top
;
176 else if ( siblings
.GetLast()->GetData()->GetWindow() == this )
177 return BarPlacement_Bottom
;
179 return BarPlacement_Unknown
;
182 wxShowEffect
wxInfoBarGeneric::GetShowEffect() const
184 if ( m_showEffect
!= wxSHOW_EFFECT_MAX
)
187 switch ( GetBarPlacement() )
189 case BarPlacement_Top
:
190 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM
;
192 case BarPlacement_Bottom
:
193 return wxSHOW_EFFECT_SLIDE_TO_TOP
;
196 wxFAIL_MSG( "unknown info bar placement" );
199 case BarPlacement_Unknown
:
200 return wxSHOW_EFFECT_NONE
;
204 wxShowEffect
wxInfoBarGeneric::GetHideEffect() const
206 if ( m_hideEffect
!= wxSHOW_EFFECT_MAX
)
209 switch ( GetBarPlacement() )
211 case BarPlacement_Top
:
212 return wxSHOW_EFFECT_SLIDE_TO_TOP
;
214 case BarPlacement_Bottom
:
215 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM
;
218 wxFAIL_MSG( "unknown info bar placement" );
221 case BarPlacement_Unknown
:
222 return wxSHOW_EFFECT_NONE
;
226 void wxInfoBarGeneric::UpdateParent()
228 wxWindow
* const parent
= wxGetTopLevelParent(GetParent());
232 void wxInfoBarGeneric::DoHide()
234 HideWithEffect(GetHideEffect(), GetEffectDuration());
239 void wxInfoBarGeneric::DoShow()
241 // re-layout the parent first so that the window expands into an already
242 // unoccupied by the other controls area: for this we need to change our
243 // internal visibility flag to force Layout() to take us into account (an
244 // alternative solution to this hack would be to temporarily set
245 // wxRESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really batter)
247 // just change the internal flag indicating that the window is visible,
248 // without really showing it
249 wxWindowBase::Show();
251 // adjust the parent layout to account for us
254 // reset the flag back before really showing the window or it wouldn't be
255 // shown at all because it would believe itself already visible
256 wxWindowBase::Show(false);
259 // finally do really show the window.
260 ShowWithEffect(GetShowEffect(), GetEffectDuration());
263 void wxInfoBarGeneric::ShowMessage(const wxString
& msg
, int flags
)
265 // first update the controls
266 const int icon
= flags
& wxICON_MASK
;
267 if ( !icon
|| (icon
== wxICON_NONE
) )
271 else // do show an icon
273 m_icon
->SetBitmap(wxArtProvider::GetBitmap(
274 wxArtProvider::GetMessageBoxIconId(flags
),
279 // notice the use of EscapeMnemonics() to ensure that "&" come through
281 m_text
->SetLabel(wxControl::EscapeMnemonics(msg
));
284 // then show this entire window if not done yet
289 else // we're already shown
291 // just update the layout to correspond to the new message
296 void wxInfoBarGeneric::Dismiss()
301 void wxInfoBarGeneric::AddButton(wxWindowID btnid
, const wxString
& label
)
303 wxSizer
* const sizer
= GetSizer();
304 wxCHECK_RET( sizer
, "must be created first" );
306 // user-added buttons replace the standard close button so remove it if we
307 // hadn't done it yet
308 if ( sizer
->Detach(m_button
) )
313 wxButton
* const button
= new wxButton(this, btnid
, label
);
316 // smaller buttons look better in the (narrow) info bar under OS X
317 button
->SetWindowVariant(wxWINDOW_VARIANT_SMALL
);
320 sizer
->Add(button
, wxSizerFlags().Centre().DoubleBorder());
323 void wxInfoBarGeneric::RemoveButton(wxWindowID btnid
)
325 wxSizer
* const sizer
= GetSizer();
326 wxCHECK_RET( sizer
, "must be created first" );
328 // iterate over the sizer items in reverse order to find the last added
329 // button with this id (ids of all buttons should be unique anyhow but if
330 // they are repeated removing the last added one probably makes more sense)
331 const wxSizerItemList
& items
= sizer
->GetChildren();
332 for ( wxSizerItemList::compatibility_iterator node
= items
.GetLast();
333 node
!= items
.GetFirst();
334 node
= node
->GetPrevious() )
336 const wxSizerItem
* const item
= node
->GetData();
338 // if we reached the spacer separating the buttons from the text
339 // preceding them without finding our button, it must mean it's not
341 if ( item
->IsSpacer() )
343 wxFAIL_MSG( wxString::Format("button with id %d not found", btnid
) );
347 // check if we found our button
348 if ( item
->GetWindow()->GetId() == btnid
)
350 delete item
->GetWindow();
355 // check if there are any custom buttons left
356 if ( sizer
->GetChildren().GetLast()->GetData()->IsSpacer() )
358 // if the last item is the spacer, none are left so restore the
359 // standard close button
360 sizer
->Add(m_button
, wxSizerFlags().Centre().DoubleBorder());
365 void wxInfoBarGeneric::OnButton(wxCommandEvent
& WXUNUSED(event
))
370 #endif // wxUSE_INFOBAR