Branch libreoffice-5-0-4
[LibreOffice.git] / include / svtools / wizardmachine.hxx
blobe2c2d6bd8618d3539eebf29ce1e73d0eade4f193
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #ifndef INCLUDED_SVTOOLS_WIZARDMACHINE_HXX
20 #define INCLUDED_SVTOOLS_WIZARDMACHINE_HXX
22 #include <svtools/svtdllapi.h>
23 #include <svtools/wizdlg.hxx>
24 #include <vcl/button.hxx>
25 #include <vcl/tabpage.hxx>
26 #include <o3tl/typed_flags_set.hxx>
28 class Bitmap;
30 enum class WizardButtonFlags
32 NONE = 0x0000,
33 NEXT = 0x0001,
34 PREVIOUS = 0x0002,
35 FINISH = 0x0004,
36 CANCEL = 0x0008,
37 HELP = 0x0010,
39 namespace o3tl
41 template<> struct typed_flags<WizardButtonFlags> : is_typed_flags<WizardButtonFlags, 0x001f> {};
44 namespace svt
48 // wizard states
49 #define WZS_INVALID_STATE ((WizardState)-1)
52 //= WizardTypes
54 struct WizardTypes
56 typedef sal_Int16 WizardState;
57 enum CommitPageReason
59 eTravelForward, // traveling forward (maybe with skipping pages)
60 eTravelBackward, // traveling backward (maybe with skipping pages)
61 eFinish, // the wizard is about to be finished
62 eValidate // the data should be validated only, no traveling wll happen
66 class SAL_NO_VTABLE IWizardPageController
68 public:
70 // This methods behave somewhat different than ActivatePage/DeactivatePage
71 // The latter are handled by the base class itself whenever changing the pages is in the offing,
72 // i.e., when it's already decided which page is the next.
73 // We may have situations where the next page depends on the state of the current, which needs
74 // to be committed for this.
75 // So initializePage and commitPage are designated to initialitzing/committing data on the page.
76 virtual void initializePage() = 0;
77 virtual bool commitPage( WizardTypes::CommitPageReason _eReason ) = 0;
79 /** determines whether or not it is allowed to advance to a next page
81 You should make this dependent on the current state of the page only, not on
82 states on other pages of the whole dialog.
84 The default implementation always returns <TRUE/>.
86 virtual bool canAdvance() const = 0;
88 protected:
89 ~IWizardPageController() {}
93 //= OWizardPage
95 class OWizardMachine;
96 struct WizardPageImplData;
98 class SVT_DLLPUBLIC OWizardPage : public TabPage, public IWizardPageController
100 private:
101 WizardPageImplData* m_pImpl;
103 public:
104 /** @param _pParent
105 if the OWizardPage is used in an OWizardMachine, this parameter
106 must be the OWizardMachine (which is derived from Window)
108 OWizardPage(vcl::Window *pParent, const OString& rID, const OUString& rUIXMLDescription);
109 virtual ~OWizardPage();
110 virtual void dispose() SAL_OVERRIDE;
112 // IWizardPageController overridables
113 virtual void initializePage() SAL_OVERRIDE;
114 virtual bool commitPage( WizardTypes::CommitPageReason _eReason ) SAL_OVERRIDE;
115 virtual bool canAdvance() const SAL_OVERRIDE;
117 protected:
118 // TabPage overridables
119 virtual void ActivatePage() SAL_OVERRIDE;
121 /** updates the travel-related UI elements of the OWizardMachine we live in (if any)
123 If the parent of the tab page is a OWizardMachine, then updateTravelUI at this instance
124 is called. Otherwise, nothing happens.
126 void updateDialogTravelUI();
130 //= OWizardMachine
132 struct WizardMachineImplData;
133 /** implements some kind of finite automata, where the states of the automata exactly correlate
134 with tab pages.
136 That is, the machine can have up to n states, where at each point in time exactly one state is
137 the current one. A state being current is represented as one of n tab pages being displayed
138 currently.
140 The class handles the UI for traveling between the states (e.g. it administrates the <em>Next</em> and
141 <em>Previous</em> buttons which you usually find in a wizard.
143 Derived classes have to implement the travel logic by overriding <member>determineNextState</member>,
144 which has to determine the state which follows the current state. Since this may depend
145 on the actual data presented in the wizard (e.g. checkboxes checked, or something like this),
146 they can implement non-linear traveling this way.
149 class SVT_DLLPUBLIC OWizardMachine : public WizardDialog, public WizardTypes
151 private:
152 // restrict access to some aspects of our base class
153 SVT_DLLPRIVATE void AddPage( TabPage* pPage ) { WizardDialog::AddPage(pPage); }
154 SVT_DLLPRIVATE void RemovePage( TabPage* pPage ) { WizardDialog::RemovePage(pPage); }
155 SVT_DLLPRIVATE void SetPage( sal_uInt16 nLevel, TabPage* pPage ) { WizardDialog::SetPage(nLevel, pPage); }
156 // TabPage* GetPage( sal_uInt16 nLevel ) const { return WizardDialog::GetPage(nLevel); }
157 // TODO: probably the complete page handling (next, previous etc.) should be prohibited ...
159 // IMPORTANT:
160 // traveling pages should not be done by calling these base class member, some mechanisms of this class
161 // here (e.g. committing page data) depend on having full control over page traveling.
162 // So use the travelXXX methods if you need to travel
164 protected:
165 VclPtr<OKButton> m_pFinish;
166 VclPtr<CancelButton> m_pCancel;
167 VclPtr<PushButton> m_pNextPage;
168 VclPtr<PushButton> m_pPrevPage;
169 VclPtr<HelpButton> m_pHelp;
171 private:
172 // hold members in this structure to allow keeping compatible when members are added
173 WizardMachineImplData* m_pImpl;
175 SVT_DLLPRIVATE void addButtons(vcl::Window* _pParent, sal_uInt32 _nButtonFlags);
177 public:
178 OWizardMachine(vcl::Window* _pParent, const WinBits i_nStyle, WizardButtonFlags _nButtonFlags );
179 OWizardMachine(vcl::Window* _pParent, WizardButtonFlags _nButtonFlags );
180 virtual ~OWizardMachine();
181 virtual void dispose() SAL_OVERRIDE;
183 /// enable (or disable) buttons
184 void enableButtons(WizardButtonFlags _nWizardButtonFlags, bool _bEnable);
185 /// set the default style for a button
186 void defaultButton(WizardButtonFlags _nWizardButtonFlags);
187 /// set the default style for a button
188 void defaultButton(PushButton* _pNewDefButton);
190 /// set the base of the title to use - the title of the current page is appended
191 void setTitleBase(const OUString& _rTitleBase);
193 /// determines whether there is a next state to which we can advance
194 virtual bool canAdvance() const;
196 /** updates the user interface which deals with traveling in the wizard
198 The default implementation simply checks whether both the current page and the wizard
199 itself allow to advance to the next state (<code>canAdvance</code>), and enables the "Next"
200 button if and only if this is the case.
202 virtual void updateTravelUI();
204 protected:
205 // WizardDialog overridables
206 virtual void ActivatePage() SAL_OVERRIDE;
207 virtual bool DeactivatePage() SAL_OVERRIDE;
209 // our own overridables
211 /// to override to create new pages
212 virtual VclPtr<TabPage> createPage(WizardState _nState) = 0;
214 /// will be called when a new page is about to be displayed
215 virtual void enterState(WizardState _nState);
217 /** will be called when the current state is about to be left for the given reason
219 The base implementation in this class will simply call <member>OWizardPage::commitPage</member>
220 for the current page, and return whatever this call returns.
222 @param _eReason
223 The reason why the state is to be left.
224 @return
225 <TRUE/> if and only if the page is allowed to be left
227 virtual bool prepareLeaveCurrentState( CommitPageReason _eReason );
229 /** will be called when the given state is left
231 This is the very last possibility for derived classes to veto the deactivation
232 of a page.
234 @todo Normally, we would not need the return value here - derived classes now have
235 the possibility to veto page deactivations in <member>prepareLeaveCurrentState</member>. However,
236 changing this return type is too incompatible at the moment ...
238 @return
239 <TRUE/> if and only if the page is allowed to be left
241 virtual bool leaveState( WizardState _nState );
243 /** determine the next state to travel from the given one
245 The default behaviour is linear traveling, overwrite this to change it
247 Return WZS_INVALID_STATE to prevent traveling.
249 virtual WizardState determineNextState( WizardState _nCurrentState ) const;
251 /** called when the finish button is pressed
252 <p>By default, only the base class' Finish method (which is not virtual) is called</p>
254 virtual bool onFinish();
256 /// travel to the next state
257 bool travelNext();
259 /// travel to the previous state
260 bool travelPrevious();
262 /** enables the automatic enabled/disabled state of the "Next" button
264 If this is <TRUE/>, then upon entering a new state, the "Next" button will automatically be
265 enabled if and only if determineNextState does not return WZS_INVALID_STATE.
267 void enableAutomaticNextButtonState( bool _bEnable = true );
268 bool isAutomaticNextButtonStateEnabled() const;
270 /** removes a page from the history. Should be called when the page is being disabled
272 void removePageFromHistory( WizardState nToRemove );
274 /** skip a state
276 The method behaves as if from the current state, <arg>_nSteps</arg> <method>travelNext</method>s were
277 called, but without actually creating or displaying the \EDntermediate pages. Only the
278 (<arg>_nSteps</arg> + 1)th page is created.
280 The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
282 A very essential precondition for using this method is that your <method>determineNextState</method>
283 method is able to determine the next state without actually having the page of the current state.
285 @return
286 <TRUE/> if and only if traveling was successful
288 @see skipUntil
289 @see skipBackwardUntil
291 bool skip( sal_Int32 _nSteps = 1 );
293 /** skips one or more states, until a given state is reached
295 The method behaves as if from the current state, <method>travelNext</method>s were called
296 successively, until <arg>_nTargetState</arg> is reached, but without actually creating or
297 displaying the \EDntermediate pages.
299 The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
301 @return
302 <TRUE/> if and only if traveling was successful
304 @see skip
305 @see skipBackwardUntil
307 bool skipUntil( WizardState _nTargetState );
309 /** moves back one or more states, until a given state is reached
311 This method allows traveling backwards more than one state without actually showing the intermediate
312 states.
314 For instance, if you want to travel two steps backward at a time, you could used
315 two travelPrevious calls, but this would <em>show</em> both pages, which is not necessary,
316 since you're interested in the target page only. Using <member>skipBackwardUntil</member> relieves
317 you of this.
319 @return
320 <TRUE/> if and only if traveling was successful
322 @see skipUntil
323 @see skip
325 bool skipBackwardUntil( WizardState _nTargetState );
327 /** returns the current state of the machine
329 Vulgo, this is the identifier of the current tab page :)
331 WizardState getCurrentState() const { return WizardDialog::GetCurLevel(); }
333 virtual IWizardPageController*
334 getPageController( TabPage* _pCurrentPage ) const;
336 /** retrieves a copy of the state history, i.e. all states we already visited
338 void getStateHistory( ::std::vector< WizardState >& _out_rHistory );
340 public:
341 class AccessGuard
343 friend class WizardTravelSuspension;
344 private:
345 AccessGuard() { }
348 void suspendTraveling( AccessGuard );
349 void resumeTraveling( AccessGuard );
350 bool isTravelingSuspended() const;
352 protected:
353 TabPage* GetOrCreatePage( const WizardState i_nState );
355 private:
356 DECL_DLLPRIVATE_LINK(OnNextPage, void*);
357 DECL_DLLPRIVATE_LINK(OnPrevPage, void*);
358 DECL_DLLPRIVATE_LINK(OnFinish, void*);
360 SVT_DLLPRIVATE void implResetDefault(vcl::Window* _pWindow);
361 SVT_DLLPRIVATE void implUpdateTitle();
362 SVT_DLLPRIVATE void implConstruct( const WizardButtonFlags _nButtonFlags );
365 /// helper class to temporarily suspend any traveling in the wizard
366 class WizardTravelSuspension
368 public:
369 WizardTravelSuspension( OWizardMachine& _rWizard )
370 :m_rWizard( _rWizard )
372 m_rWizard.suspendTraveling( OWizardMachine::AccessGuard() );
375 ~WizardTravelSuspension()
377 m_rWizard.resumeTraveling( OWizardMachine::AccessGuard() );
380 private:
381 OWizardMachine& m_rWizard;
385 } // namespace svt
388 #endif // INCLUDED_SVTOOLS_WIZARDMACHINE_HXX
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */