1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/statbar.cpp
3 // Purpose: wxStatusBarBase implementation
4 // Author: Vadim Zeitlin
5 // Modified by: Francesco Montorsi
6 // Created: 14.10.01
7 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
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
23 #if wxUSE_STATUSBAR
24
25 #include "wx/statusbr.h"
26
27 #ifndef WX_PRECOMP
28 #include "wx/frame.h"
29 #endif //WX_PRECOMP
30
31 const char wxStatusBarNameStr[] = "statusBar";
32
33 // ============================================================================
34 // wxStatusBarPane implementation
35 // ============================================================================
36
SetText(const wxString & text)37 bool wxStatusBarPane::SetText(const wxString& text)
38 {
39 if ( text == m_text )
40 return false;
41
42 /*
43 If we have a message to restore on the stack, we update it to
44 correspond to the current one so that a sequence of calls such as
45
46 1. SetStatusText("foo")
47 2. PushStatusText("bar")
48 3. SetStatusText("new foo")
49 4. PopStatusText()
50
51 doesn't overwrite the "new foo" which should be shown at the end with
52 the old value "foo". This would be unexpected and hard to avoid,
53 especially when PushStatusText() is used internally by wxWidgets
54 without knowledge of the user program, as it is for showing the menu
55 and toolbar help strings.
56
57 By updating the top of the stack we ensure that the next call to
58 PopStatusText() basically becomes a NOP without breaking the balance
59 between the calls to push and pop as we would have done if we really
60 called PopStatusText() here.
61 */
62 if ( !m_arrStack.empty() )
63 {
64 m_arrStack.back() = text;
65 }
66
67 m_text = text;
68
69 return true;
70 }
71
PushText(const wxString & text)72 bool wxStatusBarPane::PushText(const wxString& text)
73 {
74 // save the currently shown text
75 m_arrStack.push_back(m_text);
76
77 // and update the new one if necessary
78 if ( text == m_text )
79 return false;
80
81 m_text = text;
82
83 return true;
84 }
85
PopText()86 bool wxStatusBarPane::PopText()
87 {
88 wxCHECK_MSG( !m_arrStack.empty(), false, "no status message to pop" );
89
90 const wxString text = m_arrStack.back();
91
92 m_arrStack.pop_back();
93
94 if ( text == m_text )
95 return false;
96
97 m_text = text;
98
99 return true;
100 }
101
102 // ============================================================================
103 // wxStatusBarBase implementation
104 // ============================================================================
105
106 wxIMPLEMENT_DYNAMIC_CLASS(wxStatusBar, wxWindow);
107
108 #include "wx/arrimpl.cpp" // This is a magic incantation which must be done!
WX_DEFINE_EXPORTED_OBJARRAY(wxStatusBarPaneArray)109 WX_DEFINE_EXPORTED_OBJARRAY(wxStatusBarPaneArray)
110
111
112 // ----------------------------------------------------------------------------
113 // ctor/dtor
114 // ----------------------------------------------------------------------------
115
116 wxStatusBarBase::wxStatusBarBase()
117 {
118 m_bSameWidthForAllPanes = true;
119 }
120
~wxStatusBarBase()121 wxStatusBarBase::~wxStatusBarBase()
122 {
123 // notify the frame that it doesn't have a status bar any longer to avoid
124 // dangling pointers
125 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
126 if ( frame && frame->GetStatusBar() == this )
127 frame->SetStatusBar(NULL);
128 }
129
130 // ----------------------------------------------------------------------------
131 // field widths
132 // ----------------------------------------------------------------------------
133
SetFieldsCount(int number,const int * widths)134 void wxStatusBarBase::SetFieldsCount(int number, const int *widths)
135 {
136 wxCHECK_RET( number > 0, wxT("invalid field number in SetFieldsCount") );
137
138 if ( (size_t)number > m_panes.GetCount() )
139 {
140 wxStatusBarPane newPane;
141
142 // add more entries with the default style and zero width
143 // (this will be set later)
144 for (size_t i = m_panes.GetCount(); i < (size_t)number; ++i)
145 m_panes.Add(newPane);
146 }
147 else if ( (size_t)number < m_panes.GetCount() )
148 {
149 // remove entries in excess
150 m_panes.RemoveAt(number, m_panes.GetCount()-number);
151 }
152
153 // SetStatusWidths will automatically refresh
154 SetStatusWidths(number, widths);
155 }
156
SetStatusWidths(int WXUNUSED_UNLESS_DEBUG (n),const int widths[])157 void wxStatusBarBase::SetStatusWidths(int WXUNUSED_UNLESS_DEBUG(n),
158 const int widths[])
159 {
160 wxASSERT_MSG( (size_t)n == m_panes.GetCount(), wxT("field number mismatch") );
161
162 if (widths == NULL)
163 {
164 // special value meaning: override explicit pane widths and make them all
165 // of the same size
166 m_bSameWidthForAllPanes = true;
167 }
168 else
169 {
170 for ( size_t i = 0; i < m_panes.GetCount(); i++ )
171 m_panes[i].SetWidth(widths[i]);
172
173 m_bSameWidthForAllPanes = false;
174 }
175
176 // update the display after the widths changed
177 Refresh();
178 }
179
SetStatusStyles(int WXUNUSED_UNLESS_DEBUG (n),const int styles[])180 void wxStatusBarBase::SetStatusStyles(int WXUNUSED_UNLESS_DEBUG(n),
181 const int styles[])
182 {
183 wxCHECK_RET( styles, wxT("NULL pointer in SetStatusStyles") );
184
185 wxASSERT_MSG( (size_t)n == m_panes.GetCount(), wxT("field number mismatch") );
186
187 for ( size_t i = 0; i < m_panes.GetCount(); i++ )
188 m_panes[i].SetStyle(styles[i]);
189
190 // update the display after the widths changed
191 Refresh();
192 }
193
CalculateAbsWidths(wxCoord widthTotal) const194 wxArrayInt wxStatusBarBase::CalculateAbsWidths(wxCoord widthTotal) const
195 {
196 wxArrayInt widths;
197
198 if ( m_bSameWidthForAllPanes )
199 {
200 // Default: all fields have the same width. This is not always
201 // possible to do exactly (if widthTotal is not divisible by
202 // m_panes.GetCount()) - if that happens, we distribute the extra
203 // pixels among all fields:
204 int widthToUse = widthTotal;
205
206 for ( size_t i = m_panes.GetCount(); i > 0; i-- )
207 {
208 // divide the unassigned width evently between the
209 // not yet processed fields:
210 int w = widthToUse / i;
211 widths.Add(w);
212 widthToUse -= w;
213 }
214 }
215 else // do not override explicit pane widths
216 {
217 // calculate the total width of all the fixed width fields and the
218 // total number of var field widths counting with multiplicity
219 size_t nTotalWidth = 0,
220 nVarCount = 0,
221 i;
222
223 for ( i = 0; i < m_panes.GetCount(); i++ )
224 {
225 if ( m_panes[i].GetWidth() >= 0 )
226 nTotalWidth += m_panes[i].GetWidth();
227 else
228 nVarCount += -m_panes[i].GetWidth();
229 }
230
231 // the amount of extra width we have per each var width field
232 int widthExtra = widthTotal - nTotalWidth;
233
234 // do fill the array
235 for ( i = 0; i < m_panes.GetCount(); i++ )
236 {
237 if ( m_panes[i].GetWidth() >= 0 )
238 widths.Add(m_panes[i].GetWidth());
239 else
240 {
241 int nVarWidth = widthExtra > 0 ? (widthExtra * (-m_panes[i].GetWidth())) / nVarCount : 0;
242 nVarCount += m_panes[i].GetWidth();
243 widthExtra -= nVarWidth;
244 widths.Add(nVarWidth);
245 }
246 }
247 }
248
249 return widths;
250 }
251
252 // ----------------------------------------------------------------------------
253 // setting/getting status text
254 // ----------------------------------------------------------------------------
255
SetStatusText(const wxString & text,int number)256 void wxStatusBarBase::SetStatusText(const wxString& text, int number)
257 {
258 wxCHECK_RET( (unsigned)number < m_panes.size(),
259 "invalid status bar field index" );
260
261 if ( m_panes[number].SetText(text) )
262 DoUpdateStatusText(number);
263 }
264
GetStatusText(int number) const265 wxString wxStatusBarBase::GetStatusText(int number) const
266 {
267 wxCHECK_MSG( (unsigned)number < m_panes.size(), wxString(),
268 "invalid status bar field index" );
269
270 return m_panes[number].GetText();
271 }
272
SetEllipsizedFlag(int number,bool isEllipsized)273 void wxStatusBarBase::SetEllipsizedFlag(int number, bool isEllipsized)
274 {
275 wxCHECK_RET( (unsigned)number < m_panes.size(),
276 "invalid status bar field index" );
277
278 m_panes[number].SetIsEllipsized(isEllipsized);
279 }
280
281 // ----------------------------------------------------------------------------
282 // pushing/popping status text
283 // ----------------------------------------------------------------------------
284
PushStatusText(const wxString & text,int number)285 void wxStatusBarBase::PushStatusText(const wxString& text, int number)
286 {
287 wxCHECK_RET( (unsigned)number < m_panes.size(),
288 "invalid status bar field index" );
289
290 if ( m_panes[number].PushText(text) )
291 DoUpdateStatusText(number);
292 }
293
PopStatusText(int number)294 void wxStatusBarBase::PopStatusText(int number)
295 {
296 wxCHECK_RET( (unsigned)number < m_panes.size(),
297 "invalid status bar field index" );
298
299 if ( m_panes[number].PopText() )
300 DoUpdateStatusText(number);
301 }
302
303 #endif // wxUSE_STATUSBAR
304