1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svtools.hxx" 30 31 #include <svtools/roadmapwizard.hxx> 32 #include <svtools/svtools.hrc> 33 #include <svtools/svtdata.hxx> 34 #include <svtools/roadmap.hxx> 35 #include <tools/debug.hxx> 36 37 #include <stdarg.h> 38 39 #include <vector> 40 #include <map> 41 #include <set> 42 43 //........................................................................ 44 namespace svt 45 { 46 //........................................................................ 47 48 namespace 49 { 50 typedef ::std::set< WizardTypes::WizardState > StateSet; 51 52 typedef ::std::map< 53 RoadmapWizardTypes::PathId, 54 RoadmapWizardTypes::WizardPath 55 > Paths; 56 57 typedef ::std::map< 58 WizardTypes::WizardState, 59 ::std::pair< 60 String, 61 RoadmapWizardTypes::RoadmapPageFactory 62 > 63 > StateDescriptions; 64 } 65 66 struct RoadmapWizardImpl : public RoadmapWizardTypes 67 { 68 ORoadmap* pRoadmap; 69 Paths aPaths; 70 PathId nActivePath; 71 StateDescriptions aStateDescriptors; 72 StateSet aDisabledStates; 73 bool bActivePathIsDefinite; 74 FixedLine* pFixedLine; 75 76 RoadmapWizardImpl() 77 :pRoadmap( NULL ) 78 ,nActivePath( -1 ) 79 ,bActivePathIsDefinite( false ) 80 ,pFixedLine(NULL) 81 { 82 } 83 84 ~RoadmapWizardImpl() 85 { 86 delete pRoadmap; 87 delete pFixedLine; 88 } 89 90 /// returns the index of the current state in given path, or -1 91 sal_Int32 getStateIndexInPath( WizardTypes::WizardState _nState, const WizardPath& _rPath ); 92 /// returns the index of the current state in the path with the given id, or -1 93 sal_Int32 getStateIndexInPath( WizardTypes::WizardState _nState, PathId _nPathId ); 94 /// returns the index of the first state in which the two given paths differ 95 sal_Int32 getFirstDifferentIndex( const WizardPath& _rLHS, const WizardPath& _rRHS ); 96 }; 97 98 //-------------------------------------------------------------------- 99 sal_Int32 RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState, const WizardPath& _rPath ) 100 { 101 sal_Int32 nStateIndexInPath = 0; 102 WizardPath::const_iterator aPathLoop = _rPath.begin(); 103 for ( ; aPathLoop != _rPath.end(); ++aPathLoop, ++nStateIndexInPath ) 104 if ( *aPathLoop == _nState ) 105 break; 106 if ( aPathLoop == _rPath.end() ) 107 nStateIndexInPath = -1; 108 return nStateIndexInPath; 109 } 110 111 //-------------------------------------------------------------------- 112 sal_Int32 RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState, PathId _nPathId ) 113 { 114 sal_Int32 nStateIndexInPath = -1; 115 Paths::const_iterator aPathPos = aPaths.find( _nPathId ); 116 if ( aPathPos != aPaths.end( ) ) 117 nStateIndexInPath = getStateIndexInPath( _nState, aPathPos->second ); 118 return nStateIndexInPath; 119 } 120 121 //-------------------------------------------------------------------- 122 sal_Int32 RoadmapWizardImpl::getFirstDifferentIndex( const WizardPath& _rLHS, const WizardPath& _rRHS ) 123 { 124 sal_Int32 nMinLength = ::std::min( _rLHS.size(), _rRHS.size() ); 125 for ( sal_Int32 nCheck = 0; nCheck < nMinLength; ++nCheck ) 126 { 127 if ( _rLHS[ nCheck ] != _rRHS[ nCheck ] ) 128 return nCheck; 129 } 130 return nMinLength; 131 } 132 133 //==================================================================== 134 //= RoadmapWizard 135 //==================================================================== 136 DBG_NAME( RoadmapWizard ) 137 //-------------------------------------------------------------------- 138 #if OSL_DEBUG_LEVEL > 0 139 const char* CheckInvariants( const void* pVoid ) 140 { 141 return static_cast< const RoadmapWizard* >( pVoid )->checkInvariants(); 142 } 143 144 //-------------------------------------------------------------------- 145 const sal_Char* RoadmapWizard::checkInvariants() const 146 { 147 // all paths have to start with the same state 148 WizardState nSharedFirstState = WZS_INVALID_STATE; 149 for ( Paths::const_iterator aPath = m_pImpl->aPaths.begin(); 150 aPath != m_pImpl->aPaths.end(); 151 ++aPath 152 ) 153 { 154 if ( aPath->second.empty() ) 155 return "RoadmapWizard::checkInvariants: paths should not be empty!"; 156 157 if ( nSharedFirstState == WZS_INVALID_STATE ) 158 // first path 159 nSharedFirstState = aPath->second[ 0 ]; 160 else 161 if ( nSharedFirstState != aPath->second[ 0 ] ) 162 return "RoadmapWizard::checkInvariants: alls paths must start with the same state!"; 163 } 164 165 if ( !m_pImpl->aPaths.empty() ) 166 { 167 Paths::const_iterator aCurrentPathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath ); 168 if ( aCurrentPathPos == m_pImpl->aPaths.end() ) 169 return "RoadmapWizard::checkInvariants: invalid active path!"; 170 171 if ( -1 == m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath ) ) 172 return "RoadmapWizard::checkInvariants: the current state is not part of the current path!"; 173 } 174 175 return NULL; 176 } 177 #endif 178 179 //-------------------------------------------------------------------- 180 RoadmapWizard::RoadmapWizard( Window* _pParent, const ResId& _rRes, sal_uInt32 _nButtonFlags ) 181 :OWizardMachine( _pParent, _rRes, _nButtonFlags ) 182 ,m_pImpl( new RoadmapWizardImpl ) 183 { 184 DBG_CTOR( RoadmapWizard, CheckInvariants ); 185 impl_construct(); 186 } 187 188 //-------------------------------------------------------------------- 189 RoadmapWizard::RoadmapWizard( Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags ) 190 :OWizardMachine( _pParent, i_nStyle, _nButtonFlags ) 191 ,m_pImpl( new RoadmapWizardImpl ) 192 { 193 DBG_CTOR( RoadmapWizard, CheckInvariants ); 194 impl_construct(); 195 } 196 197 //-------------------------------------------------------------------- 198 void RoadmapWizard::impl_construct() 199 { 200 SetLeftAlignedButtonCount( 1 ); 201 SetEmptyViewMargin(); 202 203 m_pImpl->pRoadmap = new ORoadmap( this, WB_TABSTOP ); 204 m_pImpl->pRoadmap->SetText( SvtResId( STR_WIZDLG_ROADMAP_TITLE ) ); 205 m_pImpl->pRoadmap->SetPosPixel( Point( 0, 0 ) ); 206 m_pImpl->pRoadmap->SetItemSelectHdl( LINK( this, RoadmapWizard, OnRoadmapItemSelected ) ); 207 208 Size aRoadmapSize =( LogicToPixel( Size( 85, 0 ), MAP_APPFONT ) ); 209 aRoadmapSize.Height() = GetSizePixel().Height(); 210 m_pImpl->pRoadmap->SetSizePixel( aRoadmapSize ); 211 212 m_pImpl->pFixedLine = new FixedLine( this, WB_VERT ); 213 m_pImpl->pFixedLine->Show(); 214 m_pImpl->pFixedLine->SetPosPixel( Point( aRoadmapSize.Width() + 1, 0 ) ); 215 m_pImpl->pFixedLine->SetSizePixel( Size( LogicToPixel( Size( 2, 0 ) ).Width(), aRoadmapSize.Height() ) ); 216 217 SetViewWindow( m_pImpl->pRoadmap ); 218 SetViewAlign( WINDOWALIGN_LEFT ); 219 m_pImpl->pRoadmap->Show(); 220 } 221 222 //-------------------------------------------------------------------- 223 RoadmapWizard::~RoadmapWizard() 224 { 225 delete m_pImpl; 226 DBG_DTOR( RoadmapWizard, CheckInvariants ); 227 } 228 229 //-------------------------------------------------------------------- 230 void RoadmapWizard::SetRoadmapBitmap( const BitmapEx& _rBitmap ) 231 { 232 m_pImpl->pRoadmap->SetRoadmapBitmap( _rBitmap ); 233 } 234 235 //-------------------------------------------------------------------- 236 const BitmapEx& RoadmapWizard::GetRoadmapBitmap( ) const 237 { 238 return m_pImpl->pRoadmap->GetRoadmapBitmap(); 239 } 240 241 //-------------------------------------------------------------------- 242 void RoadmapWizard::SetRoadmapHelpId( const rtl::OString& _rId ) 243 { 244 m_pImpl->pRoadmap->SetHelpId( _rId ); 245 } 246 247 //-------------------------------------------------------------------- 248 const rtl::OString& RoadmapWizard::GetRoadmapHelpId() const 249 { 250 return m_pImpl->pRoadmap->GetHelpId(); 251 } 252 253 //-------------------------------------------------------------------- 254 void RoadmapWizard::SetRoadmapInteractive( sal_Bool _bInteractive ) 255 { 256 m_pImpl->pRoadmap->SetRoadmapInteractive( _bInteractive ); 257 } 258 259 //-------------------------------------------------------------------- 260 sal_Bool RoadmapWizard::IsRoadmapInteractive() 261 { 262 return m_pImpl->pRoadmap->IsRoadmapInteractive(); 263 } 264 265 //-------------------------------------------------------------------- 266 void RoadmapWizard::declarePath( PathId _nPathId, const WizardPath& _lWizardStates) 267 { 268 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 269 270 m_pImpl->aPaths.insert( Paths::value_type( _nPathId, _lWizardStates ) ); 271 272 if ( m_pImpl->aPaths.size() == 1 ) 273 // the very first path -> activate it 274 activatePath( _nPathId, false ); 275 else 276 implUpdateRoadmap( ); 277 } 278 279 //-------------------------------------------------------------------- 280 void RoadmapWizard::declarePath( PathId _nPathId, WizardState _nFirstState, ... ) 281 { 282 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 283 284 DBG_ASSERT( _nFirstState != WZS_INVALID_STATE, "RoadmapWizard::declarePath: there should be at least one state in the path!" ); 285 if ( _nFirstState == WZS_INVALID_STATE ) 286 return; 287 288 WizardPath aNewPath; 289 290 // collect the elements of the path 291 va_list aStateList; 292 va_start( aStateList, _nFirstState ); 293 294 WizardState nState = _nFirstState; 295 while ( nState != WZS_INVALID_STATE ) 296 { 297 aNewPath.push_back( nState ); 298 nState = sal::static_int_cast< WizardState >( 299 va_arg( aStateList, int )); 300 } 301 va_end( aStateList ); 302 303 DBG_ASSERT( _nFirstState == 0, "RoadmapWizard::declarePath: first state must be NULL." ); 304 // The WizardDialog (our very base class) always starts with a mnCurLevel == 0 305 306 declarePath( _nPathId, aNewPath ); 307 } 308 309 //-------------------------------------------------------------------- 310 void RoadmapWizard::describeState( WizardState _nState, const String& _rStateDisplayName, RoadmapPageFactory _pPageFactory ) 311 { 312 OSL_ENSURE( m_pImpl->aStateDescriptors.find( _nState ) == m_pImpl->aStateDescriptors.end(), 313 "RoadmapWizard::describeState: there already is a descriptor for this state!" ); 314 m_pImpl->aStateDescriptors[ _nState ] = StateDescriptions::mapped_type( _rStateDisplayName, _pPageFactory ); 315 } 316 317 //-------------------------------------------------------------------- 318 void RoadmapWizard::activatePath( PathId _nPathId, bool _bDecideForIt ) 319 { 320 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 321 322 if ( ( _nPathId == m_pImpl->nActivePath ) && ( _bDecideForIt == m_pImpl->bActivePathIsDefinite ) ) 323 // nothing to do 324 return; 325 326 // does the given path exist? 327 Paths::const_iterator aNewPathPos = m_pImpl->aPaths.find( _nPathId ); 328 DBG_ASSERT( aNewPathPos != m_pImpl->aPaths.end(), "RoadmapWizard::activate: there is no such path!" ); 329 if ( aNewPathPos == m_pImpl->aPaths.end() ) 330 return; 331 332 // determine the index of the current state in the current path 333 sal_Int32 nCurrentStatePathIndex = -1; 334 if ( m_pImpl->nActivePath != -1 ) 335 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath ); 336 337 DBG_ASSERT( (sal_Int32)aNewPathPos->second.size() > nCurrentStatePathIndex, 338 "RoadmapWizard::activate: you cannot activate a path which has less states than we've already advanced!" ); 339 // If this asserts, this for instance means that we are already in state number, say, 5 340 // of our current path, and the caller tries to activate a path which has less than 5 341 // states 342 if ( (sal_Int32)aNewPathPos->second.size() <= nCurrentStatePathIndex ) 343 return; 344 345 // assert that the current and the new path are equal, up to nCurrentStatePathIndex 346 Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath ); 347 if ( aActivePathPos != m_pImpl->aPaths.end() ) 348 { 349 if ( m_pImpl->getFirstDifferentIndex( aActivePathPos->second, aNewPathPos->second ) <= nCurrentStatePathIndex ) 350 { 351 OSL_ENSURE( false, "RoadmapWizard::activate: you cannot activate a path which conflicts with the current one *before* the current state!" ); 352 return; 353 } 354 } 355 356 m_pImpl->nActivePath = _nPathId; 357 m_pImpl->bActivePathIsDefinite = _bDecideForIt; 358 359 implUpdateRoadmap( ); 360 } 361 362 //-------------------------------------------------------------------- 363 void RoadmapWizard::implUpdateRoadmap( ) 364 { 365 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 366 367 DBG_ASSERT( m_pImpl->aPaths.find( m_pImpl->nActivePath ) != m_pImpl->aPaths.end(), 368 "RoadmapWizard::implUpdateRoadmap: there is no such path!" ); 369 const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] ); 370 371 sal_Int32 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), rActivePath ); 372 373 // determine up to which index (in the new path) we have to display the items 374 RoadmapTypes::ItemIndex nUpperStepBoundary = (RoadmapTypes::ItemIndex)rActivePath.size(); 375 sal_Bool bIncompletePath = sal_False; 376 if ( !m_pImpl->bActivePathIsDefinite ) 377 { 378 for ( Paths::const_iterator aPathPos = m_pImpl->aPaths.begin(); 379 aPathPos != m_pImpl->aPaths.end(); 380 ++aPathPos 381 ) 382 { 383 if ( aPathPos->first == m_pImpl->nActivePath ) 384 // it's the path we are just activating -> no need to check anything 385 continue; 386 // the index from which on both paths differ 387 sal_Int32 nDivergenceIndex = m_pImpl->getFirstDifferentIndex( rActivePath, aPathPos->second ); 388 if ( nDivergenceIndex <= nCurrentStatePathIndex ) 389 // they differ in an index which we have already left behind us 390 // -> this is no conflict anymore 391 continue; 392 393 // the path conflicts with our new path -> don't activate the 394 // *complete* new path, but only up to the step which is unambiguous 395 nUpperStepBoundary = nDivergenceIndex; 396 bIncompletePath = sal_True; 397 } 398 } 399 400 // can we advance from the current page? 401 bool bCurrentPageCanAdvance = true; 402 TabPage* pCurrentPage = GetPage( getCurrentState() ); 403 if ( pCurrentPage ) 404 { 405 const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) ); 406 OSL_ENSURE( pController != NULL, "RoadmapWizard::implUpdateRoadmap: no controller for the current page!" ); 407 bCurrentPageCanAdvance = !pController || pController->canAdvance(); 408 } 409 410 // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active 411 // path, up to (excluding) nUpperStepBoundary 412 RoadmapTypes::ItemIndex nLoopUntil = ::std::max( (RoadmapTypes::ItemIndex)nUpperStepBoundary, m_pImpl->pRoadmap->GetItemCount() ); 413 for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex ) 414 { 415 bool bExistentItem = ( nItemIndex < m_pImpl->pRoadmap->GetItemCount() ); 416 bool bNeedItem = ( nItemIndex < nUpperStepBoundary ); 417 418 bool bInsertItem = false; 419 if ( bExistentItem ) 420 { 421 if ( !bNeedItem ) 422 { 423 while ( nItemIndex < m_pImpl->pRoadmap->GetItemCount() ) 424 m_pImpl->pRoadmap->DeleteRoadmapItem( nItemIndex ); 425 break; 426 } 427 else 428 { 429 // there is an item with this index in the roadmap - does it match what is requested by 430 // the respective state in the active path? 431 RoadmapTypes::ItemId nPresentItemId = m_pImpl->pRoadmap->GetItemID( nItemIndex ); 432 WizardState nRequiredState = rActivePath[ nItemIndex ]; 433 if ( nPresentItemId != nRequiredState ) 434 { 435 m_pImpl->pRoadmap->DeleteRoadmapItem( nItemIndex ); 436 bInsertItem = true; 437 } 438 } 439 } 440 else 441 { 442 DBG_ASSERT( bNeedItem, "RoadmapWizard::implUpdateRoadmap: ehm - none needed, none present - why did the loop not terminate?" ); 443 bInsertItem = bNeedItem; 444 } 445 446 WizardState nState( rActivePath[ nItemIndex ] ); 447 if ( bInsertItem ) 448 { 449 m_pImpl->pRoadmap->InsertRoadmapItem( 450 nItemIndex, 451 getStateDisplayName( nState ), 452 nState 453 ); 454 } 455 456 // if the item is *after* the current state, but the current page does not 457 // allow advancing, the disable the state. This relieves derived classes 458 // from disabling all future states just because the current state does not 459 // (yet) allow advancing. 460 const bool nUnconditionedDisable = !bCurrentPageCanAdvance && ( nItemIndex > nCurrentStatePathIndex ); 461 const bool bEnable = !nUnconditionedDisable && ( m_pImpl->aDisabledStates.find( nState ) == m_pImpl->aDisabledStates.end() ); 462 463 m_pImpl->pRoadmap->EnableRoadmapItem( m_pImpl->pRoadmap->GetItemID( nItemIndex ), bEnable ); 464 } 465 466 m_pImpl->pRoadmap->SetRoadmapComplete( !bIncompletePath ); 467 } 468 469 //-------------------------------------------------------------------- 470 WizardTypes::WizardState RoadmapWizard::determineNextState( WizardState _nCurrentState ) const 471 { 472 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 473 474 sal_Int32 nCurrentStatePathIndex = -1; 475 476 Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath ); 477 if ( aActivePathPos != m_pImpl->aPaths.end() ) 478 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( _nCurrentState, aActivePathPos->second ); 479 480 DBG_ASSERT( nCurrentStatePathIndex != -1, "RoadmapWizard::determineNextState: ehm - how can we travel if there is no (valid) active path?" ); 481 if ( nCurrentStatePathIndex == -1 ) 482 return WZS_INVALID_STATE; 483 484 sal_Int32 nNextStateIndex = nCurrentStatePathIndex + 1; 485 486 while ( ( nNextStateIndex < (sal_Int32)aActivePathPos->second.size() ) 487 && ( m_pImpl->aDisabledStates.find( aActivePathPos->second[ nNextStateIndex ] ) != m_pImpl->aDisabledStates.end() ) 488 ) 489 { 490 ++nNextStateIndex; 491 } 492 493 if ( nNextStateIndex >= (sal_Int32)aActivePathPos->second.size() ) 494 // there is no next state in the current path (at least none which is enabled) 495 return WZS_INVALID_STATE; 496 497 return aActivePathPos->second[ nNextStateIndex ]; 498 } 499 500 //--------------------------------------------------------------------- 501 bool RoadmapWizard::canAdvance() const 502 { 503 if ( !m_pImpl->bActivePathIsDefinite ) 504 { 505 // check how many paths are still allowed 506 const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] ); 507 sal_Int32 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), rActivePath ); 508 509 size_t nPossiblePaths(0); 510 for ( Paths::const_iterator aPathPos = m_pImpl->aPaths.begin(); 511 aPathPos != m_pImpl->aPaths.end(); 512 ++aPathPos 513 ) 514 { 515 // the index from which on both paths differ 516 sal_Int32 nDivergenceIndex = m_pImpl->getFirstDifferentIndex( rActivePath, aPathPos->second ); 517 518 if ( nDivergenceIndex > nCurrentStatePathIndex ) 519 // this path is still a possible path 520 nPossiblePaths += 1; 521 } 522 523 // if we have more than one path which is still possible, then we assume 524 // to always have a next state. Though there might be scenarios where this 525 // is not true, but this is too sophisticated (means not really needed) right now. 526 if ( nPossiblePaths > 1 ) 527 return true; 528 } 529 530 const WizardPath& rPath = m_pImpl->aPaths[ m_pImpl->nActivePath ]; 531 if ( *rPath.rbegin() == getCurrentState() ) 532 return false; 533 534 return true; 535 } 536 537 //--------------------------------------------------------------------- 538 void RoadmapWizard::updateTravelUI() 539 { 540 OWizardMachine::updateTravelUI(); 541 542 // disable the "Previous" button if all states in our history are disabled 543 ::std::vector< WizardState > aHistory; 544 getStateHistory( aHistory ); 545 bool bHaveEnabledState = false; 546 for ( ::std::vector< WizardState >::const_iterator state = aHistory.begin(); 547 state != aHistory.end() && !bHaveEnabledState; 548 ++state 549 ) 550 { 551 if ( isStateEnabled( *state ) ) 552 bHaveEnabledState = true; 553 } 554 555 enableButtons( WZB_PREVIOUS, bHaveEnabledState ); 556 557 implUpdateRoadmap(); 558 } 559 560 //-------------------------------------------------------------------- 561 IMPL_LINK( RoadmapWizard, OnRoadmapItemSelected, void*, EMPTYARG ) 562 { 563 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 564 565 RoadmapTypes::ItemId nCurItemId = m_pImpl->pRoadmap->GetCurrentRoadmapItemID(); 566 if ( nCurItemId == getCurrentState() ) 567 // nothing to do 568 return 1L; 569 570 if ( isTravelingSuspended() ) 571 return 0; 572 573 WizardTravelSuspension aTravelGuard( *this ); 574 575 sal_Int32 nCurrentIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath ); 576 sal_Int32 nNewIndex = m_pImpl->getStateIndexInPath( nCurItemId, m_pImpl->nActivePath ); 577 578 DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ), 579 "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" ); 580 if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) ) 581 { 582 return 0L; 583 } 584 585 sal_Bool bResult = sal_True; 586 if ( nNewIndex > nCurrentIndex ) 587 { 588 bResult = skipUntil( (WizardState)nCurItemId ); 589 WizardState nTemp = (WizardState)nCurItemId; 590 while( nTemp ) 591 { 592 if( m_pImpl->aDisabledStates.find( --nTemp ) != m_pImpl->aDisabledStates.end() ) 593 removePageFromHistory( nTemp ); 594 } 595 } 596 else 597 bResult = skipBackwardUntil( (WizardState)nCurItemId ); 598 599 if ( !bResult ) 600 m_pImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() ); 601 602 return 1L; 603 } 604 605 //-------------------------------------------------------------------- 606 void RoadmapWizard::enterState( WizardState _nState ) 607 { 608 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 609 610 OWizardMachine::enterState( _nState ); 611 612 // synchronize the roadmap 613 implUpdateRoadmap( ); 614 m_pImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() ); 615 } 616 617 //-------------------------------------------------------------------- 618 String RoadmapWizard::getStateDisplayName( WizardState _nState ) const 619 { 620 String sDisplayName; 621 622 StateDescriptions::const_iterator pos = m_pImpl->aStateDescriptors.find( _nState ); 623 OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(), 624 "RoadmapWizard::getStateDisplayName: no default implementation available for this state!" ); 625 if ( pos != m_pImpl->aStateDescriptors.end() ) 626 sDisplayName = pos->second.first; 627 628 return sDisplayName; 629 } 630 631 //-------------------------------------------------------------------- 632 TabPage* RoadmapWizard::createPage( WizardState _nState ) 633 { 634 TabPage* pPage( NULL ); 635 636 StateDescriptions::const_iterator pos = m_pImpl->aStateDescriptors.find( _nState ); 637 OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(), 638 "RoadmapWizard::createPage: no default implementation available for this state!" ); 639 if ( pos != m_pImpl->aStateDescriptors.end() ) 640 { 641 RoadmapPageFactory pFactory = pos->second.second; 642 pPage = (*pFactory)( *this ); 643 } 644 645 return pPage; 646 } 647 648 //-------------------------------------------------------------------- 649 void RoadmapWizard::enableState( WizardState _nState, bool _bEnable ) 650 { 651 DBG_CHKTHIS( RoadmapWizard, CheckInvariants ); 652 653 // remember this (in case the state appears in the roadmap later on) 654 if ( _bEnable ) 655 m_pImpl->aDisabledStates.erase( _nState ); 656 else 657 { 658 m_pImpl->aDisabledStates.insert( _nState ); 659 removePageFromHistory( _nState ); 660 } 661 662 // if the state is currently in the roadmap, reflect it's new status 663 m_pImpl->pRoadmap->EnableRoadmapItem( (RoadmapTypes::ItemId)_nState, _bEnable ); 664 } 665 666 //-------------------------------------------------------------------- 667 bool RoadmapWizard::knowsState( WizardState i_nState ) const 668 { 669 for ( Paths::const_iterator path = m_pImpl->aPaths.begin(); 670 path != m_pImpl->aPaths.end(); 671 ++path 672 ) 673 { 674 for ( WizardPath::const_iterator state = path->second.begin(); 675 state != path->second.end(); 676 ++state 677 ) 678 { 679 if ( *state == i_nState ) 680 return true; 681 } 682 } 683 return false; 684 } 685 686 //-------------------------------------------------------------------- 687 bool RoadmapWizard::isStateEnabled( WizardState _nState ) const 688 { 689 return m_pImpl->aDisabledStates.find( _nState ) == m_pImpl->aDisabledStates.end(); 690 } 691 692 //-------------------------------------------------------------------- 693 void RoadmapWizard::Resize() 694 { 695 OWizardMachine::Resize(); 696 697 if ( IsReallyShown() && !IsInInitShow() ) 698 ResizeFixedLine(); 699 } 700 701 702 //-------------------------------------------------------------------- 703 void RoadmapWizard::StateChanged( StateChangedType nType ) 704 { 705 WizardDialog::StateChanged( nType ); 706 707 if ( nType == STATE_CHANGE_INITSHOW ) 708 ResizeFixedLine(); 709 } 710 711 //-------------------------------------------------------------------- 712 void RoadmapWizard::ResizeFixedLine() 713 { 714 Size aSize( m_pImpl->pRoadmap->GetSizePixel() ); 715 aSize.Width() = m_pImpl->pFixedLine->GetSizePixel().Width(); 716 m_pImpl->pFixedLine->SetSizePixel( aSize ); 717 } 718 719 //-------------------------------------------------------------------- 720 void RoadmapWizard::updateRoadmapItemLabel( WizardState _nState ) 721 { 722 const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] ); 723 RoadmapTypes::ItemIndex nUpperStepBoundary = (RoadmapTypes::ItemIndex)rActivePath.size(); 724 RoadmapTypes::ItemIndex nLoopUntil = ::std::max( (RoadmapTypes::ItemIndex)nUpperStepBoundary, m_pImpl->pRoadmap->GetItemCount() ); 725 sal_Int32 nCurrentStatePathIndex = -1; 726 if ( m_pImpl->nActivePath != -1 ) 727 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath ); 728 for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex ) 729 { 730 bool bExistentItem = ( nItemIndex < m_pImpl->pRoadmap->GetItemCount() ); 731 if ( bExistentItem ) 732 { 733 // there is an item with this index in the roadmap - does it match what is requested by 734 // the respective state in the active path? 735 RoadmapTypes::ItemId nPresentItemId = m_pImpl->pRoadmap->GetItemID( nItemIndex ); 736 WizardState nRequiredState = rActivePath[ nItemIndex ]; 737 if ( _nState == nRequiredState ) 738 { 739 m_pImpl->pRoadmap->ChangeRoadmapItemLabel( nPresentItemId, getStateDisplayName( nRequiredState ) ); 740 break; 741 } 742 } 743 } 744 } 745 746 //........................................................................ 747 } // namespace svt 748 //........................................................................ 749