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