]> git.saurik.com Git - wxWidgets.git/blob - src/generic/wizard.cpp
Fixed bug that wrote incomplete wxExpr files (missing fclose)
[wxWidgets.git] / src / generic / wizard.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: generic/wizard.cpp
3 // Purpose: generic implementation of wxWizard class
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 15.08.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation ".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/dynarray.h"
33 #include "wx/intl.h"
34 #endif //WX_PRECOMP
35
36 #include "wx/statline.h"
37
38 #include "wx/wizard.h"
39
40 // ----------------------------------------------------------------------------
41 // simple types
42 // ----------------------------------------------------------------------------
43
44 WX_DEFINE_ARRAY(wxPanel *, wxArrayPages);
45
46 // ----------------------------------------------------------------------------
47 // wxWizardGeneric - generic implementation of wxWizard
48 // ----------------------------------------------------------------------------
49
50 class wxWizardGeneric : public wxWizard
51 {
52 public:
53 // ctor
54 wxWizardGeneric(wxWindow *parent,
55 int id,
56 const wxString& title,
57 const wxBitmap& bitmap,
58 const wxPoint& pos,
59 const wxSize& size);
60
61 // implement base class pure virtuals
62 virtual void AddPage(wxPanel *page);
63 virtual void InsertPage(int nPage, wxPanel *page);
64 virtual bool RunWizard();
65 virtual wxPanel *GetCurrentPage() const;
66
67 // implementation only from now on
68 // -------------------------------
69
70 // is the wizard running?
71 bool IsRunning() const { return m_page != -1; }
72
73 // show the given page calling TransferDataFromWindow - if it returns
74 // FALSE, the old page is not hidden and the function returns FALSE
75 bool ShowPage(size_t page);
76
77 // get the current page assuming the wizard is running
78 wxPanel *DoGetCurrentPage() const
79 {
80 wxASSERT_MSG( IsRunning(), _T("no current page!") );
81
82 return m_pages[(size_t)m_page];
83 }
84
85 // place the given page correctly and hide it
86 void DoAddPage(wxPanel *page);
87
88 private:
89 // event handlers
90 void OnCancel(wxCommandEvent& event);
91 void OnBackOrNext(wxCommandEvent& event);
92
93 // wizard dimensions
94 int m_x, m_y; // the origin for the pages
95 int m_width, // the size of the page itself
96 m_height; // (total width is m_width + m_x)
97
98 // wizard state
99 int m_page; // the current page or -1
100 wxArrayPages m_pages; // the array with all wizards pages
101
102 // wizard controls
103 wxButton *m_btnPrev, // the "<Back" button
104 *m_btnNext; // the "Next>" or "Finish" button
105
106 DECLARE_EVENT_TABLE()
107 };
108
109 // ----------------------------------------------------------------------------
110 // event tables and such
111 // ----------------------------------------------------------------------------
112
113 BEGIN_EVENT_TABLE(wxWizardGeneric, wxDialog)
114 EVT_BUTTON(wxID_CANCEL, OnCancel)
115 EVT_BUTTON(-1, OnBackOrNext)
116 END_EVENT_TABLE()
117
118 IMPLEMENT_ABSTRACT_CLASS(wxWizard, wxDialog)
119 IMPLEMENT_DYNAMIC_CLASS(wxWizardEvent, wxNotifyEvent)
120
121 // ============================================================================
122 // implementation
123 // ============================================================================
124
125 // ----------------------------------------------------------------------------
126 // generic wxWizard implementation
127 // ----------------------------------------------------------------------------
128
129 wxWizardGeneric::wxWizardGeneric(wxWindow *parent,
130 int id,
131 const wxString& title,
132 const wxBitmap& bitmap,
133 const wxPoint& pos,
134 const wxSize& size)
135 {
136 // constants defining the dialog layout
137 // ------------------------------------
138
139 // these constants define the position of the upper left corner of the
140 // bitmap or the page in the wizard
141 static const int X_MARGIN = 10;
142 static const int Y_MARGIN = 10;
143
144 // margin between the bitmap and the panel
145 static const int BITMAP_X_MARGIN = 15;
146
147 // margin between the bitmap and the static line
148 static const int BITMAP_Y_MARGIN = 15;
149
150 // margin between the static line and the buttons
151 static const int SEPARATOR_LINE_MARGIN = 15;
152
153 // margin between "Next >" and "Cancel" buttons
154 static const int BUTTON_MARGIN = 10;
155
156 // default width and height of the page
157 static const int DEFAULT_PAGE_WIDTH = 270;
158 static const int DEFAULT_PAGE_HEIGHT = 290;
159
160 // init members
161 // ------------
162
163 m_page = -1;
164
165 // create controls
166 // ---------------
167
168 wxSize sizeBtn = wxButton::GetDefaultSize();
169
170 (void)wxDialog::Create(parent, id, title, pos, size);
171
172 // the global dialog layout is: a row of buttons at the bottom (aligned to
173 // the right), the static line above them, the bitmap (if any) on the left
174 // of the upper part of the dialog and the panel in the remaining space
175 m_x = X_MARGIN;
176 m_y = Y_MARGIN;
177 if ( bitmap.Ok() )
178 {
179 (void)new wxStaticBitmap(this, -1, bitmap, wxPoint(m_x, m_y));
180
181 m_x += bitmap.GetWidth() + BITMAP_X_MARGIN;
182 m_height = bitmap.GetHeight();
183 }
184 else
185 {
186 m_height = DEFAULT_PAGE_HEIGHT;
187 }
188
189 m_width = DEFAULT_PAGE_WIDTH;
190
191 int x = X_MARGIN;
192 int y = m_y + m_height + BITMAP_Y_MARGIN;
193 (void)new wxStaticLine(this, -1, wxPoint(x, y),
194 wxSize(m_x + m_width - x, 2));
195
196 x = m_x + m_width - 3*sizeBtn.x - BUTTON_MARGIN;
197 y += SEPARATOR_LINE_MARGIN;
198 m_btnPrev = new wxButton(this, -1, _("< &Back"), wxPoint(x, y), sizeBtn);
199
200 x += sizeBtn.x;
201 m_btnNext = new wxButton(this, -1, _("&Next >"), wxPoint(x, y), sizeBtn);
202
203 x += sizeBtn.x + BUTTON_MARGIN;
204 (void)new wxButton(this, wxID_CANCEL, _("Cancel"), wxPoint(x, y), sizeBtn);
205
206 // position and size the dialog
207 // ----------------------------
208
209 if ( size == wxDefaultSize )
210 {
211 SetClientSize(m_x + m_width + X_MARGIN,
212 m_y + m_height + BITMAP_Y_MARGIN +
213 SEPARATOR_LINE_MARGIN + sizeBtn.y + Y_MARGIN);
214 }
215
216 if ( pos == wxDefaultPosition )
217 {
218 Centre();
219 }
220 }
221
222 bool wxWizardGeneric::ShowPage(size_t page)
223 {
224 wxCHECK_MSG( page < m_pages.GetCount(), FALSE,
225 _T("invalid wizard page index") );
226
227 wxASSERT_MSG( page != (size_t)m_page, _T("this is useless") );
228
229 size_t last = m_pages.GetCount() - 1;
230 bool mustChangeNextBtnLabel = (size_t)m_page == last || page == last;
231
232 if ( m_page != -1 )
233 {
234 wxPanel *panel = DoGetCurrentPage();
235 if ( !panel->TransferDataFromWindow() )
236 return FALSE;
237
238 panel->Hide();
239 }
240
241 m_page = page;
242 DoGetCurrentPage()->Show();
243
244 // update the buttons state
245 m_btnPrev->Enable(m_page != 0);
246 if ( mustChangeNextBtnLabel )
247 {
248 m_btnNext->SetLabel((size_t)m_page == last ? _("&Finish")
249 : _("&Next >"));
250 }
251
252 return TRUE;
253 }
254
255 void wxWizardGeneric::DoAddPage(wxPanel *page)
256 {
257 page->Hide();
258 page->SetSize(m_x, m_y, m_width, m_height);
259 }
260
261 void wxWizardGeneric::AddPage(wxPanel *page)
262 {
263 m_pages.Add(page);
264
265 DoAddPage(page);
266 }
267
268 void wxWizardGeneric::InsertPage(int nPage, wxPanel *page)
269 {
270 m_pages.Insert(page, nPage);
271 if ( nPage < m_page )
272 {
273 // the indices of all pages after the inserted one are shifted by 1
274 m_page++;
275 }
276
277 DoAddPage(page);
278 }
279
280 bool wxWizardGeneric::RunWizard()
281 {
282 wxCHECK_MSG( m_pages.GetCount() != 0, FALSE, _T("can't run empty wizard") );
283
284 // can't return FALSE here because there is no old page
285 (void)ShowPage(0u);
286
287 return ShowModal() == wxID_OK;
288 }
289
290 wxPanel *wxWizardGeneric::GetCurrentPage() const
291 {
292 return IsRunning() ? DoGetCurrentPage() : (wxPanel *)NULL;
293 }
294
295 void wxWizardGeneric::OnCancel(wxCommandEvent& WXUNUSED(event))
296 {
297 wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId());
298 if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
299 {
300 // no objections - close the dialog
301 EndModal(wxID_CANCEL);
302 }
303 //else: request to Cancel ignored
304 }
305
306 void wxWizardGeneric::OnBackOrNext(wxCommandEvent& event)
307 {
308 wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
309 (event.GetEventObject() == m_btnPrev),
310 _T("unknown button") );
311
312 int delta = event.GetEventObject() == m_btnNext ? 1 : -1;
313 int page = m_page + delta;
314
315 wxASSERT_MSG( page >= 0, _T("'Back' button should have been disabled!") );
316
317 if ( (size_t)page == m_pages.GetCount() )
318 {
319 // check that we have valid data in the last page too
320 if ( m_pages.Last()->TransferDataFromWindow() )
321 {
322 // that's all, folks!
323 EndModal(wxID_OK);
324 }
325 }
326 else
327 {
328 // just pass to the next page (or may be not - but we don't care here)
329 (void)ShowPage(page);
330 }
331 }
332
333 // ----------------------------------------------------------------------------
334 // our public interface
335 // ----------------------------------------------------------------------------
336
337 /* static */ wxWizard *wxWizard::Create(wxWindow *parent,
338 int id,
339 const wxString& title,
340 const wxBitmap& bitmap,
341 const wxPoint& pos,
342 const wxSize& size)
343 {
344 return new wxWizardGeneric(parent, id, title, bitmap, pos, size);
345 }
346
347 // ----------------------------------------------------------------------------
348 // wxWizardEvent
349 // ----------------------------------------------------------------------------
350
351 wxWizardEvent::wxWizardEvent(wxEventType type, int id)
352 : wxNotifyEvent(type, id)
353 {
354 m_page = m_pageOld = -1;
355 }