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