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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svtools.hxx" 26 #include <svtools/wizardmachine.hxx> 27 #include <svtools/helpid.hrc> 28 #include <tools/debug.hxx> 29 #include <tools/diagnose_ex.h> 30 #include <vcl/msgbox.hxx> 31 #include <svtools/svtdata.hxx> 32 #ifndef _SVTOOLS_HRC 33 #include <svtools/svtools.hrc> 34 #endif 35 36 //......................................................................... 37 namespace svt 38 { 39 //......................................................................... 40 41 //===================================================================== 42 //= WizardPageImplData 43 //===================================================================== 44 struct WizardPageImplData 45 { WizardPageImplDatasvt::WizardPageImplData46 WizardPageImplData() 47 { 48 } 49 }; 50 51 //===================================================================== 52 //= OWizardPage 53 //===================================================================== 54 //--------------------------------------------------------------------- OWizardPage(Window * _pParent,WinBits _nStyle)55 OWizardPage::OWizardPage( Window* _pParent, WinBits _nStyle ) 56 :TabPage( _pParent, _nStyle ) 57 ,m_pImpl( new WizardPageImplData ) 58 { 59 } 60 61 //--------------------------------------------------------------------- OWizardPage(Window * _pParent,const ResId & _rResId)62 OWizardPage::OWizardPage( Window* _pParent, const ResId& _rResId ) 63 :TabPage( _pParent, _rResId ) 64 ,m_pImpl( new WizardPageImplData ) 65 { 66 } 67 68 //--------------------------------------------------------------------- ~OWizardPage()69 OWizardPage::~OWizardPage() 70 { 71 delete m_pImpl; 72 } 73 74 //--------------------------------------------------------------------- initializePage()75 void OWizardPage::initializePage() 76 { 77 } 78 79 //--------------------------------------------------------------------- ActivatePage()80 void OWizardPage::ActivatePage() 81 { 82 TabPage::ActivatePage(); 83 updateDialogTravelUI(); 84 } 85 86 //--------------------------------------------------------------------- updateDialogTravelUI()87 void OWizardPage::updateDialogTravelUI() 88 { 89 OWizardMachine* pWizardMachine = dynamic_cast< OWizardMachine* >( GetParent() ); 90 if ( pWizardMachine ) 91 pWizardMachine->updateTravelUI(); 92 } 93 94 //--------------------------------------------------------------------- canAdvance() const95 bool OWizardPage::canAdvance() const 96 { 97 return true; 98 } 99 100 //--------------------------------------------------------------------- commitPage(WizardTypes::CommitPageReason)101 sal_Bool OWizardPage::commitPage( WizardTypes::CommitPageReason ) 102 { 103 return sal_True; 104 } 105 106 //===================================================================== 107 //= WizardMachineImplData 108 //===================================================================== 109 struct WizardMachineImplData : public WizardTypes 110 { 111 String sTitleBase; // the base for the title 112 ::std::stack< WizardState > aStateHistory; // the history of all states (used for implementing "Back") 113 114 WizardState nFirstUnknownPage; 115 // the WizardDialog does not allow non-linear transitions (e.g. it's 116 // not possible to add pages in a non-linear order), so we need some own maintainance data 117 118 sal_Bool m_bAutoNextButtonState; 119 120 bool m_bTravelingSuspended; 121 WizardMachineImplDatasvt::WizardMachineImplData122 WizardMachineImplData() 123 :nFirstUnknownPage( 0 ) 124 ,m_bAutoNextButtonState( sal_False ) 125 ,m_bTravelingSuspended( false ) 126 { 127 } 128 }; 129 calcRightHelpOffset(sal_uInt32 _nButtonFlags)130 long OWizardMachine::calcRightHelpOffset(sal_uInt32 _nButtonFlags) 131 { 132 sal_Int32 nMask = 1; 133 sal_Int32 nRightAlignedButtonCount = -1; 134 for (unsigned int i = 0; i < 8*sizeof(_nButtonFlags); i++ ) 135 { 136 if( ( _nButtonFlags & nMask ) != 0 ) 137 nRightAlignedButtonCount++; 138 nMask <<= 1; 139 } 140 Size aSize = GetPageSizePixel(); 141 sal_Int32 nTotButtonWidth = nRightAlignedButtonCount * LogicalCoordinateToPixel(50); 142 sal_Int32 nTotRightButtonSpaceOffset = (nRightAlignedButtonCount) * WIZARDDIALOG_BUTTON_STDOFFSET_X; 143 if ((_nButtonFlags & WZB_NEXT) && (_nButtonFlags & WZB_NEXT)) 144 nTotRightButtonSpaceOffset = (nTotRightButtonSpaceOffset - WIZARDDIALOG_BUTTON_STDOFFSET_X) + WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X; 145 return aSize.Width() - nTotButtonWidth - nTotRightButtonSpaceOffset; 146 } 147 148 //===================================================================== 149 //= OWizardMachine 150 //===================================================================== 151 //--------------------------------------------------------------------- OWizardMachine(Window * _pParent,const ResId & _rRes,sal_uInt32 _nButtonFlags)152 OWizardMachine::OWizardMachine(Window* _pParent, const ResId& _rRes, sal_uInt32 _nButtonFlags ) 153 :WizardDialog( _pParent, _rRes ) 154 ,m_pFinish(NULL) 155 ,m_pCancel(NULL) 156 ,m_pNextPage(NULL) 157 ,m_pPrevPage(NULL) 158 ,m_pHelp(NULL) 159 ,m_pImpl( new WizardMachineImplData ) 160 { 161 implConstruct( _nButtonFlags ); 162 } 163 164 //--------------------------------------------------------------------- OWizardMachine(Window * _pParent,const WinBits i_nStyle,sal_uInt32 _nButtonFlags)165 OWizardMachine::OWizardMachine(Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags ) 166 :WizardDialog( _pParent, i_nStyle ) 167 ,m_pFinish(NULL) 168 ,m_pCancel(NULL) 169 ,m_pNextPage(NULL) 170 ,m_pPrevPage(NULL) 171 ,m_pHelp(NULL) 172 ,m_pImpl( new WizardMachineImplData ) 173 { 174 implConstruct( _nButtonFlags ); 175 } 176 177 //--------------------------------------------------------------------- implConstruct(const sal_uInt32 _nButtonFlags)178 void OWizardMachine::implConstruct( const sal_uInt32 _nButtonFlags ) 179 { 180 m_pImpl->sTitleBase = GetText(); 181 182 // create the buttons according to the wizard button flags 183 // the help button 184 if (_nButtonFlags & WZB_HELP) 185 { 186 m_pHelp= new HelpButton(this, WB_TABSTOP); 187 m_pHelp->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) ); 188 m_pHelp->Show(); 189 AddButton( m_pHelp, WIZARDDIALOG_BUTTON_STDOFFSET_X); 190 } 191 192 // the previous button 193 if (_nButtonFlags & WZB_PREVIOUS) 194 { 195 m_pPrevPage = new PushButton(this, WB_TABSTOP); 196 m_pPrevPage->SetHelpId( HID_WIZARD_PREVIOUS ); 197 m_pPrevPage->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) ); 198 m_pPrevPage->SetText(String(SvtResId(STR_WIZDLG_PREVIOUS))); 199 m_pPrevPage->Show(); 200 201 if (_nButtonFlags & WZB_NEXT) 202 AddButton( m_pPrevPage, ( WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X) ); // half x-offset to the next button 203 else 204 AddButton( m_pPrevPage, WIZARDDIALOG_BUTTON_STDOFFSET_X ); 205 SetPrevButton( m_pPrevPage ); 206 m_pPrevPage->SetClickHdl( LINK( this, OWizardMachine, OnPrevPage ) ); 207 } 208 209 // the next button 210 if (_nButtonFlags & WZB_NEXT) 211 { 212 m_pNextPage = new PushButton(this, WB_TABSTOP); 213 m_pNextPage->SetHelpId( HID_WIZARD_NEXT ); 214 m_pNextPage->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) ); 215 m_pNextPage->SetText(String(SvtResId(STR_WIZDLG_NEXT))); 216 m_pNextPage->Show(); 217 218 AddButton( m_pNextPage, WIZARDDIALOG_BUTTON_STDOFFSET_X ); 219 SetNextButton( m_pNextPage ); 220 m_pNextPage->SetClickHdl( LINK( this, OWizardMachine, OnNextPage ) ); 221 } 222 223 // the finish button 224 if (_nButtonFlags & WZB_FINISH) 225 { 226 m_pFinish = new OKButton(this, WB_TABSTOP); 227 m_pFinish->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) ); 228 m_pFinish->SetText(String(SvtResId(STR_WIZDLG_FINISH))); 229 m_pFinish->Show(); 230 231 AddButton( m_pFinish, WIZARDDIALOG_BUTTON_STDOFFSET_X ); 232 m_pFinish->SetClickHdl( LINK( this, OWizardMachine, OnFinish ) ); 233 } 234 235 // the cancel button 236 if (_nButtonFlags & WZB_CANCEL) 237 { 238 m_pCancel = new CancelButton(this, WB_TABSTOP); 239 m_pCancel->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) ); 240 m_pCancel->Show(); 241 242 AddButton( m_pCancel, WIZARDDIALOG_BUTTON_STDOFFSET_X ); 243 } 244 } 245 246 //--------------------------------------------------------------------- ~OWizardMachine()247 OWizardMachine::~OWizardMachine() 248 { 249 delete m_pFinish; 250 delete m_pCancel; 251 delete m_pNextPage; 252 delete m_pPrevPage; 253 delete m_pHelp; 254 255 for (WizardState i=0; i<m_pImpl->nFirstUnknownPage; ++i) 256 delete GetPage(i); 257 258 delete m_pImpl; 259 } 260 261 //--------------------------------------------------------------------- implUpdateTitle()262 void OWizardMachine::implUpdateTitle() 263 { 264 String sCompleteTitle(m_pImpl->sTitleBase); 265 266 // append the page title 267 TabPage* pCurrentPage = GetPage(getCurrentState()); 268 if ( pCurrentPage && pCurrentPage->GetText().Len() ) 269 { 270 sCompleteTitle += String::CreateFromAscii(" - "); 271 sCompleteTitle += pCurrentPage->GetText(); 272 } 273 274 SetText(sCompleteTitle); 275 } 276 277 //--------------------------------------------------------------------- getTitleBase() const278 const String& OWizardMachine::getTitleBase() const 279 { 280 return m_pImpl->sTitleBase; 281 } 282 283 //--------------------------------------------------------------------- setTitleBase(const String & _rTitleBase)284 void OWizardMachine::setTitleBase(const String& _rTitleBase) 285 { 286 m_pImpl->sTitleBase = _rTitleBase; 287 implUpdateTitle(); 288 } 289 290 //--------------------------------------------------------------------- GetOrCreatePage(const WizardState i_nState)291 TabPage* OWizardMachine::GetOrCreatePage( const WizardState i_nState ) 292 { 293 if ( NULL == GetPage( i_nState ) ) 294 { 295 TabPage* pNewPage = createPage( i_nState ); 296 DBG_ASSERT( pNewPage, "OWizardMachine::GetOrCreatePage: invalid new page (NULL)!" ); 297 298 // fill up the page sequence of our base class (with dummies) 299 while ( m_pImpl->nFirstUnknownPage < i_nState ) 300 { 301 AddPage( NULL ); 302 ++m_pImpl->nFirstUnknownPage; 303 } 304 305 if ( m_pImpl->nFirstUnknownPage == i_nState ) 306 { 307 // encountered this page number the first time 308 AddPage( pNewPage ); 309 ++m_pImpl->nFirstUnknownPage; 310 } 311 else 312 // already had this page - just change it 313 SetPage( i_nState, pNewPage ); 314 } 315 return GetPage( i_nState ); 316 } 317 318 //--------------------------------------------------------------------- ActivatePage()319 void OWizardMachine::ActivatePage() 320 { 321 WizardDialog::ActivatePage(); 322 323 WizardState nCurrentLevel = GetCurLevel(); 324 GetOrCreatePage( nCurrentLevel ); 325 326 enterState( nCurrentLevel ); 327 } 328 329 //--------------------------------------------------------------------- DeactivatePage()330 long OWizardMachine::DeactivatePage() 331 { 332 WizardState nCurrentState = getCurrentState(); 333 if (!leaveState(nCurrentState) || !WizardDialog::DeactivatePage()) 334 return sal_False; 335 return sal_True; 336 } 337 338 //--------------------------------------------------------------------- defaultButton(sal_uInt32 _nWizardButtonFlags)339 void OWizardMachine::defaultButton(sal_uInt32 _nWizardButtonFlags) 340 { 341 // the new default button 342 PushButton* pNewDefButton = NULL; 343 if (m_pFinish && (_nWizardButtonFlags & WZB_FINISH)) 344 pNewDefButton = m_pFinish; 345 if (m_pNextPage && (_nWizardButtonFlags & WZB_NEXT)) 346 pNewDefButton = m_pNextPage; 347 if (m_pPrevPage && (_nWizardButtonFlags & WZB_PREVIOUS)) 348 pNewDefButton = m_pPrevPage; 349 if (m_pHelp && (_nWizardButtonFlags & WZB_HELP)) 350 pNewDefButton = m_pHelp; 351 if (m_pCancel && (_nWizardButtonFlags & WZB_CANCEL)) 352 pNewDefButton = m_pCancel; 353 354 if ( pNewDefButton ) 355 defaultButton( pNewDefButton ); 356 else 357 implResetDefault( this ); 358 } 359 360 //--------------------------------------------------------------------- implResetDefault(Window * _pWindow)361 void OWizardMachine::implResetDefault(Window* _pWindow) 362 { 363 Window* pChildLoop = _pWindow->GetWindow(WINDOW_FIRSTCHILD); 364 while (pChildLoop) 365 { 366 // does the window participate in the tabbing order? 367 if (pChildLoop->GetStyle() & WB_DIALOGCONTROL) 368 implResetDefault(pChildLoop); 369 370 // is it a button? 371 WindowType eType = pChildLoop->GetType(); 372 if ( (WINDOW_BUTTON == eType) 373 || (WINDOW_PUSHBUTTON == eType) 374 || (WINDOW_OKBUTTON == eType) 375 || (WINDOW_CANCELBUTTON == eType) 376 || (WINDOW_HELPBUTTON == eType) 377 || (WINDOW_IMAGEBUTTON == eType) 378 || (WINDOW_MENUBUTTON == eType) 379 || (WINDOW_MOREBUTTON == eType) 380 ) 381 { 382 pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON); 383 } 384 385 // the next one ... 386 pChildLoop = pChildLoop->GetWindow(WINDOW_NEXT); 387 } 388 } 389 390 //--------------------------------------------------------------------- defaultButton(PushButton * _pNewDefButton)391 void OWizardMachine::defaultButton(PushButton* _pNewDefButton) 392 { 393 // loop through all (direct and indirect) descendants which participate in our tabbing order, and 394 // reset the WB_DEFBUTTON for every window which is a button 395 implResetDefault(this); 396 397 // set it's new style 398 if (_pNewDefButton) 399 _pNewDefButton->SetStyle(_pNewDefButton->GetStyle() | WB_DEFBUTTON); 400 } 401 402 //--------------------------------------------------------------------- enableButtons(sal_uInt32 _nWizardButtonFlags,sal_Bool _bEnable)403 void OWizardMachine::enableButtons(sal_uInt32 _nWizardButtonFlags, sal_Bool _bEnable) 404 { 405 if (m_pFinish && (_nWizardButtonFlags & WZB_FINISH)) 406 m_pFinish->Enable(_bEnable); 407 if (m_pNextPage && (_nWizardButtonFlags & WZB_NEXT)) 408 m_pNextPage->Enable(_bEnable); 409 if (m_pPrevPage && (_nWizardButtonFlags & WZB_PREVIOUS)) 410 m_pPrevPage->Enable(_bEnable); 411 if (m_pHelp && (_nWizardButtonFlags & WZB_HELP)) 412 m_pHelp->Enable(_bEnable); 413 if (m_pCancel && (_nWizardButtonFlags & WZB_CANCEL)) 414 m_pCancel->Enable(_bEnable); 415 } 416 417 //--------------------------------------------------------------------- enterState(WizardState _nState)418 void OWizardMachine::enterState(WizardState _nState) 419 { 420 // tell the page 421 IWizardPageController* pController = getPageController( GetPage( _nState ) ); 422 OSL_ENSURE( pController, "OWizardMachine::enterState: no controller for the given page!" ); 423 if ( pController ) 424 pController->initializePage(); 425 426 if ( isAutomaticNextButtonStateEnabled() ) 427 enableButtons( WZB_NEXT, canAdvance() ); 428 429 enableButtons( WZB_PREVIOUS, !m_pImpl->aStateHistory.empty() ); 430 431 // set the new title - it depends on the current page (i.e. state) 432 implUpdateTitle(); 433 } 434 435 //--------------------------------------------------------------------- leaveState(WizardState)436 sal_Bool OWizardMachine::leaveState(WizardState) 437 { 438 // no need to ask the page here. 439 // If we reach this point, we already gave the current page the chance to commit it's data, 440 // and it was allowed to commit it's data 441 442 return sal_True; 443 } 444 445 //--------------------------------------------------------------------- onFinish()446 sal_Bool OWizardMachine::onFinish() 447 { 448 return Finnish( RET_OK ); 449 } 450 451 //--------------------------------------------------------------------- IMPL_LINK(OWizardMachine,OnFinish,PushButton *,EMPTYARG)452 IMPL_LINK(OWizardMachine, OnFinish, PushButton*, EMPTYARG) 453 { 454 if ( isTravelingSuspended() ) 455 return 0; 456 WizardTravelSuspension aTravelGuard( *this ); 457 if ( !prepareLeaveCurrentState( eFinish ) ) 458 { 459 return 0L; 460 } 461 return onFinish() ? 1L : 0L; 462 } 463 464 //--------------------------------------------------------------------- determineNextState(WizardState _nCurrentState) const465 OWizardMachine::WizardState OWizardMachine::determineNextState( WizardState _nCurrentState ) const 466 { 467 return _nCurrentState + 1; 468 } 469 470 //--------------------------------------------------------------------- prepareLeaveCurrentState(CommitPageReason _eReason)471 sal_Bool OWizardMachine::prepareLeaveCurrentState( CommitPageReason _eReason ) 472 { 473 IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) ); 474 ENSURE_OR_RETURN( pController != NULL, "OWizardMachine::prepareLeaveCurrentState: no controller for the current page!", sal_True ); 475 return pController->commitPage( _eReason ); 476 } 477 478 //--------------------------------------------------------------------- skipBackwardUntil(WizardState _nTargetState)479 sal_Bool OWizardMachine::skipBackwardUntil( WizardState _nTargetState ) 480 { 481 // alowed to leave the current page? 482 if ( !prepareLeaveCurrentState( eTravelBackward ) ) 483 return sal_False; 484 485 // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong 486 ::std::stack< WizardState > aTravelVirtually = m_pImpl->aStateHistory; 487 ::std::stack< WizardState > aOldStateHistory = m_pImpl->aStateHistory; 488 489 WizardState nCurrentRollbackState = getCurrentState(); 490 while ( nCurrentRollbackState != _nTargetState ) 491 { 492 DBG_ASSERT( !aTravelVirtually.empty(), "OWizardMachine::skipBackwardUntil: this target state does not exist in the history!" ); 493 nCurrentRollbackState = aTravelVirtually.top(); 494 aTravelVirtually.pop(); 495 } 496 m_pImpl->aStateHistory = aTravelVirtually; 497 if ( !ShowPage( _nTargetState ) ) 498 { 499 m_pImpl->aStateHistory = aOldStateHistory; 500 return sal_False; 501 } 502 return sal_True; 503 } 504 505 //--------------------------------------------------------------------- skipUntil(WizardState _nTargetState)506 sal_Bool OWizardMachine::skipUntil( WizardState _nTargetState ) 507 { 508 WizardState nCurrentState = getCurrentState(); 509 510 // alowed to leave the current page? 511 if ( !prepareLeaveCurrentState( nCurrentState < _nTargetState ? eTravelForward : eTravelBackward ) ) 512 return sal_False; 513 514 // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong 515 ::std::stack< WizardState > aTravelVirtually = m_pImpl->aStateHistory; 516 ::std::stack< WizardState > aOldStateHistory = m_pImpl->aStateHistory; 517 while ( nCurrentState != _nTargetState ) 518 { 519 WizardState nNextState = determineNextState( nCurrentState ); 520 if ( WZS_INVALID_STATE == nNextState ) 521 { 522 DBG_ERROR( "OWizardMachine::skipUntil: the given target state does not exist!" ); 523 return sal_False; 524 } 525 526 // remember the skipped state in the history 527 aTravelVirtually.push( nCurrentState ); 528 529 // get the next state 530 nCurrentState = nNextState; 531 } 532 m_pImpl->aStateHistory = aTravelVirtually; 533 // show the target page 534 if ( !ShowPage( nCurrentState ) ) 535 { 536 // argh! prepareLeaveCurrentPage succeeded, determineNextState succeeded, 537 // but ShowPage doesn't? Somebody behaves very strange here .... 538 DBG_ERROR( "OWizardMachine::skipUntil: very unpolite ...." ); 539 m_pImpl->aStateHistory = aOldStateHistory; 540 return sal_False; 541 } 542 return sal_True; 543 } 544 545 //--------------------------------------------------------------------- skip(sal_Int32 _nSteps)546 sal_Bool OWizardMachine::skip(sal_Int32 _nSteps) 547 { 548 DBG_ASSERT(_nSteps > 0, "OWizardMachine::skip: invalid number of steps!"); 549 // alowed to leave the current page? 550 if ( !prepareLeaveCurrentState( eTravelForward ) ) 551 return sal_False; 552 553 WizardState nCurrentState = getCurrentState(); 554 WizardState nNextState = determineNextState(nCurrentState); 555 // loop _nSteps steps 556 while (_nSteps-- > 0) 557 { 558 if (WZS_INVALID_STATE == nNextState) 559 return sal_False; 560 561 // remember the skipped state in the history 562 m_pImpl->aStateHistory.push(nCurrentState); 563 564 // get the next state 565 nCurrentState = nNextState; 566 nNextState = determineNextState(nCurrentState); 567 } 568 569 // show the (n+1)th page 570 if (!ShowPage(nCurrentState)) 571 { 572 // TODO: this leaves us in a state where we have no current page and an inconsistent state history. 573 // Perhaps we should rollback the skipping here .... 574 DBG_ERROR("OWizardMachine::skip: very unpolite ...."); 575 // if somebody does a skip and then does not allow to leave ... 576 // (can't be a commit error, as we've already committed the current page. So if ShowPage fails here, 577 // somebody behaves really strange ...) 578 return sal_False; 579 } 580 581 // all fine 582 return sal_True; 583 } 584 585 //--------------------------------------------------------------------- travelNext()586 sal_Bool OWizardMachine::travelNext() 587 { 588 // allowed to leave the current page? 589 if ( !prepareLeaveCurrentState( eTravelForward ) ) 590 return sal_False; 591 592 // determine the next state to travel to 593 WizardState nCurrentState = getCurrentState(); 594 WizardState nNextState = determineNextState(nCurrentState); 595 if (WZS_INVALID_STATE == nNextState) 596 return sal_False; 597 598 // the state history is used by the enterState method 599 // all fine 600 m_pImpl->aStateHistory.push(nCurrentState); 601 if (!ShowPage(nNextState)) 602 { 603 m_pImpl->aStateHistory.pop(); 604 return sal_False; 605 } 606 607 return sal_True; 608 } 609 610 //--------------------------------------------------------------------- travelPrevious()611 sal_Bool OWizardMachine::travelPrevious() 612 { 613 DBG_ASSERT(m_pImpl->aStateHistory.size() > 0, "OWizardMachine::travelPrevious: have no previous page!"); 614 615 // alowed to leave the current page? 616 if ( !prepareLeaveCurrentState( eTravelBackward ) ) 617 return sal_False; 618 619 // the next state to switch to 620 WizardState nPreviousState = m_pImpl->aStateHistory.top(); 621 622 // the state history is used by the enterState method 623 m_pImpl->aStateHistory.pop(); 624 // show this page 625 if (!ShowPage(nPreviousState)) 626 { 627 m_pImpl->aStateHistory.push(nPreviousState); 628 return sal_False; 629 } 630 631 // all fine 632 return sal_True; 633 } 634 635 //--------------------------------------------------------------------- removePageFromHistory(WizardState nToRemove)636 void OWizardMachine::removePageFromHistory( WizardState nToRemove ) 637 { 638 639 ::std::stack< WizardState > aTemp; 640 while(!m_pImpl->aStateHistory.empty()) 641 { 642 WizardState nPreviousState = m_pImpl->aStateHistory.top(); 643 m_pImpl->aStateHistory.pop(); 644 if(nPreviousState != nToRemove) 645 aTemp.push( nPreviousState ); 646 else 647 break; 648 } 649 while(!aTemp.empty()) 650 { 651 m_pImpl->aStateHistory.push( aTemp.top() ); 652 aTemp.pop(); 653 } 654 } 655 656 //--------------------------------------------------------------------- enableAutomaticNextButtonState(bool _bEnable)657 void OWizardMachine::enableAutomaticNextButtonState( bool _bEnable ) 658 { 659 m_pImpl->m_bAutoNextButtonState = _bEnable; 660 } 661 662 //--------------------------------------------------------------------- isAutomaticNextButtonStateEnabled() const663 bool OWizardMachine::isAutomaticNextButtonStateEnabled() const 664 { 665 return m_pImpl->m_bAutoNextButtonState; 666 } 667 668 //--------------------------------------------------------------------- IMPL_LINK(OWizardMachine,OnPrevPage,PushButton *,EMPTYARG)669 IMPL_LINK(OWizardMachine, OnPrevPage, PushButton*, EMPTYARG) 670 { 671 if ( isTravelingSuspended() ) 672 return 0; 673 WizardTravelSuspension aTravelGuard( *this ); 674 sal_Int32 nRet = travelPrevious(); 675 return nRet; 676 } 677 678 //--------------------------------------------------------------------- IMPL_LINK(OWizardMachine,OnNextPage,PushButton *,EMPTYARG)679 IMPL_LINK(OWizardMachine, OnNextPage, PushButton*, EMPTYARG) 680 { 681 if ( isTravelingSuspended() ) 682 return 0; 683 WizardTravelSuspension aTravelGuard( *this ); 684 sal_Int32 nRet = travelNext(); 685 return nRet; 686 } 687 688 //--------------------------------------------------------------------- getPageController(TabPage * _pCurrentPage) const689 IWizardPageController* OWizardMachine::getPageController( TabPage* _pCurrentPage ) const 690 { 691 IWizardPageController* pController = dynamic_cast< IWizardPageController* >( _pCurrentPage ); 692 return pController; 693 } 694 695 //--------------------------------------------------------------------- getStateHistory(::std::vector<WizardState> & _out_rHistory)696 void OWizardMachine::getStateHistory( ::std::vector< WizardState >& _out_rHistory ) 697 { 698 ::std::stack< WizardState > aHistoryCopy( m_pImpl->aStateHistory ); 699 while ( !aHistoryCopy.empty() ) 700 { 701 _out_rHistory.push_back( aHistoryCopy.top() ); 702 aHistoryCopy.pop(); 703 } 704 } 705 706 //--------------------------------------------------------------------- canAdvance() const707 bool OWizardMachine::canAdvance() const 708 { 709 return WZS_INVALID_STATE != determineNextState( getCurrentState() ); 710 } 711 712 //--------------------------------------------------------------------- updateTravelUI()713 void OWizardMachine::updateTravelUI() 714 { 715 const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) ); 716 OSL_ENSURE( pController != NULL, "RoadmapWizard::updateTravelUI: no controller for the current page!" ); 717 718 bool bCanAdvance = 719 ( !pController || pController->canAdvance() ) // the current page allows to advance 720 && canAdvance(); // the dialog as a whole allows to advance 721 enableButtons( WZB_NEXT, bCanAdvance ); 722 } 723 724 //--------------------------------------------------------------------- isTravelingSuspended() const725 bool OWizardMachine::isTravelingSuspended() const 726 { 727 return m_pImpl->m_bTravelingSuspended; 728 } 729 730 //--------------------------------------------------------------------- suspendTraveling(AccessGuard)731 void OWizardMachine::suspendTraveling( AccessGuard ) 732 { 733 DBG_ASSERT( !m_pImpl->m_bTravelingSuspended, "OWizardMachine::suspendTraveling: already suspended!" ); 734 m_pImpl->m_bTravelingSuspended = true; 735 } 736 737 //--------------------------------------------------------------------- resumeTraveling(AccessGuard)738 void OWizardMachine::resumeTraveling( AccessGuard ) 739 { 740 DBG_ASSERT( m_pImpl->m_bTravelingSuspended, "OWizardMachine::resumeTraveling: nothing to resume!" ); 741 m_pImpl->m_bTravelingSuspended = false; 742 } 743 744 //......................................................................... 745 } // namespace svt 746 //......................................................................... 747