fixed fatal bug in wxStatusBar::SetFieldsCount(), added demo of it to the sample
[wxWidgets.git] / samples / statbar / statbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: statbar.cpp
3 // Purpose: wxStatusBar sample
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 04.02.00
7 // RCS-ID: $Id$
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "statbar.cpp"
22 #pragma interface "statbar.cpp"
23 #endif
24
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
27
28 #ifdef __BORLANDC__
29 #pragma hdrstop
30 #endif
31
32 #if !wxUSE_STATUSBAR
33 #error "You need to set wxUSE_STATUSBAR to 1 to compile this sample"
34 #endif // wxUSE_STATUSBAR
35
36 // for all others, include the necessary headers (this file is usually all you
37 // need because it includes almost all "standard" wxWindows headers
38 #ifndef WX_PRECOMP
39 #include "wx/app.h"
40 #include "wx/frame.h"
41 #include "wx/statusbr.h"
42 #include "wx/timer.h"
43 #include "wx/checkbox.h"
44 #include "wx/statbmp.h"
45 #include "wx/menu.h"
46 #include "wx/msgdlg.h"
47 #include "wx/textdlg.h"
48 #endif
49
50 #include "wx/datetime.h"
51
52 // ----------------------------------------------------------------------------
53 // resources
54 // ----------------------------------------------------------------------------
55
56 #include "green.xpm"
57 #include "red.xpm"
58
59 // ----------------------------------------------------------------------------
60 // private classes
61 // ----------------------------------------------------------------------------
62
63 // Define a new application type, each program should derive a class from wxApp
64 class MyApp : public wxApp
65 {
66 public:
67 // override base class virtuals
68 // ----------------------------
69
70 // this one is called on application startup and is a good place for the app
71 // initialization (doing it here and not in the ctor allows to have an error
72 // return: if OnInit() returns false, the application terminates)
73 virtual bool OnInit();
74 };
75
76 // A custom status bar which contains controls, icons &c
77 class MyStatusBar : public wxStatusBar
78 {
79 public:
80 MyStatusBar(wxWindow *parent);
81 virtual ~MyStatusBar();
82
83 void UpdateClock();
84
85 // event handlers
86 void OnTimer(wxTimerEvent& event) { UpdateClock(); }
87 void OnSize(wxSizeEvent& event);
88 void OnToggleClock(wxCommandEvent& event);
89
90 private:
91 enum
92 {
93 Field_Text,
94 Field_Checkbox,
95 Field_Bitmap,
96 Field_Clock,
97 Field_Max
98 };
99
100 wxTimer m_timer;
101
102 wxCheckBox *m_checkbox;
103 wxStaticBitmap *m_statbmp;
104
105 DECLARE_EVENT_TABLE()
106 };
107
108 // Define a new frame type: this is going to be our main frame
109 class MyFrame : public wxFrame
110 {
111 public:
112 // ctor(s)
113 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
114 virtual ~MyFrame();
115
116 // event handlers (these functions should _not_ be virtual)
117 void OnQuit(wxCommandEvent& event);
118 void OnAbout(wxCommandEvent& event);
119
120 void OnSetStatusFields(wxCommandEvent& event);
121 void OnRecreateStatusBar(wxCommandEvent& event);
122
123 private:
124 enum StatBarKind
125 {
126 StatBar_Default,
127 StatBar_Custom,
128 StatBar_Max
129 } m_statbarKind;
130
131 void DoCreateStatusBar(StatBarKind kind);
132
133 wxStatusBar *m_statbarDefault;
134 MyStatusBar *m_statbarCustom;
135
136 // any class wishing to process wxWindows events must use this macro
137 DECLARE_EVENT_TABLE()
138 };
139
140 // ----------------------------------------------------------------------------
141 // constants
142 // ----------------------------------------------------------------------------
143
144 // IDs for the controls and the menu commands
145 enum
146 {
147 // menu items
148 StatusBar_Quit = 1,
149 StatusBar_SetFields,
150 StatusBar_Recreate,
151 StatusBar_About,
152 StatusBar_Checkbox = 1000
153 };
154
155 static const int BITMAP_SIZE_X = 32;
156 static const int BITMAP_SIZE_Y = 15;
157
158 // ----------------------------------------------------------------------------
159 // event tables and other macros for wxWindows
160 // ----------------------------------------------------------------------------
161
162 // the event tables connect the wxWindows events with the functions (event
163 // handlers) which process them. It can be also done at run-time, but for the
164 // simple menu events like this the static method is much simpler.
165 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
166 EVT_MENU(StatusBar_Quit, MyFrame::OnQuit)
167 EVT_MENU(StatusBar_SetFields, MyFrame::OnSetStatusFields)
168 EVT_MENU(StatusBar_Recreate, MyFrame::OnRecreateStatusBar)
169 EVT_MENU(StatusBar_About, MyFrame::OnAbout)
170 END_EVENT_TABLE()
171
172 BEGIN_EVENT_TABLE(MyStatusBar, wxStatusBar)
173 EVT_SIZE(MyStatusBar::OnSize)
174 EVT_CHECKBOX(StatusBar_Checkbox, MyStatusBar::OnToggleClock)
175 EVT_TIMER(-1, MyStatusBar::OnTimer)
176 END_EVENT_TABLE()
177
178 // Create a new application object: this macro will allow wxWindows to create
179 // the application object during program execution (it's better than using a
180 // static object for many reasons) and also declares the accessor function
181 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
182 // not wxApp)
183 IMPLEMENT_APP(MyApp)
184
185 // ============================================================================
186 // implementation
187 // ============================================================================
188
189 // ----------------------------------------------------------------------------
190 // the application class
191 // ----------------------------------------------------------------------------
192
193 // `Main program' equivalent: the program execution "starts" here
194 bool MyApp::OnInit()
195 {
196 // create the main application window
197 MyFrame *frame = new MyFrame("wxStatusBar sample",
198 wxPoint(50, 50), wxSize(450, 340));
199
200 // and show it (the frames, unlike simple controls, are not shown when
201 // created initially)
202 frame->Show(TRUE);
203
204 // success: wxApp::OnRun() will be called which will enter the main message
205 // loop and the application will run. If we returned FALSE here, the
206 // application would exit immediately.
207 return TRUE;
208 }
209
210 // ----------------------------------------------------------------------------
211 // main frame
212 // ----------------------------------------------------------------------------
213
214 // frame constructor
215 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
216 : wxFrame((wxFrame *)NULL, -1, title, pos, size)
217 {
218 m_statbarDefault = NULL;
219 m_statbarCustom = NULL;
220
221 #ifdef __WXMAC__
222 // we need this in order to allow the about menu relocation, since ABOUT is
223 // not the default id of the about menu
224 wxApp::s_macAboutMenuItemId = StatusBar_About;
225 #endif
226
227 // create a menu bar
228 wxMenu *menuFile = new wxMenu;
229 menuFile->Append(StatusBar_Quit, "E&xit\tAlt-X", "Quit this program");
230
231 wxMenu *statbarMenu = new wxMenu;
232 statbarMenu->Append(StatusBar_SetFields, "&Set field count\tCtrl-C",
233 "Set the number of status bar fields");
234 statbarMenu->Append(StatusBar_Recreate, "&Recreate\tCtrl-R",
235 "Toggle status bar format");
236
237 wxMenu *helpMenu = new wxMenu;
238 helpMenu->Append(StatusBar_About, "&About...\tCtrl-A", "Show about dialog");
239
240 // now append the freshly created menu to the menu bar...
241 wxMenuBar *menuBar = new wxMenuBar();
242 menuBar->Append(menuFile, "&File");
243 menuBar->Append(statbarMenu, "&Status bar");
244 menuBar->Append(helpMenu, "&Help");
245
246 // ... and attach this menu bar to the frame
247 SetMenuBar(menuBar);
248
249 // create default status bar to start with
250 CreateStatusBar(2);
251 SetStatusText("Welcome to wxWindows!");
252
253 m_statbarDefault = GetStatusBar();
254 }
255
256 MyFrame::~MyFrame()
257 {
258 SetStatusBar(NULL);
259
260 delete m_statbarDefault;
261 delete m_statbarCustom;
262 }
263
264 void MyFrame::DoCreateStatusBar(MyFrame::StatBarKind kind)
265 {
266 wxStatusBar *statbarOld = GetStatusBar();
267 if ( statbarOld )
268 {
269 statbarOld->Hide();
270 }
271
272 switch ( kind )
273 {
274 case StatBar_Default:
275 SetStatusBar(m_statbarDefault);
276 break;
277
278 case StatBar_Custom:
279 if ( !m_statbarCustom )
280 {
281 m_statbarCustom = new MyStatusBar(this);
282 }
283 SetStatusBar(m_statbarCustom);
284 break;
285
286 default:
287 wxFAIL_MSG("unknown stat bar kind");
288 }
289
290 PositionStatusBar();
291 GetStatusBar()->Show();
292
293 m_statbarKind = kind;
294 }
295
296 // event handlers
297 void MyFrame::OnSetStatusFields(wxCommandEvent& WXUNUSED(event))
298 {
299 wxStatusBar *sb = GetStatusBar();
300
301 long nFields = wxGetNumberFromUser
302 (
303 "Select the number of fields in the status bar",
304 "Fields:",
305 "wxWindows statusbar sample",
306 sb->GetFieldsCount(),
307 1, 5,
308 this
309 );
310
311 // we don't check if the number changed at all on purpose: calling
312 // SetFieldsCount() with the same number of fields should be ok
313 if ( nFields != -1 )
314 {
315 // we set the widths only for 2 of them, otherwise let all the fields
316 // have equal width (the default behaviour)
317 const int *widths = NULL;
318 if ( nFields == 2 )
319 {
320 static const int widthsFor2Fields[2] = { 200, -1 };
321 widths = widthsFor2Fields;
322 }
323
324 sb->SetFieldsCount(nFields, widths);
325
326 wxLogStatus(this,
327 wxString::Format("Status bar now has %ld fields", nFields));
328 }
329 else
330 {
331 wxLogStatus(this, "Cancelled");
332 }
333 }
334
335 void MyFrame::OnRecreateStatusBar(wxCommandEvent& WXUNUSED(event))
336 {
337 DoCreateStatusBar(m_statbarKind == StatBar_Custom ? StatBar_Default
338 : StatBar_Custom);
339 }
340
341 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
342 {
343 // TRUE is to force the frame to close
344 Close(TRUE);
345 }
346
347 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
348 {
349 wxMessageBox("wxStatusBar sample\n(c) 2000 Vadim Zeitlin",
350 "About statbar", wxOK | wxICON_INFORMATION, this);
351 }
352
353 // ----------------------------------------------------------------------------
354 // MyStatusBar
355 // ----------------------------------------------------------------------------
356
357 #ifdef __VISUALC__
358 // 'this' : used in base member initializer list -- so what??
359 #pragma warning(disable: 4355)
360 #endif
361
362 MyStatusBar::MyStatusBar(wxWindow *parent)
363 : wxStatusBar(parent, -1), m_timer(this)
364 {
365 static const int widths[Field_Max] = { -1, 150, BITMAP_SIZE_X, 100 };
366
367 SetFieldsCount(Field_Max);
368 SetStatusWidths(Field_Max, widths);
369
370 m_checkbox = new wxCheckBox(this, StatusBar_Checkbox, _T("&Toggle clock"));
371 m_checkbox->SetValue(TRUE);
372
373 m_statbmp = new wxStaticBitmap(this, -1, wxIcon(green_xpm));
374
375 m_timer.Start(1000);
376
377 SetMinHeight(BITMAP_SIZE_Y);
378
379 UpdateClock();
380 }
381
382 #ifdef __VISUALC__
383 #pragma warning(default: 4355)
384 #endif
385
386 MyStatusBar::~MyStatusBar()
387 {
388 if ( m_timer.IsRunning() )
389 {
390 m_timer.Stop();
391 }
392 }
393
394 void MyStatusBar::OnSize(wxSizeEvent& event)
395 {
396 wxRect rect;
397 GetFieldRect(Field_Checkbox, rect);
398
399 m_checkbox->SetSize(rect.x + 2, rect.y + 2, rect.width - 4, rect.height - 4);
400
401 GetFieldRect(Field_Bitmap, rect);
402 m_statbmp->Move(rect.x + (rect.width - BITMAP_SIZE_X) / 2,
403 rect.y + (rect.height - BITMAP_SIZE_Y) / 2);
404
405 event.Skip();
406 }
407
408 void MyStatusBar::OnToggleClock(wxCommandEvent& event)
409 {
410 if ( m_checkbox->GetValue() )
411 {
412 m_timer.Start(1000);
413
414 m_statbmp->SetIcon(wxIcon(green_xpm));
415
416 UpdateClock();
417 }
418 else // don't show clock
419 {
420 m_timer.Stop();
421
422 m_statbmp->SetIcon(wxIcon(red_xpm));
423
424 SetStatusText("", Field_Clock);
425 }
426 }
427
428 void MyStatusBar::UpdateClock()
429 {
430 SetStatusText(wxDateTime::Now().FormatTime(), Field_Clock);
431 }