summaryrefslogtreecommitdiff
path: root/svtools/source/dialogs/roadmapwizard.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/dialogs/roadmapwizard.cxx')
-rw-r--r--svtools/source/dialogs/roadmapwizard.cxx748
1 files changed, 748 insertions, 0 deletions
diff --git a/svtools/source/dialogs/roadmapwizard.cxx b/svtools/source/dialogs/roadmapwizard.cxx
new file mode 100644
index 000000000000..cdf2eef32fdc
--- /dev/null
+++ b/svtools/source/dialogs/roadmapwizard.cxx
@@ -0,0 +1,748 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svtools.hxx"
+
+#include <svtools/roadmapwizard.hxx>
+#include <svtools/svtools.hrc>
+#include <svtools/svtdata.hxx>
+#include <svtools/roadmap.hxx>
+#include <tools/debug.hxx>
+
+#include <stdarg.h>
+
+#include <vector>
+#include <map>
+#include <set>
+
+//........................................................................
+namespace svt
+{
+//........................................................................
+
+ namespace
+ {
+ typedef ::std::set< WizardTypes::WizardState > StateSet;
+
+ typedef ::std::map<
+ RoadmapWizardTypes::PathId,
+ RoadmapWizardTypes::WizardPath
+ > Paths;
+
+ typedef ::std::map<
+ WizardTypes::WizardState,
+ ::std::pair<
+ String,
+ RoadmapWizardTypes::RoadmapPageFactory
+ >
+ > StateDescriptions;
+ }
+
+ struct RoadmapWizardImpl : public RoadmapWizardTypes
+ {
+ ORoadmap* pRoadmap;
+ Paths aPaths;
+ PathId nActivePath;
+ StateDescriptions aStateDescriptors;
+ StateSet aDisabledStates;
+ bool bActivePathIsDefinite;
+ FixedLine* pFixedLine;
+
+ RoadmapWizardImpl()
+ :pRoadmap( NULL )
+ ,nActivePath( -1 )
+ ,bActivePathIsDefinite( false )
+ ,pFixedLine(NULL)
+ {
+ }
+
+ ~RoadmapWizardImpl()
+ {
+ delete pRoadmap;
+ delete pFixedLine;
+ }
+
+ /// returns the index of the current state in given path, or -1
+ sal_Int32 getStateIndexInPath( WizardTypes::WizardState _nState, const WizardPath& _rPath );
+ /// returns the index of the current state in the path with the given id, or -1
+ sal_Int32 getStateIndexInPath( WizardTypes::WizardState _nState, PathId _nPathId );
+ /// returns the index of the first state in which the two given paths differ
+ sal_Int32 getFirstDifferentIndex( const WizardPath& _rLHS, const WizardPath& _rRHS );
+ };
+
+ //--------------------------------------------------------------------
+ sal_Int32 RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState, const WizardPath& _rPath )
+ {
+ sal_Int32 nStateIndexInPath = 0;
+ WizardPath::const_iterator aPathLoop = _rPath.begin();
+ for ( ; aPathLoop != _rPath.end(); ++aPathLoop, ++nStateIndexInPath )
+ if ( *aPathLoop == _nState )
+ break;
+ if ( aPathLoop == _rPath.end() )
+ nStateIndexInPath = -1;
+ return nStateIndexInPath;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int32 RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState, PathId _nPathId )
+ {
+ sal_Int32 nStateIndexInPath = -1;
+ Paths::const_iterator aPathPos = aPaths.find( _nPathId );
+ if ( aPathPos != aPaths.end( ) )
+ nStateIndexInPath = getStateIndexInPath( _nState, aPathPos->second );
+ return nStateIndexInPath;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int32 RoadmapWizardImpl::getFirstDifferentIndex( const WizardPath& _rLHS, const WizardPath& _rRHS )
+ {
+ sal_Int32 nMinLength = ::std::min( _rLHS.size(), _rRHS.size() );
+ for ( sal_Int32 nCheck = 0; nCheck < nMinLength; ++nCheck )
+ {
+ if ( _rLHS[ nCheck ] != _rRHS[ nCheck ] )
+ return nCheck;
+ }
+ return nMinLength;
+ }
+
+ //====================================================================
+ //= RoadmapWizard
+ //====================================================================
+ DBG_NAME( RoadmapWizard )
+ //--------------------------------------------------------------------
+#if OSL_DEBUG_LEVEL > 0
+ const char* CheckInvariants( const void* pVoid )
+ {
+ return static_cast< const RoadmapWizard* >( pVoid )->checkInvariants();
+ }
+
+ //--------------------------------------------------------------------
+ const sal_Char* RoadmapWizard::checkInvariants() const
+ {
+ // all paths have to start with the same state
+ WizardState nSharedFirstState = WZS_INVALID_STATE;
+ for ( Paths::const_iterator aPath = m_pImpl->aPaths.begin();
+ aPath != m_pImpl->aPaths.end();
+ ++aPath
+ )
+ {
+ if ( aPath->second.empty() )
+ return "RoadmapWizard::checkInvariants: paths should not be empty!";
+
+ if ( nSharedFirstState == WZS_INVALID_STATE )
+ // first path
+ nSharedFirstState = aPath->second[ 0 ];
+ else
+ if ( nSharedFirstState != aPath->second[ 0 ] )
+ return "RoadmapWizard::checkInvariants: alls paths must start with the same state!";
+ }
+
+ if ( !m_pImpl->aPaths.empty() )
+ {
+ Paths::const_iterator aCurrentPathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath );
+ if ( aCurrentPathPos == m_pImpl->aPaths.end() )
+ return "RoadmapWizard::checkInvariants: invalid active path!";
+
+ if ( -1 == m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath ) )
+ return "RoadmapWizard::checkInvariants: the current state is not part of the current path!";
+ }
+
+ return NULL;
+ }
+#endif
+
+ //--------------------------------------------------------------------
+ RoadmapWizard::RoadmapWizard( Window* _pParent, const ResId& _rRes, sal_uInt32 _nButtonFlags )
+ :OWizardMachine( _pParent, _rRes, _nButtonFlags )
+ ,m_pImpl( new RoadmapWizardImpl )
+ {
+ DBG_CTOR( RoadmapWizard, CheckInvariants );
+ impl_construct();
+ }
+
+ //--------------------------------------------------------------------
+ RoadmapWizard::RoadmapWizard( Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags )
+ :OWizardMachine( _pParent, i_nStyle, _nButtonFlags )
+ ,m_pImpl( new RoadmapWizardImpl )
+ {
+ DBG_CTOR( RoadmapWizard, CheckInvariants );
+ impl_construct();
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::impl_construct()
+ {
+ SetLeftAlignedButtonCount( 1 );
+ SetEmptyViewMargin();
+
+ m_pImpl->pRoadmap = new ORoadmap( this, WB_TABSTOP );
+ m_pImpl->pRoadmap->SetText( SvtResId( STR_WIZDLG_ROADMAP_TITLE ) );
+ m_pImpl->pRoadmap->SetPosPixel( Point( 0, 0 ) );
+ m_pImpl->pRoadmap->SetItemSelectHdl( LINK( this, RoadmapWizard, OnRoadmapItemSelected ) );
+
+ Size aRoadmapSize =( LogicToPixel( Size( 85, 0 ), MAP_APPFONT ) );
+ aRoadmapSize.Height() = GetSizePixel().Height();
+ m_pImpl->pRoadmap->SetSizePixel( aRoadmapSize );
+
+ m_pImpl->pFixedLine = new FixedLine( this, WB_VERT );
+ m_pImpl->pFixedLine->Show();
+ m_pImpl->pFixedLine->SetPosPixel( Point( aRoadmapSize.Width() + 1, 0 ) );
+ m_pImpl->pFixedLine->SetSizePixel( Size( LogicToPixel( Size( 2, 0 ) ).Width(), aRoadmapSize.Height() ) );
+
+ SetViewWindow( m_pImpl->pRoadmap );
+ SetViewAlign( WINDOWALIGN_LEFT );
+ m_pImpl->pRoadmap->Show();
+ }
+
+ //--------------------------------------------------------------------
+ RoadmapWizard::~RoadmapWizard()
+ {
+ delete m_pImpl;
+ DBG_DTOR( RoadmapWizard, CheckInvariants );
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::SetRoadmapBitmap( const BitmapEx& _rBitmap )
+ {
+ m_pImpl->pRoadmap->SetRoadmapBitmap( _rBitmap );
+ }
+
+ //--------------------------------------------------------------------
+ const BitmapEx& RoadmapWizard::GetRoadmapBitmap( ) const
+ {
+ return m_pImpl->pRoadmap->GetRoadmapBitmap();
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::SetRoadmapHelpId( const rtl::OString& _rId )
+ {
+ m_pImpl->pRoadmap->SetHelpId( _rId );
+ }
+
+ //--------------------------------------------------------------------
+ const rtl::OString& RoadmapWizard::GetRoadmapHelpId() const
+ {
+ return m_pImpl->pRoadmap->GetHelpId();
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::SetRoadmapInteractive( sal_Bool _bInteractive )
+ {
+ m_pImpl->pRoadmap->SetRoadmapInteractive( _bInteractive );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool RoadmapWizard::IsRoadmapInteractive()
+ {
+ return m_pImpl->pRoadmap->IsRoadmapInteractive();
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::declarePath( PathId _nPathId, const WizardPath& _lWizardStates)
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ m_pImpl->aPaths.insert( Paths::value_type( _nPathId, _lWizardStates ) );
+
+ if ( m_pImpl->aPaths.size() == 1 )
+ // the very first path -> activate it
+ activatePath( _nPathId, false );
+ else
+ implUpdateRoadmap( );
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::declarePath( PathId _nPathId, WizardState _nFirstState, ... )
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ DBG_ASSERT( _nFirstState != WZS_INVALID_STATE, "RoadmapWizard::declarePath: there should be at least one state in the path!" );
+ if ( _nFirstState == WZS_INVALID_STATE )
+ return;
+
+ WizardPath aNewPath;
+
+ // collect the elements of the path
+ va_list aStateList;
+ va_start( aStateList, _nFirstState );
+
+ WizardState nState = _nFirstState;
+ while ( nState != WZS_INVALID_STATE )
+ {
+ aNewPath.push_back( nState );
+ nState = sal::static_int_cast< WizardState >(
+ va_arg( aStateList, int ));
+ }
+ va_end( aStateList );
+
+ DBG_ASSERT( _nFirstState == 0, "RoadmapWizard::declarePath: first state must be NULL." );
+ // The WizardDialog (our very base class) always starts with a mnCurLevel == 0
+
+ declarePath( _nPathId, aNewPath );
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::describeState( WizardState _nState, const String& _rStateDisplayName, RoadmapPageFactory _pPageFactory )
+ {
+ OSL_ENSURE( m_pImpl->aStateDescriptors.find( _nState ) == m_pImpl->aStateDescriptors.end(),
+ "RoadmapWizard::describeState: there already is a descriptor for this state!" );
+ m_pImpl->aStateDescriptors[ _nState ] = StateDescriptions::mapped_type( _rStateDisplayName, _pPageFactory );
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::activatePath( PathId _nPathId, bool _bDecideForIt )
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ if ( ( _nPathId == m_pImpl->nActivePath ) && ( _bDecideForIt == m_pImpl->bActivePathIsDefinite ) )
+ // nothing to do
+ return;
+
+ // does the given path exist?
+ Paths::const_iterator aNewPathPos = m_pImpl->aPaths.find( _nPathId );
+ DBG_ASSERT( aNewPathPos != m_pImpl->aPaths.end(), "RoadmapWizard::activate: there is no such path!" );
+ if ( aNewPathPos == m_pImpl->aPaths.end() )
+ return;
+
+ // determine the index of the current state in the current path
+ sal_Int32 nCurrentStatePathIndex = -1;
+ if ( m_pImpl->nActivePath != -1 )
+ nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath );
+
+ DBG_ASSERT( (sal_Int32)aNewPathPos->second.size() > nCurrentStatePathIndex,
+ "RoadmapWizard::activate: you cannot activate a path which has less states than we've already advanced!" );
+ // If this asserts, this for instance means that we are already in state number, say, 5
+ // of our current path, and the caller tries to activate a path which has less than 5
+ // states
+ if ( (sal_Int32)aNewPathPos->second.size() <= nCurrentStatePathIndex )
+ return;
+
+ // assert that the current and the new path are equal, up to nCurrentStatePathIndex
+ Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath );
+ if ( aActivePathPos != m_pImpl->aPaths.end() )
+ {
+ if ( m_pImpl->getFirstDifferentIndex( aActivePathPos->second, aNewPathPos->second ) <= nCurrentStatePathIndex )
+ {
+ OSL_ENSURE( false, "RoadmapWizard::activate: you cannot activate a path which conflicts with the current one *before* the current state!" );
+ return;
+ }
+ }
+
+ m_pImpl->nActivePath = _nPathId;
+ m_pImpl->bActivePathIsDefinite = _bDecideForIt;
+
+ implUpdateRoadmap( );
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::implUpdateRoadmap( )
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ DBG_ASSERT( m_pImpl->aPaths.find( m_pImpl->nActivePath ) != m_pImpl->aPaths.end(),
+ "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
+ const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
+
+ sal_Int32 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), rActivePath );
+
+ // determine up to which index (in the new path) we have to display the items
+ RoadmapTypes::ItemIndex nUpperStepBoundary = (RoadmapTypes::ItemIndex)rActivePath.size();
+ sal_Bool bIncompletePath = sal_False;
+ if ( !m_pImpl->bActivePathIsDefinite )
+ {
+ for ( Paths::const_iterator aPathPos = m_pImpl->aPaths.begin();
+ aPathPos != m_pImpl->aPaths.end();
+ ++aPathPos
+ )
+ {
+ if ( aPathPos->first == m_pImpl->nActivePath )
+ // it's the path we are just activating -> no need to check anything
+ continue;
+ // the index from which on both paths differ
+ sal_Int32 nDivergenceIndex = m_pImpl->getFirstDifferentIndex( rActivePath, aPathPos->second );
+ if ( nDivergenceIndex <= nCurrentStatePathIndex )
+ // they differ in an index which we have already left behind us
+ // -> this is no conflict anymore
+ continue;
+
+ // the path conflicts with our new path -> don't activate the
+ // *complete* new path, but only up to the step which is unambiguous
+ nUpperStepBoundary = nDivergenceIndex;
+ bIncompletePath = sal_True;
+ }
+ }
+
+ // can we advance from the current page?
+ bool bCurrentPageCanAdvance = true;
+ TabPage* pCurrentPage = GetPage( getCurrentState() );
+ if ( pCurrentPage )
+ {
+ const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
+ OSL_ENSURE( pController != NULL, "RoadmapWizard::implUpdateRoadmap: no controller for the current page!" );
+ bCurrentPageCanAdvance = !pController || pController->canAdvance();
+ }
+
+ // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active
+ // path, up to (excluding) nUpperStepBoundary
+ RoadmapTypes::ItemIndex nLoopUntil = ::std::max( (RoadmapTypes::ItemIndex)nUpperStepBoundary, m_pImpl->pRoadmap->GetItemCount() );
+ for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex )
+ {
+ bool bExistentItem = ( nItemIndex < m_pImpl->pRoadmap->GetItemCount() );
+ bool bNeedItem = ( nItemIndex < nUpperStepBoundary );
+
+ bool bInsertItem = false;
+ if ( bExistentItem )
+ {
+ if ( !bNeedItem )
+ {
+ while ( nItemIndex < m_pImpl->pRoadmap->GetItemCount() )
+ m_pImpl->pRoadmap->DeleteRoadmapItem( nItemIndex );
+ break;
+ }
+ else
+ {
+ // there is an item with this index in the roadmap - does it match what is requested by
+ // the respective state in the active path?
+ RoadmapTypes::ItemId nPresentItemId = m_pImpl->pRoadmap->GetItemID( nItemIndex );
+ WizardState nRequiredState = rActivePath[ nItemIndex ];
+ if ( nPresentItemId != nRequiredState )
+ {
+ m_pImpl->pRoadmap->DeleteRoadmapItem( nItemIndex );
+ bInsertItem = true;
+ }
+ }
+ }
+ else
+ {
+ DBG_ASSERT( bNeedItem, "RoadmapWizard::implUpdateRoadmap: ehm - none needed, none present - why did the loop not terminate?" );
+ bInsertItem = bNeedItem;
+ }
+
+ WizardState nState( rActivePath[ nItemIndex ] );
+ if ( bInsertItem )
+ {
+ m_pImpl->pRoadmap->InsertRoadmapItem(
+ nItemIndex,
+ getStateDisplayName( nState ),
+ nState
+ );
+ }
+
+ // if the item is *after* the current state, but the current page does not
+ // allow advancing, the disable the state. This relieves derived classes
+ // from disabling all future states just because the current state does not
+ // (yet) allow advancing.
+ const bool nUnconditionedDisable = !bCurrentPageCanAdvance && ( nItemIndex > nCurrentStatePathIndex );
+ const bool bEnable = !nUnconditionedDisable && ( m_pImpl->aDisabledStates.find( nState ) == m_pImpl->aDisabledStates.end() );
+
+ m_pImpl->pRoadmap->EnableRoadmapItem( m_pImpl->pRoadmap->GetItemID( nItemIndex ), bEnable );
+ }
+
+ m_pImpl->pRoadmap->SetRoadmapComplete( !bIncompletePath );
+ }
+
+ //--------------------------------------------------------------------
+ WizardTypes::WizardState RoadmapWizard::determineNextState( WizardState _nCurrentState ) const
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ sal_Int32 nCurrentStatePathIndex = -1;
+
+ Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath );
+ if ( aActivePathPos != m_pImpl->aPaths.end() )
+ nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( _nCurrentState, aActivePathPos->second );
+
+ DBG_ASSERT( nCurrentStatePathIndex != -1, "RoadmapWizard::determineNextState: ehm - how can we travel if there is no (valid) active path?" );
+ if ( nCurrentStatePathIndex == -1 )
+ return WZS_INVALID_STATE;
+
+ sal_Int32 nNextStateIndex = nCurrentStatePathIndex + 1;
+
+ while ( ( nNextStateIndex < (sal_Int32)aActivePathPos->second.size() )
+ && ( m_pImpl->aDisabledStates.find( aActivePathPos->second[ nNextStateIndex ] ) != m_pImpl->aDisabledStates.end() )
+ )
+ {
+ ++nNextStateIndex;
+ }
+
+ if ( nNextStateIndex >= (sal_Int32)aActivePathPos->second.size() )
+ // there is no next state in the current path (at least none which is enabled)
+ return WZS_INVALID_STATE;
+
+ return aActivePathPos->second[ nNextStateIndex ];
+ }
+
+ //---------------------------------------------------------------------
+ bool RoadmapWizard::canAdvance() const
+ {
+ if ( !m_pImpl->bActivePathIsDefinite )
+ {
+ // check how many paths are still allowed
+ const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
+ sal_Int32 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), rActivePath );
+
+ size_t nPossiblePaths(0);
+ for ( Paths::const_iterator aPathPos = m_pImpl->aPaths.begin();
+ aPathPos != m_pImpl->aPaths.end();
+ ++aPathPos
+ )
+ {
+ // the index from which on both paths differ
+ sal_Int32 nDivergenceIndex = m_pImpl->getFirstDifferentIndex( rActivePath, aPathPos->second );
+
+ if ( nDivergenceIndex > nCurrentStatePathIndex )
+ // this path is still a possible path
+ nPossiblePaths += 1;
+ }
+
+ // if we have more than one path which is still possible, then we assume
+ // to always have a next state. Though there might be scenarios where this
+ // is not true, but this is too sophisticated (means not really needed) right now.
+ if ( nPossiblePaths > 1 )
+ return true;
+ }
+
+ const WizardPath& rPath = m_pImpl->aPaths[ m_pImpl->nActivePath ];
+ if ( *rPath.rbegin() == getCurrentState() )
+ return false;
+
+ return true;
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapWizard::updateTravelUI()
+ {
+ OWizardMachine::updateTravelUI();
+
+ // disable the "Previous" button if all states in our history are disabled
+ ::std::vector< WizardState > aHistory;
+ getStateHistory( aHistory );
+ bool bHaveEnabledState = false;
+ for ( ::std::vector< WizardState >::const_iterator state = aHistory.begin();
+ state != aHistory.end() && !bHaveEnabledState;
+ ++state
+ )
+ {
+ if ( isStateEnabled( *state ) )
+ bHaveEnabledState = true;
+ }
+
+ enableButtons( WZB_PREVIOUS, bHaveEnabledState );
+
+ implUpdateRoadmap();
+ }
+
+ //--------------------------------------------------------------------
+ IMPL_LINK( RoadmapWizard, OnRoadmapItemSelected, void*, EMPTYARG )
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ RoadmapTypes::ItemId nCurItemId = m_pImpl->pRoadmap->GetCurrentRoadmapItemID();
+ if ( nCurItemId == getCurrentState() )
+ // nothing to do
+ return 1L;
+
+ if ( isTravelingSuspended() )
+ return 0;
+
+ WizardTravelSuspension aTravelGuard( *this );
+
+ sal_Int32 nCurrentIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath );
+ sal_Int32 nNewIndex = m_pImpl->getStateIndexInPath( nCurItemId, m_pImpl->nActivePath );
+
+ DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ),
+ "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
+ if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) )
+ {
+ return 0L;
+ }
+
+ sal_Bool bResult = sal_True;
+ if ( nNewIndex > nCurrentIndex )
+ {
+ bResult = skipUntil( (WizardState)nCurItemId );
+ WizardState nTemp = (WizardState)nCurItemId;
+ while( nTemp )
+ {
+ if( m_pImpl->aDisabledStates.find( --nTemp ) != m_pImpl->aDisabledStates.end() )
+ removePageFromHistory( nTemp );
+ }
+ }
+ else
+ bResult = skipBackwardUntil( (WizardState)nCurItemId );
+
+ if ( !bResult )
+ m_pImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() );
+
+ return 1L;
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::enterState( WizardState _nState )
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ OWizardMachine::enterState( _nState );
+
+ // synchronize the roadmap
+ implUpdateRoadmap( );
+ m_pImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() );
+ }
+
+ //--------------------------------------------------------------------
+ String RoadmapWizard::getStateDisplayName( WizardState _nState ) const
+ {
+ String sDisplayName;
+
+ StateDescriptions::const_iterator pos = m_pImpl->aStateDescriptors.find( _nState );
+ OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(),
+ "RoadmapWizard::getStateDisplayName: no default implementation available for this state!" );
+ if ( pos != m_pImpl->aStateDescriptors.end() )
+ sDisplayName = pos->second.first;
+
+ return sDisplayName;
+ }
+
+ //--------------------------------------------------------------------
+ TabPage* RoadmapWizard::createPage( WizardState _nState )
+ {
+ TabPage* pPage( NULL );
+
+ StateDescriptions::const_iterator pos = m_pImpl->aStateDescriptors.find( _nState );
+ OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(),
+ "RoadmapWizard::createPage: no default implementation available for this state!" );
+ if ( pos != m_pImpl->aStateDescriptors.end() )
+ {
+ RoadmapPageFactory pFactory = pos->second.second;
+ pPage = (*pFactory)( *this );
+ }
+
+ return pPage;
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::enableState( WizardState _nState, bool _bEnable )
+ {
+ DBG_CHKTHIS( RoadmapWizard, CheckInvariants );
+
+ // remember this (in case the state appears in the roadmap later on)
+ if ( _bEnable )
+ m_pImpl->aDisabledStates.erase( _nState );
+ else
+ {
+ m_pImpl->aDisabledStates.insert( _nState );
+ removePageFromHistory( _nState );
+ }
+
+ // if the state is currently in the roadmap, reflect it's new status
+ m_pImpl->pRoadmap->EnableRoadmapItem( (RoadmapTypes::ItemId)_nState, _bEnable );
+ }
+
+ //--------------------------------------------------------------------
+ bool RoadmapWizard::knowsState( WizardState i_nState ) const
+ {
+ for ( Paths::const_iterator path = m_pImpl->aPaths.begin();
+ path != m_pImpl->aPaths.end();
+ ++path
+ )
+ {
+ for ( WizardPath::const_iterator state = path->second.begin();
+ state != path->second.end();
+ ++state
+ )
+ {
+ if ( *state == i_nState )
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ bool RoadmapWizard::isStateEnabled( WizardState _nState ) const
+ {
+ return m_pImpl->aDisabledStates.find( _nState ) == m_pImpl->aDisabledStates.end();
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::Resize()
+ {
+ OWizardMachine::Resize();
+
+ if ( IsReallyShown() && !IsInInitShow() )
+ ResizeFixedLine();
+ }
+
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::StateChanged( StateChangedType nType )
+ {
+ WizardDialog::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ResizeFixedLine();
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::ResizeFixedLine()
+ {
+ Size aSize( m_pImpl->pRoadmap->GetSizePixel() );
+ aSize.Width() = m_pImpl->pFixedLine->GetSizePixel().Width();
+ m_pImpl->pFixedLine->SetSizePixel( aSize );
+ }
+
+ //--------------------------------------------------------------------
+ void RoadmapWizard::updateRoadmapItemLabel( WizardState _nState )
+ {
+ const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
+ RoadmapTypes::ItemIndex nUpperStepBoundary = (RoadmapTypes::ItemIndex)rActivePath.size();
+ RoadmapTypes::ItemIndex nLoopUntil = ::std::max( (RoadmapTypes::ItemIndex)nUpperStepBoundary, m_pImpl->pRoadmap->GetItemCount() );
+ sal_Int32 nCurrentStatePathIndex = -1;
+ if ( m_pImpl->nActivePath != -1 )
+ nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath );
+ for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex )
+ {
+ bool bExistentItem = ( nItemIndex < m_pImpl->pRoadmap->GetItemCount() );
+ if ( bExistentItem )
+ {
+ // there is an item with this index in the roadmap - does it match what is requested by
+ // the respective state in the active path?
+ RoadmapTypes::ItemId nPresentItemId = m_pImpl->pRoadmap->GetItemID( nItemIndex );
+ WizardState nRequiredState = rActivePath[ nItemIndex ];
+ if ( _nState == nRequiredState )
+ {
+ m_pImpl->pRoadmap->ChangeRoadmapItemLabel( nPresentItemId, getStateDisplayName( nRequiredState ) );
+ break;
+ }
+ }
+ }
+ }
+
+//........................................................................
+} // namespace svt
+//........................................................................