1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/infobar.cpp
3 // Purpose: generic wxInfoBar implementation
4 // Author: Vadim Zeitlin
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"
28 #include "wx/infobar.h"
31 #include "wx/bmpbuttn.h"
32 #include "wx/button.h"
33 #include "wx/dcmemory.h"
34 #include "wx/settings.h"
35 #include "wx/statbmp.h"
36 #include "wx/stattext.h"
40 #include "wx/artprov.h"
41 #include "wx/renderer.h"
42 #include "wx/scopeguard.h"
44 BEGIN_EVENT_TABLE(wxInfoBarGeneric
, wxInfoBarBase
)
45 EVT_BUTTON(wxID_ANY
, wxInfoBarGeneric::OnButton
)
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
55 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
58 GetCloseButtonBitmap(wxWindow
*win
,
60 const wxColour
& colBg
,
65 dc
.SetBackground(colBg
);
67 wxRendererNative::Get().
68 DrawTitleBarBitmap(win
, dc
, size
, wxTITLEBAR_BUTTON_CLOSE
, flags
);
72 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
74 } // anonymous namespace
76 // ============================================================================
78 // ============================================================================
80 void wxInfoBarGeneric::Init()
87 m_hideEffect
= wxSHOW_EFFECT_MAX
;
89 // use default effect duration
93 bool wxInfoBarGeneric::Create(wxWindow
*parent
, wxWindowID winid
)
95 // calling Hide() before Create() ensures that we're created initially
98 if ( !wxWindow::Create(parent
, winid
) )
101 // use special, easy to notice, colours
102 const wxColour colBg
= wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK
);
103 SetBackgroundColour(colBg
);
104 SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT
));
106 // create the controls: icon, text and the button to dismiss the
109 // the icon is not shown unless it's assigned a valid bitmap
110 m_icon
= new wxStaticBitmap(this, wxID_ANY
, wxNullBitmap
);
112 m_text
= new wxStaticText(this, wxID_ANY
, "");
114 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
115 const wxSize sizeBmp
= wxArtProvider::GetSizeHint(wxART_BUTTON
);
116 wxBitmap bmp
= GetCloseButtonBitmap(this, sizeBmp
, colBg
);
117 #else // !wxHAS_DRAW_TITLE_BAR_BITMAP
118 wxBitmap bmp
= wxArtProvider::GetBitmap(wxART_CLOSE
, wxART_BUTTON
);
119 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
120 m_button
= new wxBitmapButton
130 #ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
131 m_button
->SetBitmapPressed(
132 GetCloseButtonBitmap(this, sizeBmp
, colBg
, wxCONTROL_PRESSED
));
134 m_button
->SetBitmapCurrent(
135 GetCloseButtonBitmap(this, sizeBmp
, colBg
, wxCONTROL_CURRENT
));
136 #endif // wxHAS_DRAW_TITLE_BAR_BITMAP
138 m_button
->SetBackgroundColour(colBg
);
139 m_button
->SetToolTip(_("Hide this notification message."));
141 // center the text inside the sizer with an icon to the left of it and a
142 // button at the very right
144 // NB: AddButton() relies on the button being the last control in the sizer
145 // and being preceded by a spacer
146 wxSizer
* const sizer
= new wxBoxSizer(wxHORIZONTAL
);
147 sizer
->Add(m_icon
, wxSizerFlags().Centre().Border());
148 sizer
->Add(m_text
, wxSizerFlags().Centre());
149 sizer
->AddStretchSpacer();
150 sizer
->Add(m_button
, wxSizerFlags().Centre().Border());
156 bool wxInfoBarGeneric::SetFont(const wxFont
& font
)
158 if ( !wxInfoBarBase::SetFont(font
) )
161 // check that we're not called before Create()
163 m_text
->SetFont(font
);
168 wxInfoBarGeneric::BarPlacement
wxInfoBarGeneric::GetBarPlacement() const
170 wxSizer
* const sizer
= GetContainingSizer();
172 return BarPlacement_Unknown
;
174 // FIXME-VC6: can't compare "const wxInfoBarGeneric *" and "wxWindow *",
175 // so need this workaround
176 wxWindow
* const self
= const_cast<wxInfoBarGeneric
*>(this);
177 const wxSizerItemList
& siblings
= sizer
->GetChildren();
178 if ( siblings
.GetFirst()->GetData()->GetWindow() == self
)
179 return BarPlacement_Top
;
180 else if ( siblings
.GetLast()->GetData()->GetWindow() == self
)
181 return BarPlacement_Bottom
;
183 return BarPlacement_Unknown
;
186 wxShowEffect
wxInfoBarGeneric::GetShowEffect() const
188 if ( m_showEffect
!= wxSHOW_EFFECT_MAX
)
191 switch ( GetBarPlacement() )
193 case BarPlacement_Top
:
194 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM
;
196 case BarPlacement_Bottom
:
197 return wxSHOW_EFFECT_SLIDE_TO_TOP
;
200 wxFAIL_MSG( "unknown info bar placement" );
203 case BarPlacement_Unknown
:
204 return wxSHOW_EFFECT_NONE
;
208 wxShowEffect
wxInfoBarGeneric::GetHideEffect() const
210 if ( m_hideEffect
!= wxSHOW_EFFECT_MAX
)
213 switch ( GetBarPlacement() )
215 case BarPlacement_Top
:
216 return wxSHOW_EFFECT_SLIDE_TO_TOP
;
218 case BarPlacement_Bottom
:
219 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM
;
222 wxFAIL_MSG( "unknown info bar placement" );
225 case BarPlacement_Unknown
:
226 return wxSHOW_EFFECT_NONE
;
230 void wxInfoBarGeneric::UpdateParent()
232 wxWindow
* const parent
= wxGetTopLevelParent(GetParent());
236 void wxInfoBarGeneric::DoHide()
238 HideWithEffect(GetHideEffect(), GetEffectDuration());
243 void wxInfoBarGeneric::DoShow()
245 // re-layout the parent first so that the window expands into an already
246 // unoccupied by the other controls area: for this we need to change our
247 // internal visibility flag to force Layout() to take us into account (an
248 // alternative solution to this hack would be to temporarily set
249 // wxRESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really batter)
251 // just change the internal flag indicating that the window is visible,
252 // without really showing it
253 wxWindowBase::Show();
255 // adjust the parent layout to account for us
258 // reset the flag back before really showing the window or it wouldn't be
259 // shown at all because it would believe itself already visible
260 wxWindowBase::Show(false);
263 // finally do really show the window.
264 ShowWithEffect(GetShowEffect(), GetEffectDuration());
267 void wxInfoBarGeneric::ShowMessage(const wxString
& msg
, int flags
)
269 // first update the controls
270 const int icon
= flags
& wxICON_MASK
;
271 if ( !icon
|| (icon
== wxICON_NONE
) )
275 else // do show an icon
277 m_icon
->SetBitmap(wxArtProvider::GetBitmap(
278 wxArtProvider::GetMessageBoxIconId(flags
),
283 // notice the use of EscapeMnemonics() to ensure that "&" come through
285 m_text
->SetLabel(wxControl::EscapeMnemonics(msg
));
288 // then show this entire window if not done yet
293 else // we're already shown
295 // just update the layout to correspond to the new message
300 void wxInfoBarGeneric::Dismiss()
305 void wxInfoBarGeneric::AddButton(wxWindowID btnid
, const wxString
& label
)
307 wxSizer
* const sizer
= GetSizer();
308 wxCHECK_RET( sizer
, "must be created first" );
310 // user-added buttons replace the standard close button so remove it if we
311 // hadn't done it yet
312 if ( sizer
->Detach(m_button
) )
317 wxButton
* const button
= new wxButton(this, btnid
, label
);
320 // smaller buttons look better in the (narrow) info bar under OS X
321 button
->SetWindowVariant(wxWINDOW_VARIANT_SMALL
);
324 sizer
->Add(button
, wxSizerFlags().Centre().DoubleBorder());
327 void wxInfoBarGeneric::RemoveButton(wxWindowID btnid
)
329 wxSizer
* const sizer
= GetSizer();
330 wxCHECK_RET( sizer
, "must be created first" );
332 // iterate over the sizer items in reverse order to find the last added
333 // button with this id (ids of all buttons should be unique anyhow but if
334 // they are repeated removing the last added one probably makes more sense)
335 const wxSizerItemList
& items
= sizer
->GetChildren();
336 for ( wxSizerItemList::compatibility_iterator node
= items
.GetLast();
337 node
!= items
.GetFirst();
338 node
= node
->GetPrevious() )
340 const wxSizerItem
* const item
= node
->GetData();
342 // if we reached the spacer separating the buttons from the text
343 // preceding them without finding our button, it must mean it's not
345 if ( item
->IsSpacer() )
347 wxFAIL_MSG( wxString::Format("button with id %d not found", btnid
) );
351 // check if we found our button
352 if ( item
->GetWindow()->GetId() == btnid
)
354 delete item
->GetWindow();
359 // check if there are any custom buttons left
360 if ( sizer
->GetChildren().GetLast()->GetData()->IsSpacer() )
362 // if the last item is the spacer, none are left so restore the
363 // standard close button
364 sizer
->Add(m_button
, wxSizerFlags().Centre().DoubleBorder());
369 void wxInfoBarGeneric::OnButton(wxCommandEvent
& WXUNUSED(event
))
374 #endif // wxUSE_INFOBAR