]> git.saurik.com Git - wxWidgets.git/blame - src/generic/infobar.cpp
Fix for #15224: wxRichTextTable: Setting a cell's text colour affects subsequent...
[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
a92b5dfe
VZ
6// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
18// for compilers that support precompilation, includes "wx.h".
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#if wxUSE_INFOBAR
26
65391c8f
PC
27#include "wx/infobar.h"
28
a92b5dfe 29#ifndef WX_PRECOMP
a92b5dfe 30 #include "wx/bmpbuttn.h"
374ae80f 31 #include "wx/button.h"
a8e87569 32 #include "wx/dcmemory.h"
a92b5dfe
VZ
33 #include "wx/settings.h"
34 #include "wx/statbmp.h"
35 #include "wx/stattext.h"
65391c8f 36 #include "wx/sizer.h"
a92b5dfe
VZ
37#endif // WX_PRECOMP
38
ed8efd46 39#include "wx/artprov.h"
a92b5dfe 40#include "wx/scopeguard.h"
a92b5dfe 41
cc7033c2
VZ
42BEGIN_EVENT_TABLE(wxInfoBarGeneric, wxInfoBarBase)
43 EVT_BUTTON(wxID_ANY, wxInfoBarGeneric::OnButton)
44END_EVENT_TABLE()
45
a92b5dfe
VZ
46// ============================================================================
47// implementation
48// ============================================================================
49
ed8efd46 50void wxInfoBarGeneric::Init()
a92b5dfe
VZ
51{
52 m_icon = NULL;
53 m_text = NULL;
54 m_button = NULL;
55
3996b21a
VZ
56 m_showEffect =
57 m_hideEffect = wxSHOW_EFFECT_MAX;
a92b5dfe
VZ
58
59 // use default effect duration
60 m_effectDuration = 0;
61}
62
ed8efd46 63bool wxInfoBarGeneric::Create(wxWindow *parent, wxWindowID winid)
a92b5dfe
VZ
64{
65 // calling Hide() before Create() ensures that we're created initially
66 // hidden
67 Hide();
68 if ( !wxWindow::Create(parent, winid) )
69 return false;
70
71 // use special, easy to notice, colours
cc260804
VZ
72 const wxColour colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK);
73 SetBackgroundColour(colBg);
a92b5dfe
VZ
74 SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
75
76 // create the controls: icon, text and the button to dismiss the
77 // message.
78
79 // the icon is not shown unless it's assigned a valid bitmap
80 m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
81
a92b5dfe 82 m_text = new wxStaticText(this, wxID_ANY, "");
a92b5dfe 83
a68fb3fc 84 m_button = wxBitmapButton::NewCloseButton(this, wxID_ANY);
a92b5dfe
VZ
85 m_button->SetToolTip(_("Hide this notification message."));
86
374ae80f
VZ
87 // center the text inside the sizer with an icon to the left of it and a
88 // button at the very right
89 //
90 // NB: AddButton() relies on the button being the last control in the sizer
91 // and being preceded by a spacer
a92b5dfe 92 wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL);
bc061c8e
VZ
93 sizer->Add(m_icon, wxSizerFlags().Centre().Border());
94 sizer->Add(m_text, wxSizerFlags().Centre());
a92b5dfe 95 sizer->AddStretchSpacer();
bc061c8e 96 sizer->Add(m_button, wxSizerFlags().Centre().Border());
a92b5dfe
VZ
97 SetSizer(sizer);
98
99 return true;
100}
101
ed8efd46 102bool wxInfoBarGeneric::SetFont(const wxFont& font)
df8c364b
VZ
103{
104 if ( !wxInfoBarBase::SetFont(font) )
105 return false;
106
107 // check that we're not called before Create()
108 if ( m_text )
109 m_text->SetFont(font);
110
111 return true;
112}
113
3996b21a
VZ
114wxInfoBarGeneric::BarPlacement wxInfoBarGeneric::GetBarPlacement() const
115{
116 wxSizer * const sizer = GetContainingSizer();
117 if ( !sizer )
118 return BarPlacement_Unknown;
119
21d5ec7d
VZ
120 // FIXME-VC6: can't compare "const wxInfoBarGeneric *" and "wxWindow *",
121 // so need this workaround
122 wxWindow * const self = const_cast<wxInfoBarGeneric *>(this);
3996b21a 123 const wxSizerItemList& siblings = sizer->GetChildren();
21d5ec7d 124 if ( siblings.GetFirst()->GetData()->GetWindow() == self )
3996b21a 125 return BarPlacement_Top;
21d5ec7d 126 else if ( siblings.GetLast()->GetData()->GetWindow() == self )
3996b21a
VZ
127 return BarPlacement_Bottom;
128 else
129 return BarPlacement_Unknown;
130}
131
132wxShowEffect wxInfoBarGeneric::GetShowEffect() const
133{
134 if ( m_showEffect != wxSHOW_EFFECT_MAX )
135 return m_showEffect;
136
137 switch ( GetBarPlacement() )
138 {
139 case BarPlacement_Top:
140 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
141
142 case BarPlacement_Bottom:
143 return wxSHOW_EFFECT_SLIDE_TO_TOP;
144
145 default:
146 wxFAIL_MSG( "unknown info bar placement" );
147 // fall through
148
149 case BarPlacement_Unknown:
150 return wxSHOW_EFFECT_NONE;
151 }
152}
153
154wxShowEffect wxInfoBarGeneric::GetHideEffect() const
155{
156 if ( m_hideEffect != wxSHOW_EFFECT_MAX )
157 return m_hideEffect;
158
159 switch ( GetBarPlacement() )
160 {
161 case BarPlacement_Top:
162 return wxSHOW_EFFECT_SLIDE_TO_TOP;
163
164 case BarPlacement_Bottom:
165 return wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
166
167 default:
168 wxFAIL_MSG( "unknown info bar placement" );
169 // fall through
170
171 case BarPlacement_Unknown:
172 return wxSHOW_EFFECT_NONE;
173 }
174}
175
ed8efd46 176void wxInfoBarGeneric::UpdateParent()
a92b5dfe 177{
f0bae4ba 178 wxWindow * const parent = GetParent();
a92b5dfe
VZ
179 parent->Layout();
180}
181
ed8efd46 182void wxInfoBarGeneric::DoHide()
a92b5dfe 183{
3996b21a 184 HideWithEffect(GetHideEffect(), GetEffectDuration());
15ea6e20 185
a92b5dfe
VZ
186 UpdateParent();
187}
188
ed8efd46 189void wxInfoBarGeneric::DoShow()
a92b5dfe
VZ
190{
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)
196
197 // just change the internal flag indicating that the window is visible,
198 // without really showing it
199 wxWindowBase::Show();
200
a92b5dfe
VZ
201 // adjust the parent layout to account for us
202 UpdateParent();
203
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);
207
208
209 // finally do really show the window.
3996b21a 210 ShowWithEffect(GetShowEffect(), GetEffectDuration());
a92b5dfe
VZ
211}
212
ed8efd46 213void wxInfoBarGeneric::ShowMessage(const wxString& msg, int flags)
a92b5dfe
VZ
214{
215 // first update the controls
216 const int icon = flags & wxICON_MASK;
217 if ( !icon || (icon == wxICON_NONE) )
218 {
219 m_icon->Hide();
220 }
221 else // do show an icon
222 {
bc061c8e
VZ
223 m_icon->SetBitmap(wxArtProvider::GetBitmap(
224 wxArtProvider::GetMessageBoxIconId(flags),
5c67a53d 225 wxART_BUTTON));
a92b5dfe
VZ
226 m_icon->Show();
227 }
228
229 // notice the use of EscapeMnemonics() to ensure that "&" come through
230 // correctly
231 m_text->SetLabel(wxControl::EscapeMnemonics(msg));
232
233
234 // then show this entire window if not done yet
235 if ( !IsShown() )
236 {
237 DoShow();
238 }
239 else // we're already shown
240 {
241 // just update the layout to correspond to the new message
242 Layout();
243 }
244}
245
0b1add25
VZ
246void wxInfoBarGeneric::Dismiss()
247{
248 DoHide();
249}
250
ed8efd46 251void wxInfoBarGeneric::AddButton(wxWindowID btnid, const wxString& label)
374ae80f
VZ
252{
253 wxSizer * const sizer = GetSizer();
254 wxCHECK_RET( sizer, "must be created first" );
255
6a3f8b4f
VZ
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) )
259 {
260 m_button->Hide();
261 }
262
bccb042c
VZ
263 wxButton * const button = new wxButton(this, btnid, label);
264
265#ifdef __WXMAC__
266 // smaller buttons look better in the (narrow) info bar under OS X
267 button->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
268#endif // __WXMAC__
269
270 sizer->Add(button, wxSizerFlags().Centre().DoubleBorder());
374ae80f
VZ
271}
272
e6b2aae1
VZ
273void wxInfoBarGeneric::RemoveButton(wxWindowID btnid)
274{
275 wxSizer * const sizer = GetSizer();
276 wxCHECK_RET( sizer, "must be created first" );
277
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() )
285 {
e6b2aae1
VZ
286 const wxSizerItem * const item = node->GetData();
287
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
290 // there at all
291 if ( item->IsSpacer() )
292 {
293 wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) );
294 return;
295 }
296
297 // check if we found our button
298 if ( item->GetWindow()->GetId() == btnid )
299 {
300 delete item->GetWindow();
301 break;
302 }
303 }
6a3f8b4f
VZ
304
305 // check if there are any custom buttons left
306 if ( sizer->GetChildren().GetLast()->GetData()->IsSpacer() )
307 {
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());
311 m_button->Show();
312 }
e6b2aae1
VZ
313}
314
ed8efd46 315void wxInfoBarGeneric::OnButton(wxCommandEvent& WXUNUSED(event))
a92b5dfe
VZ
316{
317 DoHide();
318}
319
320#endif // wxUSE_INFOBAR