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