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