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