]> git.saurik.com Git - wxWidgets.git/blob - src/generic/wizard.cpp
GSocket:
[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 // event tables and such
49 // ----------------------------------------------------------------------------
50
51 BEGIN_EVENT_TABLE(wxWizard, wxDialog)
52 EVT_BUTTON(wxID_CANCEL, wxWizard::OnCancel)
53 EVT_BUTTON(-1, wxWizard::OnBackOrNext)
54 END_EVENT_TABLE()
55
56 IMPLEMENT_DYNAMIC_CLASS(wxWizard, wxDialog)
57 IMPLEMENT_ABSTRACT_CLASS(wxWizardPage, wxPanel)
58 IMPLEMENT_DYNAMIC_CLASS(wxWizardPageSimple, wxWizardPage)
59 IMPLEMENT_DYNAMIC_CLASS(wxWizardEvent, wxNotifyEvent)
60
61 // ============================================================================
62 // implementation
63 // ============================================================================
64
65 // ----------------------------------------------------------------------------
66 // wxWizardPage
67 // ----------------------------------------------------------------------------
68
69 wxWizardPage::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
80 wxWizardPage *wxWizardPageSimple::GetPrev() const
81 {
82 return m_prev;
83 }
84
85 wxWizardPage *wxWizardPageSimple::GetNext() const
86 {
87 return m_next;
88 }
89 // ----------------------------------------------------------------------------
90 // generic wxWizard implementation
91 // ----------------------------------------------------------------------------
92
93 wxWizard::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 Centre();
189 }
190 }
191
192 bool 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 m_statbmp->SetBitmap(bmpIsDefault ? m_bitmap : m_page->GetBitmap());
253 }
254
255 // and update the buttons state
256 m_btnPrev->Enable(m_page->GetPrev() != (wxWizardPage *)NULL);
257
258 bool hasNext = m_page->GetNext() != (wxWizardPage *)NULL;
259 if ( btnLabelWasNext != hasNext )
260 {
261 // need to update
262 if (btnLabelWasNext)
263 m_btnNext->SetLabel(_("&Finish"));
264 else
265 m_btnNext->SetLabel(_("&Next >"));
266 }
267 // nothing to do: the label was already correct
268
269 return TRUE;
270 }
271
272 bool wxWizard::RunWizard(wxWizardPage *firstPage)
273 {
274 wxCHECK_MSG( firstPage, FALSE, wxT("can't run empty wizard") );
275
276 // can't return FALSE here because there is no old page
277 (void)ShowPage(firstPage, TRUE /* forward */);
278
279 return ShowModal() == wxID_OK;
280 }
281
282 wxWizardPage *wxWizard::GetCurrentPage() const
283 {
284 return m_page;
285 }
286
287 wxSize wxWizard::GetPageSize() const
288 {
289 return wxSize(m_width, m_height);
290 }
291
292 void wxWizard::OnCancel(wxCommandEvent& WXUNUSED(event))
293 {
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
298 wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId());
299 if ( !win->GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
300 {
301 // no objections - close the dialog
302 EndModal(wxID_CANCEL);
303 }
304 //else: request to Cancel ignored
305 }
306
307 void wxWizard::OnBackOrNext(wxCommandEvent& event)
308 {
309 wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
310 (event.GetEventObject() == m_btnPrev),
311 wxT("unknown button") );
312
313 bool forward = event.GetEventObject() == m_btnNext;
314
315 wxWizardPage *page;
316 if ( forward )
317 {
318 page = m_page->GetNext();
319 }
320 else // back
321 {
322 page = m_page->GetPrev();
323
324 wxASSERT_MSG( page, wxT("\"<Back\" button should have been disabled") );
325 }
326
327 // just pass to the new page (or may be not - but we don't care here)
328 (void)ShowPage(page, forward);
329 }
330
331 // ----------------------------------------------------------------------------
332 // our public interface
333 // ----------------------------------------------------------------------------
334
335 /* static */
336 wxWizard *wxWizardBase::Create(wxWindow *parent,
337 int id,
338 const wxString& title,
339 const wxBitmap& bitmap,
340 const wxPoint& pos,
341 const wxSize& size)
342 {
343 return new wxWizard(parent, id, title, bitmap, pos, size);
344 }
345
346 // ----------------------------------------------------------------------------
347 // wxWizardEvent
348 // ----------------------------------------------------------------------------
349
350 wxWizardEvent::wxWizardEvent(wxEventType type, int id, bool direction)
351 : wxNotifyEvent(type, id)
352 {
353 m_direction = direction;
354 }
355