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