]> git.saurik.com Git - wxWidgets.git/blob - src/common/statbar.cpp
fix memory leak when using styes (closes 1086273)
[wxWidgets.git] / src / common / statbar.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: common/statbar.cpp
3 // Purpose: wxStatusBarBase implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 14.10.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "statbar.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/frame.h"
33 #include "wx/statusbr.h"
34 #endif //WX_PRECOMP
35
36 #if wxUSE_STATUSBAR
37
38 #include "wx/listimpl.cpp"
39 WX_DEFINE_LIST(wxListString);
40
41 // ============================================================================
42 // wxStatusBarBase implementation
43 // ============================================================================
44
45 IMPLEMENT_DYNAMIC_CLASS(wxStatusBar, wxWindow)
46
47 // ----------------------------------------------------------------------------
48 // ctor/dtor
49 // ----------------------------------------------------------------------------
50
51 wxStatusBarBase::wxStatusBarBase()
52 {
53 m_nFields = 0;
54
55 InitWidths();
56 InitStacks();
57 InitStyles();
58 }
59
60 wxStatusBarBase::~wxStatusBarBase()
61 {
62 FreeWidths();
63 FreeStacks();
64 FreeStyles();
65
66 // notify the frame that it doesn't have a status bar any longer to avoid
67 // dangling pointers
68 wxFrameBase *frame = wxDynamicCast(GetParent(), wxFrameBase);
69 if ( frame && frame->GetStatusBar() == this )
70 {
71 frame->SetStatusBar(NULL);
72 }
73 }
74
75 // ----------------------------------------------------------------------------
76 // widths array handling
77 // ----------------------------------------------------------------------------
78
79 void wxStatusBarBase::InitWidths()
80 {
81 m_statusWidths = NULL;
82 }
83
84 void wxStatusBarBase::FreeWidths()
85 {
86 delete [] m_statusWidths;
87 }
88
89 // ----------------------------------------------------------------------------
90 // styles array handling
91 // ----------------------------------------------------------------------------
92
93 void wxStatusBarBase::InitStyles()
94 {
95 m_statusStyles = NULL;
96 }
97
98 void wxStatusBarBase::FreeStyles()
99 {
100 delete [] m_statusStyles;
101 }
102
103 // ----------------------------------------------------------------------------
104 // field widths
105 // ----------------------------------------------------------------------------
106
107 void wxStatusBarBase::SetFieldsCount(int number, const int *widths)
108 {
109 wxCHECK_RET( number > 0, _T("invalid field number in SetFieldsCount") );
110
111 bool refresh = false;
112
113 if ( number != m_nFields )
114 {
115 // copy stacks if present
116 if(m_statusTextStacks)
117 {
118 wxListString **newStacks = new wxListString*[number];
119 size_t i, j, max = wxMin(number, m_nFields);
120
121 // copy old stacks
122 for(i = 0; i < max; ++i)
123 newStacks[i] = m_statusTextStacks[i];
124 // free old stacks in excess
125 for(j = i; j < (size_t)m_nFields; ++j)
126 {
127 if(m_statusTextStacks[j])
128 {
129 m_statusTextStacks[j]->Clear();
130 delete m_statusTextStacks[j];
131 }
132 }
133 // initialize new stacks to NULL
134 for(j = i; j < (size_t)number; ++j)
135 newStacks[j] = 0;
136
137 m_statusTextStacks = newStacks;
138 }
139
140 // Resize styles array
141 if (m_statusStyles)
142 {
143 int *oldStyles = m_statusStyles;
144 m_statusStyles = new int[number];
145 int i, max = wxMin(number, m_nFields);
146
147 // copy old styles
148 for (i = 0; i < max; ++i)
149 m_statusStyles[i] = oldStyles[i];
150
151 // initialize new styles to wxSB_NORMAL
152 for (i = max; i < number; ++i)
153 m_statusStyles[i] = wxSB_NORMAL;
154
155 // free old styles
156 delete [] oldStyles;
157 }
158
159
160 m_nFields = number;
161
162 ReinitWidths();
163
164 refresh = true;
165 }
166 //else: keep the old m_statusWidths if we had them
167
168 if ( widths )
169 {
170 SetStatusWidths(number, widths);
171
172 // already done from SetStatusWidths()
173 refresh = false;
174 }
175
176 if ( refresh )
177 Refresh();
178 }
179
180 void wxStatusBarBase::SetStatusWidths(int WXUNUSED_UNLESS_DEBUG(n),
181 const int widths[])
182 {
183 wxCHECK_RET( widths, _T("NULL pointer in SetStatusWidths") );
184
185 wxASSERT_MSG( n == m_nFields, _T("field number mismatch") );
186
187 if ( !m_statusWidths )
188 m_statusWidths = new int[m_nFields];
189
190 for ( int i = 0; i < m_nFields; i++ )
191 {
192 m_statusWidths[i] = widths[i];
193 }
194
195 // update the display after the widths changed
196 Refresh();
197 }
198
199 void wxStatusBarBase::SetStatusStyles(int WXUNUSED_UNLESS_DEBUG(n),
200 const int styles[])
201 {
202 wxCHECK_RET( styles, _T("NULL pointer in SetStatusStyles") );
203
204 wxASSERT_MSG( n == m_nFields, _T("field number mismatch") );
205
206 if ( !m_statusStyles )
207 m_statusStyles = new int[m_nFields];
208
209 for ( int i = 0; i < m_nFields; i++ )
210 {
211 m_statusStyles[i] = styles[i];
212 }
213
214 // update the display after the widths changed
215 Refresh();
216 }
217
218 wxArrayInt wxStatusBarBase::CalculateAbsWidths(wxCoord widthTotal) const
219 {
220 wxArrayInt widths;
221
222 if ( m_statusWidths == NULL )
223 {
224 if ( m_nFields )
225 {
226 // default: all fields have the same width
227 int nWidth = widthTotal / m_nFields;
228 for ( int i = 0; i < m_nFields; i++ )
229 {
230 widths.Add(nWidth);
231 }
232 }
233 //else: we're empty anyhow
234 }
235 else // have explicit status widths
236 {
237 // calculate the total width of all the fixed width fields and the
238 // total number of var field widths counting with multiplicity
239 int nTotalWidth = 0,
240 nVarCount = 0,
241 i;
242 for ( i = 0; i < m_nFields; i++ )
243 {
244 if ( m_statusWidths[i] >= 0 )
245 {
246 nTotalWidth += m_statusWidths[i];
247 }
248 else
249 {
250 nVarCount += -m_statusWidths[i];
251 }
252 }
253
254 // the amount of extra width we have per each var width field
255 int widthExtra = widthTotal - nTotalWidth;
256
257 // do fill the array
258 for ( i = 0; i < m_nFields; i++ )
259 {
260 if ( m_statusWidths[i] >= 0 )
261 {
262 widths.Add(m_statusWidths[i]);
263 }
264 else
265 {
266 int nVarWidth = widthExtra > 0 ? (widthExtra * -m_statusWidths[i]) / nVarCount : 0;
267 nVarCount += m_statusWidths[i];
268 widthExtra -= nVarWidth;
269 widths.Add(nVarWidth);
270 }
271 }
272 }
273
274 return widths;
275 }
276
277 // ----------------------------------------------------------------------------
278 // text stacks handling
279 // ----------------------------------------------------------------------------
280
281 void wxStatusBarBase::InitStacks()
282 {
283 m_statusTextStacks = NULL;
284 }
285
286 void wxStatusBarBase::FreeStacks()
287 {
288 if ( !m_statusTextStacks )
289 return;
290
291 for ( size_t i = 0; i < (size_t)m_nFields; ++i )
292 {
293 if ( m_statusTextStacks[i] )
294 {
295 wxListString& t = *m_statusTextStacks[i];
296 WX_CLEAR_LIST(wxListString, t);
297 delete m_statusTextStacks[i];
298 }
299 }
300
301 delete[] m_statusTextStacks;
302 }
303
304 // ----------------------------------------------------------------------------
305 // text stacks
306 // ----------------------------------------------------------------------------
307
308 void wxStatusBarBase::PushStatusText(const wxString& text, int number)
309 {
310 wxListString* st = GetOrCreateStatusStack(number);
311 // This long-winded way around avoids an internal compiler error
312 // in VC++ 6 with RTTI enabled
313 wxString tmp1(GetStatusText(number));
314 wxString* tmp = new wxString(tmp1);
315 st->Insert(tmp);
316 SetStatusText(text, number);
317 }
318
319 void wxStatusBarBase::PopStatusText(int number)
320 {
321 wxListString *st = GetStatusStack(number);
322 wxCHECK_RET( st, _T("Unbalanced PushStatusText/PopStatusText") );
323 wxListString::compatibility_iterator top = st->GetFirst();
324
325 SetStatusText(*top->GetData(), number);
326 delete top->GetData();
327 st->Erase(top);
328 if(st->GetCount() == 0)
329 {
330 delete st;
331 m_statusTextStacks[number] = 0;
332 }
333 }
334
335 wxListString *wxStatusBarBase::GetStatusStack(int i) const
336 {
337 if(!m_statusTextStacks)
338 return 0;
339 return m_statusTextStacks[i];
340 }
341
342 wxListString *wxStatusBarBase::GetOrCreateStatusStack(int i)
343 {
344 if(!m_statusTextStacks)
345 {
346 m_statusTextStacks = new wxListString*[m_nFields];
347
348 size_t j;
349 for(j = 0; j < (size_t)m_nFields; ++j) m_statusTextStacks[j] = 0;
350 }
351
352 if(!m_statusTextStacks[i])
353 {
354 m_statusTextStacks[i] = new wxListString();
355 }
356
357 return m_statusTextStacks[i];
358 }
359
360 #endif // wxUSE_STATUSBAR
361