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