]> git.saurik.com Git - wxWidgets.git/blame - src/generic/wizard.cpp
*** empty log message ***
[wxWidgets.git] / src / generic / wizard.cpp
CommitLineData
66cd017c
VZ
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"
b87654f3 34 #include "wx/statbmp.h"
66cd017c
VZ
35#endif //WX_PRECOMP
36
37#include "wx/statline.h"
38
39#include "wx/wizard.h"
40
41// ----------------------------------------------------------------------------
42// simple types
43// ----------------------------------------------------------------------------
44
45WX_DEFINE_ARRAY(wxPanel *, wxArrayPages);
46
66cd017c
VZ
47// ----------------------------------------------------------------------------
48// event tables and such
49// ----------------------------------------------------------------------------
50
74b31181
VZ
51BEGIN_EVENT_TABLE(wxWizard, wxDialog)
52 EVT_BUTTON(wxID_CANCEL, wxWizard::OnCancel)
53 EVT_BUTTON(-1, wxWizard::OnBackOrNext)
66cd017c
VZ
54END_EVENT_TABLE()
55
74b31181
VZ
56IMPLEMENT_DYNAMIC_CLASS(wxWizard, wxDialog)
57IMPLEMENT_ABSTRACT_CLASS(wxWizardPage, wxPanel)
58IMPLEMENT_DYNAMIC_CLASS(wxWizardPageSimple, wxWizardPage)
66cd017c
VZ
59IMPLEMENT_DYNAMIC_CLASS(wxWizardEvent, wxNotifyEvent)
60
61// ============================================================================
62// implementation
63// ============================================================================
64
74b31181
VZ
65// ----------------------------------------------------------------------------
66// wxWizardPage
67// ----------------------------------------------------------------------------
68
69wxWizardPage::wxWizardPage(wxWizard *parent) : wxPanel(parent)
70{
71 // initially the page is hidden, it's shown only when it becomes current
72 Hide();
73}
74
75// ----------------------------------------------------------------------------
76// wxWizardPageSimple
77// ----------------------------------------------------------------------------
78
79wxWizardPage *wxWizardPageSimple::GetPrev() const
80{
81 return m_prev;
82}
83
84wxWizardPage *wxWizardPageSimple::GetNext() const
85{
86 return m_next;
87}
66cd017c
VZ
88// ----------------------------------------------------------------------------
89// generic wxWizard implementation
90// ----------------------------------------------------------------------------
91
74b31181
VZ
92wxWizard::wxWizard(wxWindow *parent,
93 int id,
94 const wxString& title,
95 const wxBitmap& bitmap,
96 const wxPoint& pos,
97 const wxSize& size)
66cd017c
VZ
98{
99 // constants defining the dialog layout
100 // ------------------------------------
101
102 // these constants define the position of the upper left corner of the
103 // bitmap or the page in the wizard
104 static const int X_MARGIN = 10;
105 static const int Y_MARGIN = 10;
106
107 // margin between the bitmap and the panel
108 static const int BITMAP_X_MARGIN = 15;
109
110 // margin between the bitmap and the static line
111 static const int BITMAP_Y_MARGIN = 15;
112
113 // margin between the static line and the buttons
114 static const int SEPARATOR_LINE_MARGIN = 15;
115
116 // margin between "Next >" and "Cancel" buttons
117 static const int BUTTON_MARGIN = 10;
118
119 // default width and height of the page
120 static const int DEFAULT_PAGE_WIDTH = 270;
121 static const int DEFAULT_PAGE_HEIGHT = 290;
122
123 // init members
124 // ------------
125
74b31181 126 m_page = (wxWizardPage *)NULL;
66cd017c
VZ
127
128 // create controls
129 // ---------------
130
131 wxSize sizeBtn = wxButton::GetDefaultSize();
132
133 (void)wxDialog::Create(parent, id, title, pos, size);
134
135 // the global dialog layout is: a row of buttons at the bottom (aligned to
136 // the right), the static line above them, the bitmap (if any) on the left
137 // of the upper part of the dialog and the panel in the remaining space
138 m_x = X_MARGIN;
139 m_y = Y_MARGIN;
140 if ( bitmap.Ok() )
141 {
142 (void)new wxStaticBitmap(this, -1, bitmap, wxPoint(m_x, m_y));
143
144 m_x += bitmap.GetWidth() + BITMAP_X_MARGIN;
145 m_height = bitmap.GetHeight();
146 }
147 else
148 {
149 m_height = DEFAULT_PAGE_HEIGHT;
150 }
151
152 m_width = DEFAULT_PAGE_WIDTH;
153
154 int x = X_MARGIN;
155 int y = m_y + m_height + BITMAP_Y_MARGIN;
74b31181
VZ
156
157#if wxUSE_STATLINE
66cd017c
VZ
158 (void)new wxStaticLine(this, -1, wxPoint(x, y),
159 wxSize(m_x + m_width - x, 2));
41435ed2 160#endif
74b31181 161
66cd017c
VZ
162 x = m_x + m_width - 3*sizeBtn.x - BUTTON_MARGIN;
163 y += SEPARATOR_LINE_MARGIN;
164 m_btnPrev = new wxButton(this, -1, _("< &Back"), wxPoint(x, y), sizeBtn);
165
166 x += sizeBtn.x;
167 m_btnNext = new wxButton(this, -1, _("&Next >"), wxPoint(x, y), sizeBtn);
168
169 x += sizeBtn.x + BUTTON_MARGIN;
170 (void)new wxButton(this, wxID_CANCEL, _("Cancel"), wxPoint(x, y), sizeBtn);
171
172 // position and size the dialog
173 // ----------------------------
174
175 if ( size == wxDefaultSize )
176 {
177 SetClientSize(m_x + m_width + X_MARGIN,
178 m_y + m_height + BITMAP_Y_MARGIN +
179 SEPARATOR_LINE_MARGIN + sizeBtn.y + Y_MARGIN);
180 }
181
182 if ( pos == wxDefaultPosition )
183 {
184 Centre();
185 }
186}
187
74b31181 188bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
66cd017c 189{
223d09f6 190 wxASSERT_MSG( page != m_page, wxT("this is useless") );
66cd017c 191
74b31181
VZ
192 // we'll use this to decide whether we have to change the label of this
193 // button or not (initially the label is "Next")
194 bool btnLabelWasNext = TRUE;
66cd017c 195
74b31181 196 if ( m_page )
66cd017c 197 {
74b31181
VZ
198 // ask the current page first
199 if ( !m_page->TransferDataFromWindow() )
200 {
201 // the page data is incorrect
202 return FALSE;
203 }
204
205 // send the event to the old page
206 wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGING, GetId(), goingForward);
207 if ( m_page->GetEventHandler()->ProcessEvent(event) &&
208 !event.IsAllowed() )
209 {
210 // vetoed by the page
66cd017c 211 return FALSE;
74b31181 212 }
66cd017c 213
74b31181
VZ
214 m_page->Hide();
215
216 btnLabelWasNext = m_page->GetNext() != (wxWizardPage *)NULL;
66cd017c
VZ
217 }
218
74b31181 219 // set the new one
66cd017c 220 m_page = page;
66cd017c 221
74b31181
VZ
222 // is this the end?
223 if ( !m_page )
66cd017c 224 {
74b31181
VZ
225 // terminate successfully
226 EndModal(wxID_OK);
66cd017c 227
74b31181
VZ
228 return TRUE;
229 }
66cd017c 230
74b31181
VZ
231 // send the event to the new page now
232 wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGED, GetId(), goingForward);
233 (void)m_page->GetEventHandler()->ProcessEvent(event);
66cd017c 234
74b31181
VZ
235 // position and show the new page
236 (void)m_page->TransferDataToWindow();
237 m_page->SetSize(m_x, m_y, m_width, m_height);
238 m_page->Show();
66cd017c 239
74b31181
VZ
240 // and update the buttons state
241 m_btnPrev->Enable(m_page->GetPrev() != (wxWizardPage *)NULL);
66cd017c 242
8f177c8e
VZ
243 bool hasNext = m_page->GetNext() != (wxWizardPage *)NULL;
244 if ( btnLabelWasNext != hasNext )
66cd017c 245 {
74b31181
VZ
246 // need to update
247 m_btnNext->SetLabel(btnLabelWasNext ? _("&Finish") : _("&Next >"));
66cd017c 248 }
74b31181 249 // nothing to do: the label was already correct
66cd017c 250
74b31181 251 return TRUE;
66cd017c
VZ
252}
253
74b31181 254bool wxWizard::RunWizard(wxWizardPage *firstPage)
66cd017c 255{
223d09f6 256 wxCHECK_MSG( firstPage, FALSE, wxT("can't run empty wizard") );
66cd017c
VZ
257
258 // can't return FALSE here because there is no old page
74b31181 259 (void)ShowPage(firstPage, TRUE /* forward */);
66cd017c
VZ
260
261 return ShowModal() == wxID_OK;
262}
263
74b31181 264wxWizardPage *wxWizard::GetCurrentPage() const
66cd017c 265{
74b31181 266 return m_page;
66cd017c
VZ
267}
268
4fe5383d
VZ
269wxSize wxWizard::GetPageSize() const
270{
271 return wxSize(m_width, m_height);
272}
273
74b31181 274void wxWizard::OnCancel(wxCommandEvent& WXUNUSED(event))
66cd017c 275{
74b31181
VZ
276 // this function probably can never be called when we don't have an active
277 // page, but a small extra check won't hurt
278 wxWindow *win = m_page ? (wxWindow *)m_page : (wxWindow *)this;
279
66cd017c 280 wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId());
74b31181 281 if ( !win->GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
66cd017c
VZ
282 {
283 // no objections - close the dialog
284 EndModal(wxID_CANCEL);
285 }
286 //else: request to Cancel ignored
287}
288
74b31181 289void wxWizard::OnBackOrNext(wxCommandEvent& event)
66cd017c
VZ
290{
291 wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
292 (event.GetEventObject() == m_btnPrev),
223d09f6 293 wxT("unknown button") );
66cd017c 294
74b31181 295 bool forward = event.GetEventObject() == m_btnNext;
66cd017c 296
74b31181
VZ
297 wxWizardPage *page;
298 if ( forward )
66cd017c 299 {
74b31181 300 page = m_page->GetNext();
66cd017c 301 }
74b31181 302 else // back
66cd017c 303 {
74b31181
VZ
304 page = m_page->GetPrev();
305
223d09f6 306 wxASSERT_MSG( page, wxT("\"<Back\" button should have been disabled") );
66cd017c 307 }
74b31181
VZ
308
309 // just pass to the new page (or may be not - but we don't care here)
310 (void)ShowPage(page, forward);
66cd017c
VZ
311}
312
313// ----------------------------------------------------------------------------
314// our public interface
315// ----------------------------------------------------------------------------
316
74b31181
VZ
317/* static */
318wxWizard *wxWizardBase::Create(wxWindow *parent,
319 int id,
320 const wxString& title,
321 const wxBitmap& bitmap,
322 const wxPoint& pos,
323 const wxSize& size)
66cd017c 324{
74b31181 325 return new wxWizard(parent, id, title, bitmap, pos, size);
66cd017c
VZ
326}
327
328// ----------------------------------------------------------------------------
329// wxWizardEvent
330// ----------------------------------------------------------------------------
331
74b31181 332wxWizardEvent::wxWizardEvent(wxEventType type, int id, bool direction)
66cd017c
VZ
333 : wxNotifyEvent(type, id)
334{
74b31181 335 m_direction = direction;
66cd017c 336}
74b31181 337