]> git.saurik.com Git - wxWidgets.git/blame - src/generic/wizard.cpp
Misc. Dialog Editor/resource bugs fixed
[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 {
188 Centre();
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 {
252 m_statbmp->SetBitmap(bmpIsDefault ? m_bitmap : m_page->GetBitmap());
253 }
254
74b31181
VZ
255 // and update the buttons state
256 m_btnPrev->Enable(m_page->GetPrev() != (wxWizardPage *)NULL);
66cd017c 257
8f177c8e
VZ
258 bool hasNext = m_page->GetNext() != (wxWizardPage *)NULL;
259 if ( btnLabelWasNext != hasNext )
66cd017c 260 {
74b31181 261 // need to update
e9fa7581
OK
262 if (btnLabelWasNext)
263 m_btnNext->SetLabel(_("&Finish"));
264 else
265 m_btnNext->SetLabel(_("&Next >"));
66cd017c 266 }
74b31181 267 // nothing to do: the label was already correct
66cd017c 268
74b31181 269 return TRUE;
66cd017c
VZ
270}
271
74b31181 272bool wxWizard::RunWizard(wxWizardPage *firstPage)
66cd017c 273{
223d09f6 274 wxCHECK_MSG( firstPage, FALSE, wxT("can't run empty wizard") );
66cd017c
VZ
275
276 // can't return FALSE here because there is no old page
74b31181 277 (void)ShowPage(firstPage, TRUE /* forward */);
66cd017c
VZ
278
279 return ShowModal() == wxID_OK;
280}
281
74b31181 282wxWizardPage *wxWizard::GetCurrentPage() const
66cd017c 283{
74b31181 284 return m_page;
66cd017c
VZ
285}
286
4fe5383d
VZ
287wxSize wxWizard::GetPageSize() const
288{
289 return wxSize(m_width, m_height);
290}
291
74b31181 292void wxWizard::OnCancel(wxCommandEvent& WXUNUSED(event))
66cd017c 293{
74b31181
VZ
294 // this function probably can never be called when we don't have an active
295 // page, but a small extra check won't hurt
296 wxWindow *win = m_page ? (wxWindow *)m_page : (wxWindow *)this;
297
66cd017c 298 wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId());
74b31181 299 if ( !win->GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
66cd017c
VZ
300 {
301 // no objections - close the dialog
302 EndModal(wxID_CANCEL);
303 }
304 //else: request to Cancel ignored
305}
306
74b31181 307void wxWizard::OnBackOrNext(wxCommandEvent& event)
66cd017c
VZ
308{
309 wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
310 (event.GetEventObject() == m_btnPrev),
223d09f6 311 wxT("unknown button") );
66cd017c 312
74b31181 313 bool forward = event.GetEventObject() == m_btnNext;
66cd017c 314
74b31181
VZ
315 wxWizardPage *page;
316 if ( forward )
66cd017c 317 {
74b31181 318 page = m_page->GetNext();
66cd017c 319 }
74b31181 320 else // back
66cd017c 321 {
74b31181
VZ
322 page = m_page->GetPrev();
323
223d09f6 324 wxASSERT_MSG( page, wxT("\"<Back\" button should have been disabled") );
66cd017c 325 }
74b31181
VZ
326
327 // just pass to the new page (or may be not - but we don't care here)
328 (void)ShowPage(page, forward);
66cd017c
VZ
329}
330
331// ----------------------------------------------------------------------------
332// our public interface
333// ----------------------------------------------------------------------------
334
74b31181
VZ
335/* static */
336wxWizard *wxWizardBase::Create(wxWindow *parent,
337 int id,
338 const wxString& title,
339 const wxBitmap& bitmap,
340 const wxPoint& pos,
341 const wxSize& size)
66cd017c 342{
74b31181 343 return new wxWizard(parent, id, title, bitmap, pos, size);
66cd017c
VZ
344}
345
346// ----------------------------------------------------------------------------
347// wxWizardEvent
348// ----------------------------------------------------------------------------
349
74b31181 350wxWizardEvent::wxWizardEvent(wxEventType type, int id, bool direction)
66cd017c
VZ
351 : wxNotifyEvent(type, id)
352{
74b31181 353 m_direction = direction;
66cd017c 354}
74b31181 355