]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/generic/wizard.cpp
Added fix for mingw32 gcc-2.95 regarding FillMemory
[wxWidgets.git] / src / generic / wizard.cpp
... / ...
CommitLineData
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
45WX_DEFINE_ARRAY(wxPanel *, wxArrayPages);
46
47// ----------------------------------------------------------------------------
48// event tables and such
49// ----------------------------------------------------------------------------
50
51BEGIN_EVENT_TABLE(wxWizard, wxDialog)
52 EVT_BUTTON(wxID_CANCEL, wxWizard::OnCancel)
53 EVT_BUTTON(-1, wxWizard::OnBackOrNext)
54END_EVENT_TABLE()
55
56IMPLEMENT_DYNAMIC_CLASS(wxWizard, wxDialog)
57IMPLEMENT_ABSTRACT_CLASS(wxWizardPage, wxPanel)
58IMPLEMENT_DYNAMIC_CLASS(wxWizardPageSimple, wxWizardPage)
59IMPLEMENT_DYNAMIC_CLASS(wxWizardEvent, wxNotifyEvent)
60
61// ============================================================================
62// implementation
63// ============================================================================
64
65// ----------------------------------------------------------------------------
66// wxWizardPage
67// ----------------------------------------------------------------------------
68
69wxWizardPage::wxWizardPage(wxWizard *parent, const wxBitmap& bitmap)
70 : wxPanel(parent), m_bitmap(bitmap)
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}
89// ----------------------------------------------------------------------------
90// generic wxWizard implementation
91// ----------------------------------------------------------------------------
92
93wxWizard::wxWizard(wxWindow *parent,
94 int id,
95 const wxString& title,
96 const wxBitmap& bitmap,
97 const wxPoint& pos,
98 const wxSize& size)
99 : m_bitmap(bitmap)
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
128 m_page = (wxWizardPage *)NULL;
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 {
144 m_statbmp = new wxStaticBitmap(this, -1, bitmap, wxPoint(m_x, m_y));
145
146 m_x += bitmap.GetWidth() + BITMAP_X_MARGIN;
147 m_height = bitmap.GetHeight();
148 }
149 else
150 {
151 m_statbmp = (wxStaticBitmap *)NULL;
152
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;
160
161#if wxUSE_STATLINE
162 (void)new wxStaticLine(this, -1, wxPoint(x, y),
163 wxSize(m_x + m_width - x, 2));
164#endif
165
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 CentreOnScreen();
189 }
190}
191
192bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
193{
194 wxASSERT_MSG( page != m_page, wxT("this is useless") );
195
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;
199
200 // and this tells us whether we already had the default bitmap before
201 bool bmpWasDefault = TRUE;
202
203 if ( m_page )
204 {
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
218 return FALSE;
219 }
220
221 m_page->Hide();
222
223 btnLabelWasNext = m_page->GetNext() != (wxWizardPage *)NULL;
224 bmpWasDefault = !m_page->GetBitmap().Ok();
225 }
226
227 // set the new one
228 m_page = page;
229
230 // is this the end?
231 if ( !m_page )
232 {
233 // terminate successfully
234 EndModal(wxID_OK);
235
236 return TRUE;
237 }
238
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);
242
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();
247
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 wxBitmap bmp;
253 if ( bmpIsDefault )
254 bmp = m_bitmap;
255 else
256 bmp = m_page->GetBitmap();
257 m_statbmp->SetBitmap(bmp);
258 }
259
260 // and update the buttons state
261 m_btnPrev->Enable(m_page->GetPrev() != (wxWizardPage *)NULL);
262
263 bool hasNext = m_page->GetNext() != (wxWizardPage *)NULL;
264 if ( btnLabelWasNext != hasNext )
265 {
266 // need to update
267 if (btnLabelWasNext)
268 m_btnNext->SetLabel(_("&Finish"));
269 else
270 m_btnNext->SetLabel(_("&Next >"));
271 }
272 // nothing to do: the label was already correct
273
274 return TRUE;
275}
276
277bool wxWizard::RunWizard(wxWizardPage *firstPage)
278{
279 wxCHECK_MSG( firstPage, FALSE, wxT("can't run empty wizard") );
280
281 // can't return FALSE here because there is no old page
282 (void)ShowPage(firstPage, TRUE /* forward */);
283
284 return ShowModal() == wxID_OK;
285}
286
287wxWizardPage *wxWizard::GetCurrentPage() const
288{
289 return m_page;
290}
291
292wxSize wxWizard::GetPageSize() const
293{
294 return wxSize(m_width, m_height);
295}
296
297void wxWizard::OnCancel(wxCommandEvent& WXUNUSED(event))
298{
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
303 wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId());
304 if ( !win->GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
305 {
306 // no objections - close the dialog
307 EndModal(wxID_CANCEL);
308 }
309 //else: request to Cancel ignored
310}
311
312void wxWizard::OnBackOrNext(wxCommandEvent& event)
313{
314 wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
315 (event.GetEventObject() == m_btnPrev),
316 wxT("unknown button") );
317
318 bool forward = event.GetEventObject() == m_btnNext;
319
320 wxWizardPage *page;
321 if ( forward )
322 {
323 page = m_page->GetNext();
324 }
325 else // back
326 {
327 page = m_page->GetPrev();
328
329 wxASSERT_MSG( page, wxT("\"<Back\" button should have been disabled") );
330 }
331
332 // just pass to the new page (or may be not - but we don't care here)
333 (void)ShowPage(page, forward);
334}
335
336// ----------------------------------------------------------------------------
337// our public interface
338// ----------------------------------------------------------------------------
339
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)
347{
348 return new wxWizard(parent, id, title, bitmap, pos, size);
349}
350
351// ----------------------------------------------------------------------------
352// wxWizardEvent
353// ----------------------------------------------------------------------------
354
355wxWizardEvent::wxWizardEvent(wxEventType type, int id, bool direction)
356 : wxNotifyEvent(type, id)
357{
358 m_direction = direction;
359}
360