Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 : #ifndef _SVTOOLS_WIZARDMACHINE_HXX_
20 : #define _SVTOOLS_WIZARDMACHINE_HXX_
21 :
22 : #include "svtools/svtdllapi.h"
23 : #include <svtools/wizdlg.hxx>
24 : #include <vcl/button.hxx>
25 : #include <vcl/tabpage.hxx>
26 : #include <comphelper/stl_types.hxx>
27 :
28 : class Bitmap;
29 : //.........................................................................
30 : namespace svt
31 : {
32 : //.........................................................................
33 :
34 : // wizard buttons
35 : #define WZB_NONE 0x0000
36 : #define WZB_NEXT 0x0001
37 : #define WZB_PREVIOUS 0x0002
38 : #define WZB_FINISH 0x0004
39 : #define WZB_CANCEL 0x0008
40 : #define WZB_HELP 0x0010
41 :
42 : // wizard states
43 : #define WZS_INVALID_STATE ((WizardState)-1)
44 :
45 : //=====================================================================
46 : //= WizardTypes
47 : //=====================================================================
48 0 : struct WizardTypes
49 : {
50 : typedef sal_Int16 WizardState;
51 : enum CommitPageReason
52 : {
53 : eTravelForward, // traveling forward (maybe with skipping pages)
54 : eTravelBackward, // traveling backward (maybe with skipping pages)
55 : eFinish, // the wizard is about to be finished
56 : eValidate // the data should be validated only, no traveling wll happen
57 : };
58 : };
59 :
60 0 : class SAL_NO_VTABLE IWizardPageController
61 : {
62 : public:
63 : //-----------------------------------------------------------------
64 : // This methods behave somewhat different than ActivatePage/DeactivatePage
65 : // The latter are handled by the base class itself whenever changing the pages is in the offing,
66 : // i.e., when it's already decided which page is the next.
67 : // We may have situations where the next page depends on the state of the current, which needs
68 : // to be committed for this.
69 : // So initializePage and commitPage are designated to initialitzing/committing data on the page.
70 : virtual void initializePage() = 0;
71 : virtual sal_Bool commitPage( WizardTypes::CommitPageReason _eReason ) = 0;
72 :
73 : /** determines whether or not it is allowed to advance to a next page
74 :
75 : You should make this dependent on the current state of the page only, not on
76 : states on other pages of the whole dialog.
77 :
78 : The default implementation always returns <TRUE/>.
79 : */
80 : virtual bool canAdvance() const = 0;
81 :
82 : protected:
83 0 : ~IWizardPageController() {}
84 : };
85 :
86 : //=====================================================================
87 : //= OWizardPage
88 : //=====================================================================
89 : class OWizardMachine;
90 : struct WizardPageImplData;
91 :
92 : class SVT_DLLPUBLIC OWizardPage : public TabPage, public IWizardPageController
93 : {
94 : private:
95 : WizardPageImplData* m_pImpl;
96 :
97 : public:
98 : /** @param _pParent
99 : if the OWizardPage is used in an OWizardMachine, this parameter
100 : must be the OWizardMachine (which is derived from Window)
101 : */
102 : OWizardPage( Window* _pParent, const ResId& _rResId );
103 : ~OWizardPage();
104 :
105 : // IWizardPageController overridables
106 : virtual void initializePage();
107 : virtual sal_Bool commitPage( WizardTypes::CommitPageReason _eReason );
108 : virtual bool canAdvance() const;
109 :
110 : protected:
111 : // TabPage overridables
112 : virtual void ActivatePage();
113 :
114 : /** updates the travel-related UI elements of the OWizardMachine we live in (if any)
115 :
116 : If the parent of the tab page is a OWizardMachine, then updateTravelUI at this instance
117 : is called. Otherwise, nothing happens.
118 : */
119 : void updateDialogTravelUI();
120 : };
121 :
122 : //=====================================================================
123 : //= OWizardMachine
124 : //=====================================================================
125 : struct WizardMachineImplData;
126 : /** implements some kind of finite automata, where the states of the automata exactly correlate
127 : with tab pages.
128 :
129 : That is, the machine can have up to n states, where at each point in time exactly one state is
130 : the current one. A state being current is represented as one of n tab pages being displayed
131 : currently.
132 :
133 : The class handles the UI for traveling between the states (e.g. it administrates the <em>Next</em> and
134 : <em>Previous</em> buttons which you usually find in a wizard.
135 :
136 : Derived classes have to implement the travel logic by overriding <member>determineNextState</member>,
137 : which has to determine the state which follows the current state. Since this may depend
138 : on the actual data presented in the wizard (e.g. checkboxes checked, or something like this),
139 : they can implement non-linear traveling this way.
140 : */
141 :
142 : class SVT_DLLPUBLIC OWizardMachine : public WizardDialog, public WizardTypes
143 : {
144 : private:
145 : // restrict access to some aspects of our base class
146 0 : SVT_DLLPRIVATE void AddPage( TabPage* pPage ) { WizardDialog::AddPage(pPage); }
147 : SVT_DLLPRIVATE void RemovePage( TabPage* pPage ) { WizardDialog::RemovePage(pPage); }
148 0 : SVT_DLLPRIVATE void SetPage( sal_uInt16 nLevel, TabPage* pPage ) { WizardDialog::SetPage(nLevel, pPage); }
149 : // TabPage* GetPage( sal_uInt16 nLevel ) const { return WizardDialog::GetPage(nLevel); }
150 : // TODO: probably the complete page handling (next, previous etc.) should be prohibited ...
151 :
152 : // IMPORTANT:
153 : // traveling pages should not be done by calling these base class member, some mechanisms of this class
154 : // here (e.g. committing page data) depend on having full control over page traveling.
155 : // So use the travelXXX methods if you need to travel
156 :
157 : protected:
158 : OKButton* m_pFinish;
159 : CancelButton* m_pCancel;
160 : PushButton* m_pNextPage;
161 : PushButton* m_pPrevPage;
162 : HelpButton* m_pHelp;
163 :
164 : private:
165 : WizardMachineImplData*
166 : m_pImpl;
167 : // hold members in this structure to allow keeping compatible when members are added
168 :
169 : SVT_DLLPRIVATE void addButtons(Window* _pParent, sal_uInt32 _nButtonFlags);
170 :
171 : public:
172 : /** ctor
173 :
174 : The ctor does not call FreeResource, this is the resposibility of the derived class.
175 :
176 : For the button flags, use any combination of the WZB_* flags.
177 : */
178 : OWizardMachine(Window* _pParent, const ResId& _rRes, sal_uInt32 _nButtonFlags );
179 : OWizardMachine(Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags );
180 : ~OWizardMachine();
181 :
182 : /// enable (or disable) buttons
183 : void enableButtons(sal_uInt32 _nWizardButtonFlags, sal_Bool _bEnable);
184 : /// set the default style for a button
185 : void defaultButton(sal_uInt32 _nWizardButtonFlags);
186 : /// set the default style for a button
187 : void defaultButton(PushButton* _pNewDefButton);
188 :
189 : /// set the base of the title to use - the title of the current page is appended
190 : void setTitleBase(const String& _rTitleBase);
191 :
192 : /// determines whether there is a next state to which we can advance
193 : virtual bool canAdvance() const;
194 :
195 : /** updates the user interface which deals with traveling in the wizard
196 :
197 : The default implementation simply checks whether both the current page and the wizard
198 : itself allow to advance to the next state (<code>canAdvance</code>), and enables the "Next"
199 : button if and only if this is the case.
200 : */
201 : virtual void updateTravelUI();
202 :
203 : protected:
204 : // WizardDialog overridables
205 : virtual void ActivatePage();
206 : virtual long DeactivatePage();
207 :
208 : // our own overridables
209 :
210 : /// to override to create new pages
211 : virtual TabPage* createPage(WizardState _nState) = 0;
212 :
213 : /// will be called when a new page is about to be displayed
214 : virtual void enterState(WizardState _nState);
215 :
216 : /** will be called when the current state is about to be left for the given reason
217 :
218 : The base implementation in this class will simply call <member>OWizardPage::commitPage</member>
219 : for the current page, and return whatever this call returns.
220 :
221 : @param _eReason
222 : The reason why the state is to be left.
223 : @return
224 : <TRUE/> if and only if the page is allowed to be left
225 : */
226 : virtual sal_Bool prepareLeaveCurrentState( CommitPageReason _eReason );
227 :
228 : /** will be called when the given state is left
229 :
230 : This is the very last possibility for derived classes to veto the deactivation
231 : of a page.
232 :
233 : @todo Normally, we would not need the return value here - derived classes now have
234 : the possibility to veto page deactivations in <member>prepareLeaveCurrentState</member>. However,
235 : changing this return type is too incompatible at the moment ...
236 :
237 : @return
238 : <TRUE/> if and only if the page is allowed to be left
239 : */
240 : virtual sal_Bool leaveState( WizardState _nState );
241 :
242 : /** determine the next state to travel from the given one
243 :
244 : The default behaviour is linear traveling, overwrite this to change it
245 :
246 : Return WZS_INVALID_STATE to prevent traveling.
247 : */
248 : virtual WizardState determineNextState( WizardState _nCurrentState ) const;
249 :
250 : /** called when the finish button is pressed
251 : <p>By default, only the base class' Finnish method (which is not virtual) is called</p>
252 : */
253 : virtual sal_Bool onFinish();
254 :
255 : /// travel to the next state
256 : sal_Bool travelNext();
257 :
258 : /// travel to the previous state
259 : sal_Bool travelPrevious();
260 :
261 : /** enables the automatic enabled/disabled state of the "Next" button
262 :
263 : If this is <TRUE/>, then upon entering a new state, the "Next" button will automatically be
264 : enabled if and only if determineNextState does not return WZS_INVALID_STATE.
265 : */
266 : void enableAutomaticNextButtonState( bool _bEnable = true );
267 : bool isAutomaticNextButtonStateEnabled() const;
268 :
269 : /** removes a page from the history. Should be called when the page is being disabled
270 : */
271 : void removePageFromHistory( WizardState nToRemove );
272 :
273 : /** skip a state
274 :
275 : The method behaves as if from the current state, <arg>_nSteps</arg> <method>travelNext</method>s were
276 : called, but without actually creating or displaying the íntermediate pages. Only the
277 : (<arg>_nSteps</arg> + 1)th page is created.
278 :
279 : The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
280 :
281 : A very essential precondition for using this method is that your <method>determineNextState</method>
282 : method is able to determine the next state without actually having the page of the current state.
283 :
284 : @return
285 : <TRUE/> if and only if traveling was successful
286 :
287 : @see skipUntil
288 : @see skipBackwardUntil
289 : */
290 : sal_Bool skip( sal_Int32 _nSteps = 1 );
291 :
292 : /** skips one or more states, until a given state is reached
293 :
294 : The method behaves as if from the current state, <method>travelNext</method>s were called
295 : successively, until <arg>_nTargetState</arg> is reached, but without actually creating or
296 : displaying the íntermediate pages.
297 :
298 : The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
299 :
300 : @return
301 : <TRUE/> if and only if traveling was successful
302 :
303 : @see skip
304 : @see skipBackwardUntil
305 : */
306 : sal_Bool skipUntil( WizardState _nTargetState );
307 :
308 : /** moves back one or more states, until a given state is reached
309 :
310 : This method allows traveling backwards more than one state without actually showing the intermediate
311 : states.
312 :
313 : For instance, if you want to travel two steps backward at a time, you could used
314 : two travelPrevious calls, but this would <em>show</em> both pages, which is not necessary,
315 : since you're interested in the target page only. Using <member>skipBackwardUntil</member> reliefs
316 : you from this.
317 :
318 : @return
319 : <TRUE/> if and only if traveling was successful
320 :
321 : @see skipUntil
322 : @see skip
323 : */
324 : sal_Bool skipBackwardUntil( WizardState _nTargetState );
325 :
326 : /** returns the current state of the machine
327 :
328 : Vulgo, this is the identifier of the current tab page :)
329 : */
330 0 : WizardState getCurrentState() const { return WizardDialog::GetCurLevel(); }
331 :
332 : virtual IWizardPageController*
333 : getPageController( TabPage* _pCurrentPage ) const;
334 :
335 : /** retrieves a copy of the state history, i.e. all states we already visited
336 : */
337 : void getStateHistory( ::std::vector< WizardState >& _out_rHistory );
338 :
339 : public:
340 0 : class AccessGuard { friend class WizardTravelSuspension; private: AccessGuard() { } };
341 :
342 : void suspendTraveling( AccessGuard );
343 : void resumeTraveling( AccessGuard );
344 : bool isTravelingSuspended() const;
345 :
346 : protected:
347 : TabPage* GetOrCreatePage( const WizardState i_nState );
348 :
349 : private:
350 : // long OnNextPage( PushButton* );
351 : DECL_DLLPRIVATE_LINK(OnNextPage, void*);
352 : DECL_DLLPRIVATE_LINK(OnPrevPage, void*);
353 : DECL_DLLPRIVATE_LINK(OnFinish, void*);
354 :
355 : SVT_DLLPRIVATE void implResetDefault(Window* _pWindow);
356 : SVT_DLLPRIVATE void implUpdateTitle();
357 : SVT_DLLPRIVATE void implConstruct( const sal_uInt32 _nButtonFlags );
358 : };
359 :
360 : /// helper class to temporarily suspend any traveling in the wizard
361 : class WizardTravelSuspension
362 : {
363 : public:
364 0 : WizardTravelSuspension( OWizardMachine& _rWizard )
365 0 : :m_rWizard( _rWizard )
366 : {
367 0 : m_rWizard.suspendTraveling( OWizardMachine::AccessGuard() );
368 0 : }
369 :
370 0 : ~WizardTravelSuspension()
371 : {
372 0 : m_rWizard.resumeTraveling( OWizardMachine::AccessGuard() );
373 0 : }
374 :
375 : private:
376 : OWizardMachine& m_rWizard;
377 : };
378 :
379 : //.........................................................................
380 : } // namespace svt
381 : //.........................................................................
382 :
383 : #endif // _SVTOOLS_WIZARDMACHINE_HXX_
384 :
385 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|