1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <vcl/toolkit/roadmap.hxx>
22 #include <tools/debug.hxx>
23 #include <osl/diagnose.h>
25 #include <strings.hrc>
33 #include "wizimpldata.hxx"
37 using namespace RoadmapWizardTypes
;
41 typedef ::std::set
< WizardTypes::WizardState
> StateSet
;
49 WizardTypes::WizardState
,
57 struct RoadmapWizardImpl
59 ScopedVclPtr
<ORoadmap
> pRoadmap
;
62 StateDescriptions aStateDescriptors
;
63 StateSet aDisabledStates
;
64 bool bActivePathIsDefinite
;
69 ,bActivePathIsDefinite( false )
73 /// returns the index of the current state in given path, or -1
74 static sal_Int32
getStateIndexInPath( WizardTypes::WizardState _nState
, const WizardPath
& _rPath
);
75 /// returns the index of the current state in the path with the given id, or -1
76 sal_Int32
getStateIndexInPath( WizardTypes::WizardState _nState
, PathId _nPathId
);
77 /// returns the index of the first state in which the two given paths differ
78 static sal_Int32
getFirstDifferentIndex( const WizardPath
& _rLHS
, const WizardPath
& _rRHS
);
82 sal_Int32
RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState
, const WizardPath
& _rPath
)
84 sal_Int32 nStateIndexInPath
= 0;
86 for (auto const& path
: _rPath
)
96 nStateIndexInPath
= -1;
97 return nStateIndexInPath
;
101 sal_Int32
RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState
, PathId _nPathId
)
103 sal_Int32 nStateIndexInPath
= -1;
104 Paths::const_iterator aPathPos
= aPaths
.find( _nPathId
);
105 if ( aPathPos
!= aPaths
.end( ) )
106 nStateIndexInPath
= getStateIndexInPath( _nState
, aPathPos
->second
);
107 return nStateIndexInPath
;
111 sal_Int32
RoadmapWizardImpl::getFirstDifferentIndex( const WizardPath
& _rLHS
, const WizardPath
& _rRHS
)
113 sal_Int32 nMinLength
= ::std::min( _rLHS
.size(), _rRHS
.size() );
114 for ( sal_Int32 nCheck
= 0; nCheck
< nMinLength
; ++nCheck
)
116 if ( _rLHS
[ nCheck
] != _rRHS
[ nCheck
] )
123 RoadmapWizard::RoadmapWizard(vcl::Window
* pParent
, WinBits nStyle
, InitFlag eFlag
)
124 : Dialog(pParent
, nStyle
, eFlag
)
127 , m_pNextPage(nullptr)
128 , m_pPrevPage(nullptr)
130 , m_xWizardImpl(new WizardMachineImplData
)
131 , m_xRoadmapImpl(new RoadmapWizardImpl
)
135 implConstruct(WizardButtonFlags::NEXT
| WizardButtonFlags::PREVIOUS
| WizardButtonFlags::FINISH
| WizardButtonFlags::CANCEL
| WizardButtonFlags::HELP
);
140 RoadmapWizardMachine::RoadmapWizardMachine(weld::Window
* pParent
)
141 : WizardMachine(pParent
, WizardButtonFlags::NEXT
| WizardButtonFlags::PREVIOUS
| WizardButtonFlags::FINISH
| WizardButtonFlags::CANCEL
| WizardButtonFlags::HELP
)
142 , m_pImpl( new RoadmapWizardImpl
)
144 m_xAssistant
->connect_jump_page(LINK(this, RoadmapWizardMachine
, OnRoadmapItemSelected
));
147 void RoadmapWizard::impl_construct()
149 SetLeftAlignedButtonCount( 1 );
150 SetEmptyViewMargin();
152 m_xRoadmapImpl
->pRoadmap
.disposeAndReset( VclPtr
<ORoadmap
>::Create( this, WB_TABSTOP
) );
153 m_xRoadmapImpl
->pRoadmap
->SetText( VclResId( STR_WIZDLG_ROADMAP_TITLE
) );
154 m_xRoadmapImpl
->pRoadmap
->SetPosPixel( Point( 0, 0 ) );
155 m_xRoadmapImpl
->pRoadmap
->SetItemSelectHdl( LINK( this, RoadmapWizard
, OnRoadmapItemSelected
) );
157 Size aRoadmapSize
= LogicToPixel(Size(85, 0), MapMode(MapUnit::MapAppFont
));
158 aRoadmapSize
.setHeight( GetSizePixel().Height() );
159 m_xRoadmapImpl
->pRoadmap
->SetSizePixel( aRoadmapSize
);
161 SetViewWindow( m_xRoadmapImpl
->pRoadmap
);
162 SetViewAlign( WindowAlign::Left
);
163 m_xRoadmapImpl
->pRoadmap
->Show();
166 void RoadmapWizard::ShowRoadmap(bool bShow
)
168 m_xRoadmapImpl
->pRoadmap
->Show(bShow
);
172 RoadmapWizard::~RoadmapWizard()
177 RoadmapWizardMachine::~RoadmapWizardMachine()
181 void RoadmapWizard::dispose()
183 m_xRoadmapImpl
.reset();
185 m_pFinish
.disposeAndClear();
186 m_pCancel
.disposeAndClear();
187 m_pNextPage
.disposeAndClear();
188 m_pPrevPage
.disposeAndClear();
189 m_pHelp
.disposeAndClear();
193 for (WizardTypes::WizardState i
= 0; i
< m_xWizardImpl
->nFirstUnknownPage
; ++i
)
195 TabPage
*pPage
= GetPage(i
);
197 pPage
->disposeOnce();
199 m_xWizardImpl
.reset();
202 maWizardLayoutIdle
.Stop();
204 // Remove all buttons
206 RemoveButton( mpFirstBtn
->mpButton
);
209 while ( mpFirstPage
)
210 RemovePage( mpFirstPage
->mpPage
);
212 mpCurTabPage
.clear();
215 mpViewWindow
.clear();
219 void RoadmapWizard::SetRoadmapHelpId( const OString
& _rId
)
221 m_xRoadmapImpl
->pRoadmap
->SetHelpId( _rId
);
224 void RoadmapWizardMachine::SetRoadmapHelpId(const OString
& rId
)
226 m_xAssistant
->set_page_side_help_id(rId
);
229 void RoadmapWizardMachine::declarePath( PathId _nPathId
, const WizardPath
& _lWizardStates
)
231 m_pImpl
->aPaths
.emplace( _nPathId
, _lWizardStates
);
233 if ( m_pImpl
->aPaths
.size() == 1 )
234 // the very first path -> activate it
235 activatePath( _nPathId
);
237 implUpdateRoadmap( );
240 void RoadmapWizardMachine::activatePath( PathId _nPathId
, bool _bDecideForIt
)
242 if ( ( _nPathId
== m_pImpl
->nActivePath
) && ( _bDecideForIt
== m_pImpl
->bActivePathIsDefinite
) )
246 // does the given path exist?
247 Paths::const_iterator aNewPathPos
= m_pImpl
->aPaths
.find( _nPathId
);
248 DBG_ASSERT( aNewPathPos
!= m_pImpl
->aPaths
.end(), "RoadmapWizard::activate: there is no such path!" );
249 if ( aNewPathPos
== m_pImpl
->aPaths
.end() )
252 // determine the index of the current state in the current path
253 sal_Int32 nCurrentStatePathIndex
= -1;
254 if ( m_pImpl
->nActivePath
!= -1 )
255 nCurrentStatePathIndex
= m_pImpl
->getStateIndexInPath( getCurrentState(), m_pImpl
->nActivePath
);
257 DBG_ASSERT( static_cast<sal_Int32
>(aNewPathPos
->second
.size()) > nCurrentStatePathIndex
,
258 "RoadmapWizard::activate: you cannot activate a path which has less states than we've already advanced!" );
259 // If this asserts, this for instance means that we are already in state number, say, 5
260 // of our current path, and the caller tries to activate a path which has less than 5
262 if ( static_cast<sal_Int32
>(aNewPathPos
->second
.size()) <= nCurrentStatePathIndex
)
265 // assert that the current and the new path are equal, up to nCurrentStatePathIndex
266 Paths::const_iterator aActivePathPos
= m_pImpl
->aPaths
.find( m_pImpl
->nActivePath
);
267 if ( aActivePathPos
!= m_pImpl
->aPaths
.end() )
269 if ( RoadmapWizardImpl::getFirstDifferentIndex( aActivePathPos
->second
, aNewPathPos
->second
) <= nCurrentStatePathIndex
)
271 OSL_FAIL( "RoadmapWizard::activate: you cannot activate a path which conflicts with the current one *before* the current state!" );
276 m_pImpl
->nActivePath
= _nPathId
;
277 m_pImpl
->bActivePathIsDefinite
= _bDecideForIt
;
279 implUpdateRoadmap( );
282 void RoadmapWizard::implUpdateRoadmap( )
284 DBG_ASSERT( m_xRoadmapImpl
->aPaths
.find( m_xRoadmapImpl
->nActivePath
) != m_xRoadmapImpl
->aPaths
.end(),
285 "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
286 const WizardPath
& rActivePath( m_xRoadmapImpl
->aPaths
[ m_xRoadmapImpl
->nActivePath
] );
288 sal_Int32 nCurrentStatePathIndex
= RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath
);
289 if (nCurrentStatePathIndex
< 0)
292 // determine up to which index (in the new path) we have to display the items
293 RoadmapTypes::ItemIndex nUpperStepBoundary
= static_cast<RoadmapTypes::ItemIndex
>(rActivePath
.size());
294 bool bIncompletePath
= false;
295 if ( !m_xRoadmapImpl
->bActivePathIsDefinite
)
297 for (auto const& path
: m_xRoadmapImpl
->aPaths
)
299 if ( path
.first
== m_xRoadmapImpl
->nActivePath
)
300 // it's the path we are just activating -> no need to check anything
302 // the index from which on both paths differ
303 sal_Int32 nDivergenceIndex
= RoadmapWizardImpl::getFirstDifferentIndex( rActivePath
, path
.second
);
304 if ( nDivergenceIndex
<= nCurrentStatePathIndex
)
305 // they differ in an index which we have already left behind us
306 // -> this is no conflict anymore
309 // the path conflicts with our new path -> don't activate the
310 // *complete* new path, but only up to the step which is unambiguous
311 nUpperStepBoundary
= nDivergenceIndex
;
312 bIncompletePath
= true;
316 // can we advance from the current page?
317 bool bCurrentPageCanAdvance
= true;
318 TabPage
* pCurrentPage
= GetPage( getCurrentState() );
321 const IWizardPageController
* pController
= getPageController( GetPage( getCurrentState() ) );
322 OSL_ENSURE( pController
!= nullptr, "RoadmapWizard::implUpdateRoadmap: no controller for the current page!" );
323 bCurrentPageCanAdvance
= !pController
|| pController
->canAdvance();
326 // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active
327 // path, up to (excluding) nUpperStepBoundary
328 RoadmapTypes::ItemIndex nLoopUntil
= ::std::max( nUpperStepBoundary
, m_xRoadmapImpl
->pRoadmap
->GetItemCount() );
329 for ( RoadmapTypes::ItemIndex nItemIndex
= nCurrentStatePathIndex
; nItemIndex
< nLoopUntil
; ++nItemIndex
)
331 bool bExistentItem
= ( nItemIndex
< m_xRoadmapImpl
->pRoadmap
->GetItemCount() );
332 bool bNeedItem
= ( nItemIndex
< nUpperStepBoundary
);
334 bool bInsertItem
= false;
339 while ( nItemIndex
< m_xRoadmapImpl
->pRoadmap
->GetItemCount() )
340 m_xRoadmapImpl
->pRoadmap
->DeleteRoadmapItem( nItemIndex
);
345 // there is an item with this index in the roadmap - does it match what is requested by
346 // the respective state in the active path?
347 RoadmapTypes::ItemId nPresentItemId
= m_xRoadmapImpl
->pRoadmap
->GetItemID( nItemIndex
);
348 WizardTypes::WizardState nRequiredState
= rActivePath
[ nItemIndex
];
349 if ( nPresentItemId
!= nRequiredState
)
351 m_xRoadmapImpl
->pRoadmap
->DeleteRoadmapItem( nItemIndex
);
358 DBG_ASSERT( bNeedItem
, "RoadmapWizard::implUpdateRoadmap: ehm - none needed, none present - why did the loop not terminate?" );
359 bInsertItem
= bNeedItem
;
362 WizardTypes::WizardState
nState( rActivePath
[ nItemIndex
] );
365 m_xRoadmapImpl
->pRoadmap
->InsertRoadmapItem(
367 getStateDisplayName( nState
),
373 // if the item is *after* the current state, but the current page does not
374 // allow advancing, the disable the state. This relieves derived classes
375 // from disabling all future states just because the current state does not
376 // (yet) allow advancing.
377 const bool bUnconditionedDisable
= !bCurrentPageCanAdvance
&& ( nItemIndex
> nCurrentStatePathIndex
);
378 const bool bEnable
= !bUnconditionedDisable
&& ( m_xRoadmapImpl
->aDisabledStates
.find( nState
) == m_xRoadmapImpl
->aDisabledStates
.end() );
380 m_xRoadmapImpl
->pRoadmap
->EnableRoadmapItem( m_xRoadmapImpl
->pRoadmap
->GetItemID( nItemIndex
), bEnable
);
383 m_xRoadmapImpl
->pRoadmap
->SetRoadmapComplete( !bIncompletePath
);
386 void RoadmapWizardMachine::implUpdateRoadmap( )
389 DBG_ASSERT( m_pImpl
->aPaths
.find( m_pImpl
->nActivePath
) != m_pImpl
->aPaths
.end(),
390 "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
391 const WizardPath
& rActivePath( m_pImpl
->aPaths
[ m_pImpl
->nActivePath
] );
393 sal_Int32 nCurrentStatePathIndex
= RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath
);
394 if (nCurrentStatePathIndex
< 0)
397 // determine up to which index (in the new path) we have to display the items
398 RoadmapTypes::ItemIndex nUpperStepBoundary
= static_cast<RoadmapTypes::ItemIndex
>(rActivePath
.size());
399 if ( !m_pImpl
->bActivePathIsDefinite
)
401 for (auto const& path
: m_pImpl
->aPaths
)
403 if ( path
.first
== m_pImpl
->nActivePath
)
404 // it's the path we are just activating -> no need to check anything
406 // the index from which on both paths differ
407 sal_Int32 nDivergenceIndex
= RoadmapWizardImpl::getFirstDifferentIndex( rActivePath
, path
.second
);
408 if ( nDivergenceIndex
<= nCurrentStatePathIndex
)
409 // they differ in an index which we have already left behind us
410 // -> this is no conflict anymore
413 // the path conflicts with our new path -> don't activate the
414 // *complete* new path, but only up to the step which is unambiguous
415 nUpperStepBoundary
= nDivergenceIndex
;
419 // can we advance from the current page?
420 bool bCurrentPageCanAdvance
= true;
421 BuilderPage
* pCurrentPage
= GetPage( getCurrentState() );
424 const IWizardPageController
* pController
= getPageController( GetPage( getCurrentState() ) );
425 OSL_ENSURE( pController
!= nullptr, "RoadmapWizard::implUpdateRoadmap: no controller for the current page!" );
426 bCurrentPageCanAdvance
= !pController
|| pController
->canAdvance();
429 // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active
430 // path, up to (excluding) nUpperStepBoundary
431 RoadmapTypes::ItemIndex nRoadmapItems
= m_xAssistant
->get_n_pages();
432 RoadmapTypes::ItemIndex nLoopUntil
= ::std::max( nUpperStepBoundary
, nRoadmapItems
);
433 for ( RoadmapTypes::ItemIndex nItemIndex
= nCurrentStatePathIndex
; nItemIndex
< nLoopUntil
; ++nItemIndex
)
435 bool bExistentItem
= ( nItemIndex
< nRoadmapItems
);
436 bool bNeedItem
= ( nItemIndex
< nUpperStepBoundary
);
438 bool bInsertItem
= false;
443 int nPages
= nRoadmapItems
;
444 for (int i
= nPages
- 1; i
>= nItemIndex
; --i
)
446 m_xAssistant
->set_page_title(m_xAssistant
->get_page_ident(i
), "");
453 // there is an item with this index in the roadmap - does it match what is requested by
454 // the respective state in the active path?
455 RoadmapTypes::ItemId nPresentItemId
= m_xAssistant
->get_page_ident(nItemIndex
).toInt32();
456 WizardTypes::WizardState nRequiredState
= rActivePath
[ nItemIndex
];
457 if ( nPresentItemId
!= nRequiredState
)
459 m_xAssistant
->set_page_title(OString::number(nPresentItemId
), "");
466 DBG_ASSERT( bNeedItem
, "RoadmapWizard::implUpdateRoadmap: ehm - none needed, none present - why did the loop not terminate?" );
467 bInsertItem
= bNeedItem
;
470 WizardTypes::WizardState
nState( rActivePath
[ nItemIndex
] );
474 GetOrCreatePage(nState
);
477 OString
sIdent(OString::number(nState
));
478 m_xAssistant
->set_page_index(sIdent
, nItemIndex
);
479 m_xAssistant
->set_page_title(sIdent
, getStateDisplayName(nState
));
481 // if the item is *after* the current state, but the current page does not
482 // allow advancing, the disable the state. This relieves derived classes
483 // from disabling all future states just because the current state does not
484 // (yet) allow advancing.
485 const bool bUnconditionedDisable
= !bCurrentPageCanAdvance
&& ( nItemIndex
> nCurrentStatePathIndex
);
486 const bool bEnable
= !bUnconditionedDisable
&& ( m_pImpl
->aDisabledStates
.find( nState
) == m_pImpl
->aDisabledStates
.end() );
487 m_xAssistant
->set_page_sensitive(sIdent
, bEnable
);
491 WizardTypes::WizardState
RoadmapWizard::determineNextState( WizardTypes::WizardState _nCurrentState
) const
493 sal_Int32 nCurrentStatePathIndex
= -1;
495 Paths::const_iterator aActivePathPos
= m_xRoadmapImpl
->aPaths
.find( m_xRoadmapImpl
->nActivePath
);
496 if ( aActivePathPos
!= m_xRoadmapImpl
->aPaths
.end() )
497 nCurrentStatePathIndex
= RoadmapWizardImpl::getStateIndexInPath( _nCurrentState
, aActivePathPos
->second
);
499 DBG_ASSERT( nCurrentStatePathIndex
!= -1, "RoadmapWizard::determineNextState: ehm - how can we travel if there is no (valid) active path?" );
500 if ( nCurrentStatePathIndex
== -1 )
501 return WZS_INVALID_STATE
;
503 sal_Int32 nNextStateIndex
= nCurrentStatePathIndex
+ 1;
505 while ( ( nNextStateIndex
< static_cast<sal_Int32
>(aActivePathPos
->second
.size()) )
506 && ( m_xRoadmapImpl
->aDisabledStates
.find( aActivePathPos
->second
[ nNextStateIndex
] ) != m_xRoadmapImpl
->aDisabledStates
.end() )
512 if ( nNextStateIndex
>= static_cast<sal_Int32
>(aActivePathPos
->second
.size()) )
513 // there is no next state in the current path (at least none which is enabled)
514 return WZS_INVALID_STATE
;
516 return aActivePathPos
->second
[ nNextStateIndex
];
519 WizardTypes::WizardState
RoadmapWizardMachine::determineNextState( WizardTypes::WizardState _nCurrentState
) const
521 sal_Int32 nCurrentStatePathIndex
= -1;
523 Paths::const_iterator aActivePathPos
= m_pImpl
->aPaths
.find( m_pImpl
->nActivePath
);
524 if ( aActivePathPos
!= m_pImpl
->aPaths
.end() )
525 nCurrentStatePathIndex
= RoadmapWizardImpl::getStateIndexInPath( _nCurrentState
, aActivePathPos
->second
);
527 DBG_ASSERT( nCurrentStatePathIndex
!= -1, "RoadmapWizard::determineNextState: ehm - how can we travel if there is no (valid) active path?" );
528 if ( nCurrentStatePathIndex
== -1 )
529 return WZS_INVALID_STATE
;
531 sal_Int32 nNextStateIndex
= nCurrentStatePathIndex
+ 1;
533 while ( ( nNextStateIndex
< static_cast<sal_Int32
>(aActivePathPos
->second
.size()) )
534 && ( m_pImpl
->aDisabledStates
.find( aActivePathPos
->second
[ nNextStateIndex
] ) != m_pImpl
->aDisabledStates
.end() )
540 if ( nNextStateIndex
>= static_cast<sal_Int32
>(aActivePathPos
->second
.size()) )
541 // there is no next state in the current path (at least none which is enabled)
542 return WZS_INVALID_STATE
;
544 return aActivePathPos
->second
[ nNextStateIndex
];
547 bool RoadmapWizard::canAdvance() const
549 if ( !m_xRoadmapImpl
->bActivePathIsDefinite
)
551 // check how many paths are still allowed
552 const WizardPath
& rActivePath( m_xRoadmapImpl
->aPaths
[ m_xRoadmapImpl
->nActivePath
] );
553 sal_Int32 nCurrentStatePathIndex
= RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath
);
555 size_t nPossiblePaths(0);
556 for (auto const& path
: m_xRoadmapImpl
->aPaths
)
558 // the index from which on both paths differ
559 sal_Int32 nDivergenceIndex
= RoadmapWizardImpl::getFirstDifferentIndex( rActivePath
, path
.second
);
561 if ( nDivergenceIndex
> nCurrentStatePathIndex
)
562 // this path is still a possible path
566 // if we have more than one path which is still possible, then we assume
567 // to always have a next state. Though there might be scenarios where this
568 // is not true, but this is too sophisticated (means not really needed) right now.
569 if ( nPossiblePaths
> 1 )
573 const WizardPath
& rPath
= m_xRoadmapImpl
->aPaths
[ m_xRoadmapImpl
->nActivePath
];
574 return *rPath
.rbegin() != getCurrentState();
577 bool RoadmapWizardMachine::canAdvance() const
579 if ( !m_pImpl
->bActivePathIsDefinite
)
581 // check how many paths are still allowed
582 const WizardPath
& rActivePath( m_pImpl
->aPaths
[ m_pImpl
->nActivePath
] );
583 sal_Int32 nCurrentStatePathIndex
= RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath
);
585 size_t nPossiblePaths(0);
586 for (auto const& path
: m_pImpl
->aPaths
)
588 // the index from which on both paths differ
589 sal_Int32 nDivergenceIndex
= RoadmapWizardImpl::getFirstDifferentIndex( rActivePath
, path
.second
);
591 if ( nDivergenceIndex
> nCurrentStatePathIndex
)
592 // this path is still a possible path
596 // if we have more than one path which is still possible, then we assume
597 // to always have a next state. Though there might be scenarios where this
598 // is not true, but this is too sophisticated (means not really needed) right now.
599 if ( nPossiblePaths
> 1 )
603 const WizardPath
& rPath
= m_pImpl
->aPaths
[ m_pImpl
->nActivePath
];
604 return *rPath
.rbegin() != getCurrentState();
607 void RoadmapWizardMachine::updateTravelUI()
609 WizardMachine::updateTravelUI();
611 // disable the "Previous" button if all states in our history are disabled
612 std::vector
< WizardTypes::WizardState
> aHistory
;
613 getStateHistory( aHistory
);
614 bool bHaveEnabledState
= false;
615 for (auto const& state
: aHistory
)
617 if ( isStateEnabled(state
) )
619 bHaveEnabledState
= true;
624 enableButtons( WizardButtonFlags::PREVIOUS
, bHaveEnabledState
);
629 IMPL_LINK_NOARG(RoadmapWizard
, OnRoadmapItemSelected
, LinkParamNone
*, void)
631 RoadmapTypes::ItemId nCurItemId
= m_xRoadmapImpl
->pRoadmap
->GetCurrentRoadmapItemID();
632 if ( nCurItemId
== getCurrentState() )
636 if ( isTravelingSuspended() )
639 RoadmapWizardTravelSuspension
aTravelGuard( *this );
641 sal_Int32 nCurrentIndex
= m_xRoadmapImpl
->getStateIndexInPath( getCurrentState(), m_xRoadmapImpl
->nActivePath
);
642 sal_Int32 nNewIndex
= m_xRoadmapImpl
->getStateIndexInPath( nCurItemId
, m_xRoadmapImpl
->nActivePath
);
644 DBG_ASSERT( ( nCurrentIndex
!= -1 ) && ( nNewIndex
!= -1 ),
645 "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
646 if ( ( nCurrentIndex
== -1 ) || ( nNewIndex
== -1 ) )
652 if ( nNewIndex
> nCurrentIndex
)
654 bResult
= skipUntil( static_cast<WizardTypes::WizardState
>(nCurItemId
) );
655 WizardTypes::WizardState nTemp
= static_cast<WizardTypes::WizardState
>(nCurItemId
);
658 if( m_xRoadmapImpl
->aDisabledStates
.find( --nTemp
) != m_xRoadmapImpl
->aDisabledStates
.end() )
659 removePageFromHistory( nTemp
);
663 bResult
= skipBackwardUntil( static_cast<WizardTypes::WizardState
>(nCurItemId
) );
666 m_xRoadmapImpl
->pRoadmap
->SelectRoadmapItemByID( getCurrentState() );
669 IMPL_LINK(RoadmapWizardMachine
, OnRoadmapItemSelected
, const OString
&, rCurItemId
, bool)
671 int nCurItemId
= rCurItemId
.toInt32();
673 if ( nCurItemId
== getCurrentState() )
677 if ( isTravelingSuspended() )
680 WizardTravelSuspension
aTravelGuard( *this );
682 sal_Int32 nCurrentIndex
= m_pImpl
->getStateIndexInPath( getCurrentState(), m_pImpl
->nActivePath
);
683 sal_Int32 nNewIndex
= m_pImpl
->getStateIndexInPath( nCurItemId
, m_pImpl
->nActivePath
);
685 DBG_ASSERT( ( nCurrentIndex
!= -1 ) && ( nNewIndex
!= -1 ),
686 "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
687 if ( ( nCurrentIndex
== -1 ) || ( nNewIndex
== -1 ) )
693 if ( nNewIndex
> nCurrentIndex
)
695 bResult
= skipUntil( static_cast<WizardTypes::WizardState
>(nCurItemId
) );
696 WizardTypes::WizardState nTemp
= static_cast<WizardTypes::WizardState
>(nCurItemId
);
699 if( m_pImpl
->aDisabledStates
.find( --nTemp
) != m_pImpl
->aDisabledStates
.end() )
700 removePageFromHistory( nTemp
);
704 bResult
= skipBackwardUntil( static_cast<WizardTypes::WizardState
>(nCurItemId
) );
709 void RoadmapWizard::enterState(WizardTypes::WizardState nState
)
712 IWizardPageController
* pController
= getPageController( GetPage( nState
) );
715 pController
->initializePage();
717 if ( isAutomaticNextButtonStateEnabled() )
718 enableButtons( WizardButtonFlags::NEXT
, canAdvance() );
720 enableButtons( WizardButtonFlags::PREVIOUS
, !m_xWizardImpl
->aStateHistory
.empty() );
722 // set the new title - it depends on the current page (i.e. state)
726 // synchronize the roadmap
727 implUpdateRoadmap( );
728 m_xRoadmapImpl
->pRoadmap
->SelectRoadmapItemByID( getCurrentState() );
731 void RoadmapWizardMachine::enterState( WizardTypes::WizardState _nState
)
733 WizardMachine::enterState( _nState
);
735 // synchronize the roadmap
739 OUString
RoadmapWizard::getStateDisplayName( WizardTypes::WizardState _nState
) const
741 OUString sDisplayName
;
743 StateDescriptions::const_iterator pos
= m_xRoadmapImpl
->aStateDescriptors
.find( _nState
);
744 OSL_ENSURE( pos
!= m_xRoadmapImpl
->aStateDescriptors
.end(),
745 "RoadmapWizard::getStateDisplayName: no default implementation available for this state!" );
746 if ( pos
!= m_xRoadmapImpl
->aStateDescriptors
.end() )
747 sDisplayName
= pos
->second
.first
;
752 OUString
RoadmapWizardMachine::getStateDisplayName( WizardTypes::WizardState _nState
) const
754 OUString sDisplayName
;
756 StateDescriptions::const_iterator pos
= m_pImpl
->aStateDescriptors
.find( _nState
);
757 OSL_ENSURE( pos
!= m_pImpl
->aStateDescriptors
.end(),
758 "RoadmapWizard::getStateDisplayName: no default implementation available for this state!" );
759 if ( pos
!= m_pImpl
->aStateDescriptors
.end() )
760 sDisplayName
= pos
->second
.first
;
765 VclPtr
<TabPage
> RoadmapWizard::createPage( WizardTypes::WizardState _nState
)
767 VclPtr
<TabPage
> pPage
;
769 StateDescriptions::const_iterator pos
= m_xRoadmapImpl
->aStateDescriptors
.find( _nState
);
770 OSL_ENSURE( pos
!= m_xRoadmapImpl
->aStateDescriptors
.end(),
771 "RoadmapWizard::createPage: no default implementation available for this state!" );
772 if ( pos
!= m_xRoadmapImpl
->aStateDescriptors
.end() )
774 RoadmapPageFactory pFactory
= pos
->second
.second
;
775 pPage
= (*pFactory
)( *this );
781 void RoadmapWizardMachine::enableState( WizardTypes::WizardState _nState
, bool _bEnable
)
783 // remember this (in case the state appears in the roadmap later on)
785 m_pImpl
->aDisabledStates
.erase( _nState
);
788 m_pImpl
->aDisabledStates
.insert( _nState
);
789 removePageFromHistory( _nState
);
792 // if the state is currently in the roadmap, reflect it's new status
793 m_xAssistant
->set_page_sensitive(OString::number(_nState
), _bEnable
);
796 bool RoadmapWizardMachine::knowsState( WizardTypes::WizardState i_nState
) const
798 for (auto const& path
: m_pImpl
->aPaths
)
800 for (auto const& state
: path
.second
)
802 if ( state
== i_nState
)
809 bool RoadmapWizardMachine::isStateEnabled( WizardTypes::WizardState _nState
) const
811 return m_pImpl
->aDisabledStates
.find( _nState
) == m_pImpl
->aDisabledStates
.end();
814 void RoadmapWizard::InsertRoadmapItem(int nItemIndex
, const OUString
& rText
, int nItemId
, bool bEnable
)
816 m_xRoadmapImpl
->pRoadmap
->InsertRoadmapItem(nItemIndex
, rText
, nItemId
, bEnable
);
819 void RoadmapWizard::SelectRoadmapItemByID(int nItemId
)
821 m_xRoadmapImpl
->pRoadmap
->SelectRoadmapItemByID(nItemId
);
824 void RoadmapWizard::DeleteRoadmapItems()
826 while (m_xRoadmapImpl
->pRoadmap
->GetItemCount())
827 m_xRoadmapImpl
->pRoadmap
->DeleteRoadmapItem(0);
830 void RoadmapWizard::SetItemSelectHdl( const Link
<LinkParamNone
*,void>& _rHdl
)
832 m_xRoadmapImpl
->pRoadmap
->SetItemSelectHdl(_rHdl
);
835 int RoadmapWizard::GetCurrentRoadmapItemID() const
837 return m_xRoadmapImpl
->pRoadmap
->GetCurrentRoadmapItemID();
842 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */