]> git.saurik.com Git - wxWidgets.git/blame - src/generic/infobar.cpp
Update setup for OpenVMS
[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
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///////////////////////////////////////////////////////////////////////////////
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
28#ifndef WX_PRECOMP
a92b5dfe 29 #include "wx/bmpbuttn.h"
374ae80f 30 #include "wx/button.h"
a92b5dfe
VZ
31 #include "wx/settings.h"
32 #include "wx/statbmp.h"
33 #include "wx/stattext.h"
34#endif // WX_PRECOMP
35
36#include "wx/infobar.h"
37
ed8efd46 38#include "wx/artprov.h"
cc260804 39#include "wx/renderer.h"
a92b5dfe
VZ
40#include "wx/scopeguard.h"
41#include "wx/sizer.h"
42
cc7033c2
VZ
43BEGIN_EVENT_TABLE(wxInfoBarGeneric, wxInfoBarBase)
44 EVT_BUTTON(wxID_ANY, wxInfoBarGeneric::OnButton)
45END_EVENT_TABLE()
46
cc260804
VZ
47// ----------------------------------------------------------------------------
48// local helpers
49// ----------------------------------------------------------------------------
50
51namespace
52{
53
54#ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
55
56wxBitmap
57GetCloseButtonBitmap(wxWindow *win,
58 const wxSize& size,
59 const wxColour& colBg,
60 int flags = 0)
61{
62 wxBitmap bmp(size);
63 wxMemoryDC dc(bmp);
64 dc.SetBackground(colBg);
65 dc.Clear();
66 wxRendererNative::Get().
67 DrawTitleBarBitmap(win, dc, size, wxTITLEBAR_BUTTON_CLOSE, flags);
68 return bmp;
69}
70
71#endif // wxHAS_DRAW_TITLE_BAR_BITMAP
72
73} // anonymous namespace
74
a92b5dfe
VZ
75// ============================================================================
76// implementation
77// ============================================================================
78
ed8efd46 79void wxInfoBarGeneric::Init()
a92b5dfe
VZ
80{
81 m_icon = NULL;
82 m_text = NULL;
83 m_button = NULL;
84
3996b21a
VZ
85 m_showEffect =
86 m_hideEffect = wxSHOW_EFFECT_MAX;
a92b5dfe
VZ
87
88 // use default effect duration
89 m_effectDuration = 0;
90}
91
ed8efd46 92bool wxInfoBarGeneric::Create(wxWindow *parent, wxWindowID winid)
a92b5dfe
VZ
93{
94 // calling Hide() before Create() ensures that we're created initially
95 // hidden
96 Hide();
97 if ( !wxWindow::Create(parent, winid) )
98 return false;
99
100 // use special, easy to notice, colours
cc260804
VZ
101 const wxColour colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK);
102 SetBackgroundColour(colBg);
a92b5dfe
VZ
103 SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
104
105 // create the controls: icon, text and the button to dismiss the
106 // message.
107
108 // the icon is not shown unless it's assigned a valid bitmap
109 m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
110
a92b5dfe 111 m_text = new wxStaticText(this, wxID_ANY, "");
a92b5dfe 112
cc260804 113#ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
5c67a53d 114 const wxSize sizeBmp = wxArtProvider::GetSizeHint(wxART_BUTTON);
cc260804
VZ
115 wxBitmap bmp = GetCloseButtonBitmap(this, sizeBmp, colBg);
116#else // !wxHAS_DRAW_TITLE_BAR_BITMAP
5c67a53d 117 wxBitmap bmp = wxArtProvider::GetBitmap(wxART_CLOSE, wxART_BUTTON);
cc260804 118#endif // wxHAS_DRAW_TITLE_BAR_BITMAP
a92b5dfe
VZ
119 m_button = new wxBitmapButton
120 (
121 this,
122 wxID_ANY,
cc260804 123 bmp,
a92b5dfe
VZ
124 wxDefaultPosition,
125 wxDefaultSize,
126 wxBORDER_NONE
127 );
cc260804
VZ
128
129#ifdef wxHAS_DRAW_TITLE_BAR_BITMAP
130 m_button->SetBitmapPressed(
131 GetCloseButtonBitmap(this, sizeBmp, colBg, wxCONTROL_PRESSED));
132
133 m_button->SetBitmapCurrent(
134 GetCloseButtonBitmap(this, sizeBmp, colBg, wxCONTROL_CURRENT));
135#endif // wxHAS_DRAW_TITLE_BAR_BITMAP
136
137 m_button->SetBackgroundColour(colBg);
a92b5dfe
VZ
138 m_button->SetToolTip(_("Hide this notification message."));
139
374ae80f
VZ
140 // center the text inside the sizer with an icon to the left of it and a
141 // button at the very right
142 //
143 // NB: AddButton() relies on the button being the last control in the sizer
144 // and being preceded by a spacer
a92b5dfe 145 wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL);
bc061c8e
VZ
146 sizer->Add(m_icon, wxSizerFlags().Centre().Border());
147 sizer->Add(m_text, wxSizerFlags().Centre());
a92b5dfe 148 sizer->AddStretchSpacer();
bc061c8e 149 sizer->Add(m_button, wxSizerFlags().Centre().Border());
a92b5dfe
VZ
150 SetSizer(sizer);
151
152 return true;
153}
154
ed8efd46 155bool wxInfoBarGeneric::SetFont(const wxFont& font)
df8c364b
VZ
156{
157 if ( !wxInfoBarBase::SetFont(font) )
158 return false;
159
160 // check that we're not called before Create()
161 if ( m_text )
162 m_text->SetFont(font);
163
164 return true;
165}
166
3996b21a
VZ
167wxInfoBarGeneric::BarPlacement wxInfoBarGeneric::GetBarPlacement() const
168{
169 wxSizer * const sizer = GetContainingSizer();
170 if ( !sizer )
171 return BarPlacement_Unknown;
172
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;
178 else
179 return BarPlacement_Unknown;
180}
181
182wxShowEffect wxInfoBarGeneric::GetShowEffect() const
183{
184 if ( m_showEffect != wxSHOW_EFFECT_MAX )
185 return m_showEffect;
186
187 switch ( GetBarPlacement() )
188 {
189 case BarPlacement_Top:
190 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
191
192 case BarPlacement_Bottom:
193 return wxSHOW_EFFECT_SLIDE_TO_TOP;
194
195 default:
196 wxFAIL_MSG( "unknown info bar placement" );
197 // fall through
198
199 case BarPlacement_Unknown:
200 return wxSHOW_EFFECT_NONE;
201 }
202}
203
204wxShowEffect wxInfoBarGeneric::GetHideEffect() const
205{
206 if ( m_hideEffect != wxSHOW_EFFECT_MAX )
207 return m_hideEffect;
208
209 switch ( GetBarPlacement() )
210 {
211 case BarPlacement_Top:
212 return wxSHOW_EFFECT_SLIDE_TO_TOP;
213
214 case BarPlacement_Bottom:
215 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
216
217 default:
218 wxFAIL_MSG( "unknown info bar placement" );
219 // fall through
220
221 case BarPlacement_Unknown:
222 return wxSHOW_EFFECT_NONE;
223 }
224}
225
ed8efd46 226void wxInfoBarGeneric::UpdateParent()
a92b5dfe
VZ
227{
228 wxWindow * const parent = wxGetTopLevelParent(GetParent());
229 parent->Layout();
230}
231
ed8efd46 232void wxInfoBarGeneric::DoHide()
a92b5dfe 233{
3996b21a 234 HideWithEffect(GetHideEffect(), GetEffectDuration());
15ea6e20 235
a92b5dfe
VZ
236 UpdateParent();
237}
238
ed8efd46 239void wxInfoBarGeneric::DoShow()
a92b5dfe
VZ
240{
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)
246
247 // just change the internal flag indicating that the window is visible,
248 // without really showing it
249 wxWindowBase::Show();
250
a92b5dfe
VZ
251 // adjust the parent layout to account for us
252 UpdateParent();
253
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);
257
258
259 // finally do really show the window.
3996b21a 260 ShowWithEffect(GetShowEffect(), GetEffectDuration());
a92b5dfe
VZ
261}
262
ed8efd46 263void wxInfoBarGeneric::ShowMessage(const wxString& msg, int flags)
a92b5dfe
VZ
264{
265 // first update the controls
266 const int icon = flags & wxICON_MASK;
267 if ( !icon || (icon == wxICON_NONE) )
268 {
269 m_icon->Hide();
270 }
271 else // do show an icon
272 {
bc061c8e
VZ
273 m_icon->SetBitmap(wxArtProvider::GetBitmap(
274 wxArtProvider::GetMessageBoxIconId(flags),
5c67a53d 275 wxART_BUTTON));
a92b5dfe
VZ
276 m_icon->Show();
277 }
278
279 // notice the use of EscapeMnemonics() to ensure that "&" come through
280 // correctly
281 m_text->SetLabel(wxControl::EscapeMnemonics(msg));
282
283
284 // then show this entire window if not done yet
285 if ( !IsShown() )
286 {
287 DoShow();
288 }
289 else // we're already shown
290 {
291 // just update the layout to correspond to the new message
292 Layout();
293 }
294}
295
0b1add25
VZ
296void wxInfoBarGeneric::Dismiss()
297{
298 DoHide();
299}
300
ed8efd46 301void wxInfoBarGeneric::AddButton(wxWindowID btnid, const wxString& label)
374ae80f
VZ
302{
303 wxSizer * const sizer = GetSizer();
304 wxCHECK_RET( sizer, "must be created first" );
305
6a3f8b4f
VZ
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) )
309 {
310 m_button->Hide();
311 }
312
bccb042c
VZ
313 wxButton * const button = new wxButton(this, btnid, label);
314
315#ifdef __WXMAC__
316 // smaller buttons look better in the (narrow) info bar under OS X
317 button->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
318#endif // __WXMAC__
319
320 sizer->Add(button, wxSizerFlags().Centre().DoubleBorder());
374ae80f
VZ
321}
322
e6b2aae1
VZ
323void wxInfoBarGeneric::RemoveButton(wxWindowID btnid)
324{
325 wxSizer * const sizer = GetSizer();
326 wxCHECK_RET( sizer, "must be created first" );
327
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() )
335 {
e6b2aae1
VZ
336 const wxSizerItem * const item = node->GetData();
337
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
340 // there at all
341 if ( item->IsSpacer() )
342 {
343 wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) );
344 return;
345 }
346
347 // check if we found our button
348 if ( item->GetWindow()->GetId() == btnid )
349 {
350 delete item->GetWindow();
351 break;
352 }
353 }
6a3f8b4f
VZ
354
355 // check if there are any custom buttons left
356 if ( sizer->GetChildren().GetLast()->GetData()->IsSpacer() )
357 {
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());
361 m_button->Show();
362 }
e6b2aae1
VZ
363}
364
ed8efd46 365void wxInfoBarGeneric::OnButton(wxCommandEvent& WXUNUSED(event))
a92b5dfe
VZ
366{
367 DoHide();
368}
369
370#endif // wxUSE_INFOBAR