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