1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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_VCL_WIZARDMACHINE_HXX
20 #define INCLUDED_VCL_WIZARDMACHINE_HXX
23 #include <vcl/dllapi.h>
24 #include <vcl/builderpage.hxx>
25 #include <vcl/idle.hxx>
33 struct ImplWizButtonData
;
36 #define WZS_INVALID_STATE (::vcl::WizardTypes::WizardState(-1))
43 typedef sal_Int16 WizardState
;
46 eTravelForward
, // traveling forward (maybe with skipping pages)
47 eTravelBackward
, // traveling backward (maybe with skipping pages)
48 eFinish
, // the wizard is about to be finished
49 eValidate
// the data should be validated only, no traveling will happen
53 class SAL_NO_VTABLE IWizardPageController
57 // This methods behave somewhat different than ActivatePage/DeactivatePage
58 // The latter are handled by the base class itself whenever changing the pages is in the offing,
59 // i.e., when it's already decided which page is the next.
60 // We may have situations where the next page depends on the state of the current, which needs
61 // to be committed for this.
62 // So initializePage and commitPage are designated to initializing/committing data on the page.
63 virtual void initializePage() = 0;
64 virtual bool commitPage( WizardTypes::CommitPageReason _eReason
) = 0;
66 /** determines whether or not it is allowed to advance to a next page
68 You should make this dependent on the current state of the page only, not on
69 states on other pages of the whole dialog.
71 The default implementation always returns <TRUE/>.
73 virtual bool canAdvance() const = 0;
76 ~IWizardPageController() {}
80 class VCL_DLLPUBLIC OWizardPage
: public BuilderPage
, public IWizardPageController
83 OWizardPage(weld::Container
* pPage
, weld::DialogController
* pController
, const OUString
& rUIXMLDescription
, const OString
& rID
);
84 virtual ~OWizardPage() override
;
86 // IWizardPageController overridables
87 virtual void initializePage() override
;
88 virtual bool commitPage( WizardTypes::CommitPageReason _eReason
) override
;
89 virtual bool canAdvance() const override
;
92 // BuilderPage overridables
93 virtual void Activate() override
;
95 /** updates the travel-related UI elements of the OWizardMachine we live in (if any)
97 If the parent of the tab page is an OWizardMachine, then updateTravelUI at this instance
98 is called. Otherwise, nothing happens.
100 void updateDialogTravelUI();
104 struct WizardMachineImplData
;
105 /** implements some kind of finite automata, where the states of the automata exactly correlate
108 That is, the machine can have up to n states, where at each point in time exactly one state is
109 the current one. A state being current is represented as one of n tab pages being displayed
112 The class handles the UI for traveling between the states (e.g. it administrates the <em>Next</em> and
113 <em>Previous</em> buttons which you usually find in a wizard.
115 Derived classes have to implement the travel logic by overriding <member>determineNextState</member>,
116 which has to determine the state which follows the current state. Since this may depend
117 on the actual data presented in the wizard (e.g. checkboxes checked, or something like this),
118 they can implement non-linear traveling this way.
120 class VCL_DLLPUBLIC WizardMachine
: public weld::AssistantController
123 BuilderPage
* m_pCurTabPage
;
125 WizardTypes::WizardState m_nCurState
;
126 WizPageData
* m_pFirstPage
;
129 std::unique_ptr
<weld::Button
> m_xFinish
;
130 std::unique_ptr
<weld::Button
> m_xCancel
;
131 std::unique_ptr
<weld::Button
> m_xNextPage
;
132 std::unique_ptr
<weld::Button
> m_xPrevPage
;
133 std::unique_ptr
<weld::Button
> m_xHelp
;
136 // hold members in this structure to allow keeping compatible when members are added
137 std::unique_ptr
<WizardMachineImplData
> m_pImpl
;
140 WizardMachine(weld::Window
* _pParent
, WizardButtonFlags _nButtonFlags
);
141 virtual ~WizardMachine() override
;
143 bool Finish(short nResult
= RET_CANCEL
);
144 bool ShowPage(WizardTypes::WizardState nState
);
149 void AddPage( std::unique_ptr
<BuilderPage
> xPage
);
150 void RemovePage( const BuilderPage
* pPage
);
151 void SetPage( WizardTypes::WizardState nLevel
, std::unique_ptr
<BuilderPage
> xPage
);
152 BuilderPage
* GetPage( WizardTypes::WizardState eState
) const;
154 /// enable (or disable) buttons
155 void enableButtons(WizardButtonFlags _nWizardButtonFlags
, bool _bEnable
);
156 /// set the default style for a button
157 void defaultButton(WizardButtonFlags _nWizardButtonFlags
);
158 /// set the default style for a button
159 void defaultButton(weld::Button
* _pNewDefButton
);
161 /// set the base of the title to use - the title of the current page is appended
162 void setTitleBase(const OUString
& _rTitleBase
);
164 /// determines whether there is a next state to which we can advance
165 virtual bool canAdvance() const;
167 /** updates the user interface which deals with traveling in the wizard
169 The default implementation simply checks whether both the current page and the wizard
170 itself allow to advance to the next state (<code>canAdvance</code>), and enables the "Next"
171 button if and only if this is the case.
173 virtual void updateTravelUI();
176 virtual void ActivatePage();
177 virtual bool DeactivatePage();
179 // our own overridables
181 /// to override to create new pages
182 virtual std::unique_ptr
<BuilderPage
> createPage(WizardTypes::WizardState _nState
) = 0;
184 /// will be called when a new page is about to be displayed
185 virtual void enterState(WizardTypes::WizardState _nState
);
187 /** will be called when the current state is about to be left for the given reason
189 The base implementation in this class will simply call <member>OWizardPage::commitPage</member>
190 for the current page, and return whatever this call returns.
193 The reason why the state is to be left.
195 <TRUE/> if and only if the page is allowed to be left
197 virtual bool prepareLeaveCurrentState( WizardTypes::CommitPageReason eReason
);
199 /** will be called when the given state is left
201 This is the very last possibility for derived classes to veto the deactivation
204 @todo Normally, we would not need the return value here - derived classes now have
205 the possibility to veto page deactivations in <member>prepareLeaveCurrentState</member>. However,
206 changing this return type is too incompatible at the moment ...
209 <TRUE/> if and only if the page is allowed to be left
211 virtual bool leaveState(WizardTypes::WizardState nState
);
213 /** determine the next state to travel from the given one
215 The default behaviour is linear traveling, overwrite this to change it
217 Return WZS_INVALID_STATE to prevent traveling.
219 virtual WizardTypes::WizardState
determineNextState(WizardTypes::WizardState nCurrentState
) const;
221 /** called when the finish button is pressed
222 <p>By default, only the base class' Finish method (which is not virtual) is called</p>
224 virtual bool onFinish();
226 /// travel to the next state
229 /// travel to the previous state
230 bool travelPrevious();
232 /** enables the automatic enabled/disabled state of the "Next" button
234 If this is <TRUE/>, then upon entering a new state, the "Next" button will automatically be
235 enabled if and only if determineNextState does not return WZS_INVALID_STATE.
237 void enableAutomaticNextButtonState();
238 bool isAutomaticNextButtonStateEnabled() const;
240 /** removes a page from the history. Should be called when the page is being disabled
242 void removePageFromHistory(WizardTypes::WizardState nToRemove
);
246 The method behaves as if from the current state, <arg>_nSteps</arg> <method>travelNext</method>s were
247 called, but without actually creating or displaying the \EDntermediate pages. Only the
248 (<arg>_nSteps</arg> + 1)th page is created.
250 The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
252 A very essential precondition for using this method is that your <method>determineNextState</method>
253 method is able to determine the next state without actually having the page of the current state.
256 @see skipBackwardUntil
260 /** skips one or more states, until a given state is reached
262 The method behaves as if from the current state, <method>travelNext</method>s were called
263 successively, until <arg>_nTargetState</arg> is reached, but without actually creating or
264 displaying the \EDntermediate pages.
266 The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
269 <TRUE/> if and only if traveling was successful
272 @see skipBackwardUntil
274 bool skipUntil(WizardTypes::WizardState nTargetState
);
276 /** moves back one or more states, until a given state is reached
278 This method allows traveling backwards more than one state without actually showing the intermediate
281 For instance, if you want to travel two steps backward at a time, you could used
282 two travelPrevious calls, but this would <em>show</em> both pages, which is not necessary,
283 since you're interested in the target page only. Using <member>skipBackwardUntil</member> relieves
287 <TRUE/> if and only if traveling was successful
292 bool skipBackwardUntil(WizardTypes::WizardState nTargetState
);
294 /** returns the current state of the machine
296 Vulgo, this is the identifier of the current tab page :)
298 WizardTypes::WizardState
getCurrentState() const { return m_nCurState
; }
300 virtual IWizardPageController
* getPageController(BuilderPage
* pCurrentPage
) const;
302 /** retrieves a copy of the state history, i.e. all states we already visited
304 void getStateHistory(std::vector
<WizardTypes::WizardState
>& out_rHistory
);
309 friend class WizardTravelSuspension
;
314 void suspendTraveling( AccessGuard
);
315 void resumeTraveling( AccessGuard
);
316 bool isTravelingSuspended() const;
319 BuilderPage
* GetOrCreatePage(const WizardTypes::WizardState i_nState
);
322 DECL_DLLPRIVATE_LINK(OnNextPage
, weld::Button
&, void);
323 DECL_DLLPRIVATE_LINK(OnPrevPage
, weld::Button
&, void);
324 DECL_DLLPRIVATE_LINK(OnFinish
, weld::Button
&, void);
325 DECL_DLLPRIVATE_LINK(OnCancel
, weld::Button
&, void);
327 VCL_DLLPRIVATE
void implUpdateTitle();
328 VCL_DLLPRIVATE
void implConstruct( const WizardButtonFlags _nButtonFlags
);
332 /// helper class to temporarily suspend any traveling in the wizard
333 class WizardTravelSuspension
336 WizardTravelSuspension(WizardMachine
& rWizard
)
337 : m_pWizard(&rWizard
)
339 m_pWizard
->suspendTraveling(WizardMachine::AccessGuard());
342 ~WizardTravelSuspension()
344 m_pWizard
->resumeTraveling(WizardMachine::AccessGuard());
348 WizardMachine
* m_pWizard
;
352 #define WIZARDDIALOG_BUTTON_STDOFFSET_X 6
353 #define WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X 3
355 #endif // INCLUDED_VCL_WIZARDMACHINE_HXX
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */