Made wxInfoBar::SetFont() change the text message font.
[wxWidgets.git] / src / generic / infobar.cpp
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
29 #include "wx/artprov.h"
30 #include "wx/bmpbuttn.h"
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
38 #include "wx/scopeguard.h"
39 #include "wx/sizer.h"
40
41 // ============================================================================
42 // implementation
43 // ============================================================================
44
45 void wxInfoBar::Init()
46 {
47 m_icon = NULL;
48 m_text = NULL;
49 m_button = NULL;
50
51 m_showEffect = wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
52 m_hideEffect = wxSHOW_EFFECT_SLIDE_TO_TOP;
53
54 // use default effect duration
55 m_effectDuration = 0;
56 }
57
58 bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid)
59 {
60 // calling Hide() before Create() ensures that we're created initially
61 // hidden
62 Hide();
63 if ( !wxWindow::Create(parent, winid) )
64 return false;
65
66 // use special, easy to notice, colours
67 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
68 SetOwnForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
69
70 // create the controls: icon, text and the button to dismiss the
71 // message.
72
73 // the icon is not shown unless it's assigned a valid bitmap
74 m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
75
76 // by default, the text uses a larger, more noticeable, font
77 m_text = new wxStaticText(this, wxID_ANY, "");
78 m_text->SetFont(m_text->GetFont().Bold().Larger());
79
80 m_button = new wxBitmapButton
81 (
82 this,
83 wxID_ANY,
84 wxArtProvider::GetBitmap(wxART_CROSS_MARK),
85 wxDefaultPosition,
86 wxDefaultSize,
87 wxBORDER_NONE
88 );
89 m_button->SetToolTip(_("Hide this notification message."));
90
91 Connect
92 (
93 wxEVT_COMMAND_BUTTON_CLICKED,
94 wxCommandEventHandler(wxInfoBar::OnButton),
95 NULL,
96 this
97 );
98
99 // Center the text inside the sizer.
100 wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL);
101 sizer->AddStretchSpacer();
102 sizer->Add(m_icon, wxSizerFlags().Centre().DoubleBorder());
103 sizer->Add(m_text, wxSizerFlags().Centre().DoubleBorder());
104 sizer->AddStretchSpacer();
105 sizer->Add(m_button, wxSizerFlags().Centre().DoubleBorder());
106 SetSizer(sizer);
107
108 return true;
109 }
110
111 bool wxInfoBar::SetFont(const wxFont& font)
112 {
113 if ( !wxInfoBarBase::SetFont(font) )
114 return false;
115
116 // check that we're not called before Create()
117 if ( m_text )
118 m_text->SetFont(font);
119
120 return true;
121 }
122
123 void wxInfoBar::UpdateParent()
124 {
125 wxWindow * const parent = wxGetTopLevelParent(GetParent());
126 parent->Layout();
127 }
128
129 void wxInfoBar::ChangeParentBackground()
130 {
131 wxWindow * const parent = GetParent();
132 m_origParentBgCol = parent->GetBackgroundColour();
133
134 wxSizer * const sizer = GetContainingSizer();
135 if ( !sizer )
136 return;
137
138 wxWindow *sibling = NULL;
139 for ( wxSizerItemList::compatibility_iterator
140 node = sizer->GetChildren().GetFirst();
141 node;
142 node = node->GetNext() )
143 {
144 if ( node->GetData()->GetWindow() == this )
145 {
146 // find the next window following us
147 for ( node = node->GetNext();
148 node;
149 node = node->GetNext() )
150 {
151 wxSizerItem * const item = node->GetData();
152 if ( item->IsWindow() )
153 {
154 sibling = item->GetWindow();
155 break;
156 }
157 }
158
159 break;
160 }
161 }
162
163 if ( sibling )
164 parent->SetOwnBackgroundColour(sibling->GetBackgroundColour());
165 }
166
167 void wxInfoBar::RestoreParentBackground()
168 {
169 GetParent()->SetOwnBackgroundColour(m_origParentBgCol);
170 }
171
172 void wxInfoBar::DoHide()
173 {
174 ChangeParentBackground();
175 wxON_BLOCK_EXIT_THIS0( wxInfoBar::RestoreParentBackground );
176
177 HideWithEffect(m_hideEffect, m_effectDuration);
178 UpdateParent();
179 }
180
181 void wxInfoBar::DoShow()
182 {
183 // re-layout the parent first so that the window expands into an already
184 // unoccupied by the other controls area: for this we need to change our
185 // internal visibility flag to force Layout() to take us into account (an
186 // alternative solution to this hack would be to temporarily set
187 // wxRESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really batter)
188
189 // just change the internal flag indicating that the window is visible,
190 // without really showing it
191 wxWindowBase::Show();
192
193 // an extra hack: we want the temporarily uncovered area in which we're
194 // going to expand to look like part of this sibling for a better effect so
195 // temporarily change the background of our parent to the same colour
196 ChangeParentBackground();
197 wxON_BLOCK_EXIT_THIS0( wxInfoBar::RestoreParentBackground );
198
199 // adjust the parent layout to account for us
200 UpdateParent();
201
202 // reset the flag back before really showing the window or it wouldn't be
203 // shown at all because it would believe itself already visible
204 wxWindowBase::Show(false);
205
206
207 // finally do really show the window.
208 ShowWithEffect(m_showEffect, m_effectDuration);
209 }
210
211 void wxInfoBar::ShowMessage(const wxString& msg, int flags)
212 {
213 // first update the controls
214 const int icon = flags & wxICON_MASK;
215 if ( !icon || (icon == wxICON_NONE) )
216 {
217 m_icon->Hide();
218 }
219 else // do show an icon
220 {
221 m_icon->SetBitmap(wxArtProvider::GetMessageBoxIcon(icon));
222 m_icon->Show();
223 }
224
225 // notice the use of EscapeMnemonics() to ensure that "&" come through
226 // correctly
227 m_text->SetLabel(wxControl::EscapeMnemonics(msg));
228
229
230 // then show this entire window if not done yet
231 if ( !IsShown() )
232 {
233 DoShow();
234 }
235 else // we're already shown
236 {
237 // just update the layout to correspond to the new message
238 Layout();
239 }
240 }
241
242 void wxInfoBar::OnButton(wxCommandEvent& WXUNUSED(event))
243 {
244 DoHide();
245 }
246
247 #endif // wxUSE_INFOBAR