diff options
Diffstat (limited to 'include/svtools/wizardmachine.hxx')
-rw-r--r-- | include/svtools/wizardmachine.hxx | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/include/svtools/wizardmachine.hxx b/include/svtools/wizardmachine.hxx new file mode 100644 index 000000000000..8283b131007d --- /dev/null +++ b/include/svtools/wizardmachine.hxx @@ -0,0 +1,385 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef _SVTOOLS_WIZARDMACHINE_HXX_ +#define _SVTOOLS_WIZARDMACHINE_HXX_ + +#include "svtools/svtdllapi.h" +#include <svtools/wizdlg.hxx> +#include <vcl/button.hxx> +#include <vcl/tabpage.hxx> +#include <comphelper/stl_types.hxx> + +class Bitmap; +//......................................................................... +namespace svt +{ +//......................................................................... + +// wizard buttons +#define WZB_NONE 0x0000 +#define WZB_NEXT 0x0001 +#define WZB_PREVIOUS 0x0002 +#define WZB_FINISH 0x0004 +#define WZB_CANCEL 0x0008 +#define WZB_HELP 0x0010 + +// wizard states +#define WZS_INVALID_STATE ((WizardState)-1) + + //===================================================================== + //= WizardTypes + //===================================================================== + struct WizardTypes + { + typedef sal_Int16 WizardState; + enum CommitPageReason + { + eTravelForward, // traveling forward (maybe with skipping pages) + eTravelBackward, // traveling backward (maybe with skipping pages) + eFinish, // the wizard is about to be finished + eValidate // the data should be validated only, no traveling wll happen + }; + }; + + class SAL_NO_VTABLE IWizardPageController + { + public: + //----------------------------------------------------------------- + // This methods behave somewhat different than ActivatePage/DeactivatePage + // The latter are handled by the base class itself whenever changing the pages is in the offing, + // i.e., when it's already decided which page is the next. + // We may have situations where the next page depends on the state of the current, which needs + // to be committed for this. + // So initializePage and commitPage are designated to initialitzing/committing data on the page. + virtual void initializePage() = 0; + virtual sal_Bool commitPage( WizardTypes::CommitPageReason _eReason ) = 0; + + /** determines whether or not it is allowed to advance to a next page + + You should make this dependent on the current state of the page only, not on + states on other pages of the whole dialog. + + The default implementation always returns <TRUE/>. + */ + virtual bool canAdvance() const = 0; + + protected: + ~IWizardPageController() {} + }; + + //===================================================================== + //= OWizardPage + //===================================================================== + class OWizardMachine; + struct WizardPageImplData; + + class SVT_DLLPUBLIC OWizardPage : public TabPage, public IWizardPageController + { + private: + WizardPageImplData* m_pImpl; + + public: + /** @param _pParent + if the OWizardPage is used in an OWizardMachine, this parameter + must be the OWizardMachine (which is derived from Window) + */ + OWizardPage( Window* _pParent, const ResId& _rResId ); + ~OWizardPage(); + + // IWizardPageController overridables + virtual void initializePage(); + virtual sal_Bool commitPage( WizardTypes::CommitPageReason _eReason ); + virtual bool canAdvance() const; + + protected: + // TabPage overridables + virtual void ActivatePage(); + + /** updates the travel-related UI elements of the OWizardMachine we live in (if any) + + If the parent of the tab page is a OWizardMachine, then updateTravelUI at this instance + is called. Otherwise, nothing happens. + */ + void updateDialogTravelUI(); + }; + + //===================================================================== + //= OWizardMachine + //===================================================================== + struct WizardMachineImplData; + /** implements some kind of finite automata, where the states of the automata exactly correlate + with tab pages. + + That is, the machine can have up to n states, where at each point in time exactly one state is + the current one. A state being current is represented as one of n tab pages being displayed + currently. + + The class handles the UI for traveling between the states (e.g. it administrates the <em>Next</em> and + <em>Previous</em> buttons which you usually find in a wizard. + + Derived classes have to implement the travel logic by overriding <member>determineNextState</member>, + which has to determine the state which follows the current state. Since this may depend + on the actual data presented in the wizard (e.g. checkboxes checked, or something like this), + they can implement non-linear traveling this way. + */ + + class SVT_DLLPUBLIC OWizardMachine : public WizardDialog, public WizardTypes + { + private: + // restrict access to some aspects of our base class + SVT_DLLPRIVATE void AddPage( TabPage* pPage ) { WizardDialog::AddPage(pPage); } + SVT_DLLPRIVATE void RemovePage( TabPage* pPage ) { WizardDialog::RemovePage(pPage); } + SVT_DLLPRIVATE void SetPage( sal_uInt16 nLevel, TabPage* pPage ) { WizardDialog::SetPage(nLevel, pPage); } + // TabPage* GetPage( sal_uInt16 nLevel ) const { return WizardDialog::GetPage(nLevel); } + // TODO: probably the complete page handling (next, previous etc.) should be prohibited ... + + // IMPORTANT: + // traveling pages should not be done by calling these base class member, some mechanisms of this class + // here (e.g. committing page data) depend on having full control over page traveling. + // So use the travelXXX methods if you need to travel + + protected: + OKButton* m_pFinish; + CancelButton* m_pCancel; + PushButton* m_pNextPage; + PushButton* m_pPrevPage; + HelpButton* m_pHelp; + + private: + WizardMachineImplData* + m_pImpl; + // hold members in this structure to allow keeping compatible when members are added + + SVT_DLLPRIVATE void addButtons(Window* _pParent, sal_uInt32 _nButtonFlags); + + public: + /** ctor + + The ctor does not call FreeResource, this is the resposibility of the derived class. + + For the button flags, use any combination of the WZB_* flags. + */ + OWizardMachine(Window* _pParent, const ResId& _rRes, sal_uInt32 _nButtonFlags ); + OWizardMachine(Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags ); + ~OWizardMachine(); + + /// enable (or disable) buttons + void enableButtons(sal_uInt32 _nWizardButtonFlags, sal_Bool _bEnable); + /// set the default style for a button + void defaultButton(sal_uInt32 _nWizardButtonFlags); + /// set the default style for a button + void defaultButton(PushButton* _pNewDefButton); + + /// set the base of the title to use - the title of the current page is appended + void setTitleBase(const String& _rTitleBase); + + /// determines whether there is a next state to which we can advance + virtual bool canAdvance() const; + + /** updates the user interface which deals with traveling in the wizard + + The default implementation simply checks whether both the current page and the wizard + itself allow to advance to the next state (<code>canAdvance</code>), and enables the "Next" + button if and only if this is the case. + */ + virtual void updateTravelUI(); + + protected: + // WizardDialog overridables + virtual void ActivatePage(); + virtual long DeactivatePage(); + + // our own overridables + + /// to override to create new pages + virtual TabPage* createPage(WizardState _nState) = 0; + + /// will be called when a new page is about to be displayed + virtual void enterState(WizardState _nState); + + /** will be called when the current state is about to be left for the given reason + + The base implementation in this class will simply call <member>OWizardPage::commitPage</member> + for the current page, and return whatever this call returns. + + @param _eReason + The reason why the state is to be left. + @return + <TRUE/> if and only if the page is allowed to be left + */ + virtual sal_Bool prepareLeaveCurrentState( CommitPageReason _eReason ); + + /** will be called when the given state is left + + This is the very last possibility for derived classes to veto the deactivation + of a page. + + @todo Normally, we would not need the return value here - derived classes now have + the possibility to veto page deactivations in <member>prepareLeaveCurrentState</member>. However, + changing this return type is too incompatible at the moment ... + + @return + <TRUE/> if and only if the page is allowed to be left + */ + virtual sal_Bool leaveState( WizardState _nState ); + + /** determine the next state to travel from the given one + + The default behaviour is linear traveling, overwrite this to change it + + Return WZS_INVALID_STATE to prevent traveling. + */ + virtual WizardState determineNextState( WizardState _nCurrentState ) const; + + /** called when the finish button is pressed + <p>By default, only the base class' Finnish method (which is not virtual) is called</p> + */ + virtual sal_Bool onFinish(); + + /// travel to the next state + sal_Bool travelNext(); + + /// travel to the previous state + sal_Bool travelPrevious(); + + /** enables the automatic enabled/disabled state of the "Next" button + + If this is <TRUE/>, then upon entering a new state, the "Next" button will automatically be + enabled if and only if determineNextState does not return WZS_INVALID_STATE. + */ + void enableAutomaticNextButtonState( bool _bEnable = true ); + bool isAutomaticNextButtonStateEnabled() const; + + /** removes a page from the history. Should be called when the page is being disabled + */ + void removePageFromHistory( WizardState nToRemove ); + + /** skip a state + + The method behaves as if from the current state, <arg>_nSteps</arg> <method>travelNext</method>s were + called, but without actually creating or displaying the íntermediate pages. Only the + (<arg>_nSteps</arg> + 1)th page is created. + + The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them. + + A very essential precondition for using this method is that your <method>determineNextState</method> + method is able to determine the next state without actually having the page of the current state. + + @return + <TRUE/> if and only if traveling was successful + + @see skipUntil + @see skipBackwardUntil + */ + sal_Bool skip( sal_Int32 _nSteps = 1 ); + + /** skips one or more states, until a given state is reached + + The method behaves as if from the current state, <method>travelNext</method>s were called + successively, until <arg>_nTargetState</arg> is reached, but without actually creating or + displaying the íntermediate pages. + + The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them. + + @return + <TRUE/> if and only if traveling was successful + + @see skip + @see skipBackwardUntil + */ + sal_Bool skipUntil( WizardState _nTargetState ); + + /** moves back one or more states, until a given state is reached + + This method allows traveling backwards more than one state without actually showing the intermediate + states. + + For instance, if you want to travel two steps backward at a time, you could used + two travelPrevious calls, but this would <em>show</em> both pages, which is not necessary, + since you're interested in the target page only. Using <member>skipBackwardUntil</member> reliefs + you from this. + + @return + <TRUE/> if and only if traveling was successful + + @see skipUntil + @see skip + */ + sal_Bool skipBackwardUntil( WizardState _nTargetState ); + + /** returns the current state of the machine + + Vulgo, this is the identifier of the current tab page :) + */ + WizardState getCurrentState() const { return WizardDialog::GetCurLevel(); } + + virtual IWizardPageController* + getPageController( TabPage* _pCurrentPage ) const; + + /** retrieves a copy of the state history, i.e. all states we already visited + */ + void getStateHistory( ::std::vector< WizardState >& _out_rHistory ); + + public: + class AccessGuard { friend class WizardTravelSuspension; private: AccessGuard() { } }; + + void suspendTraveling( AccessGuard ); + void resumeTraveling( AccessGuard ); + bool isTravelingSuspended() const; + + protected: + TabPage* GetOrCreatePage( const WizardState i_nState ); + + private: + // long OnNextPage( PushButton* ); + DECL_DLLPRIVATE_LINK(OnNextPage, void*); + DECL_DLLPRIVATE_LINK(OnPrevPage, void*); + DECL_DLLPRIVATE_LINK(OnFinish, void*); + + SVT_DLLPRIVATE void implResetDefault(Window* _pWindow); + SVT_DLLPRIVATE void implUpdateTitle(); + SVT_DLLPRIVATE void implConstruct( const sal_uInt32 _nButtonFlags ); + }; + + /// helper class to temporarily suspend any traveling in the wizard + class WizardTravelSuspension + { + public: + WizardTravelSuspension( OWizardMachine& _rWizard ) + :m_rWizard( _rWizard ) + { + m_rWizard.suspendTraveling( OWizardMachine::AccessGuard() ); + } + + ~WizardTravelSuspension() + { + m_rWizard.resumeTraveling( OWizardMachine::AccessGuard() ); + } + + private: + OWizardMachine& m_rWizard; + }; + +//......................................................................... +} // namespace svt +//......................................................................... + +#endif // _SVTOOLS_WIZARDMACHINE_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |