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