LibreOffice Module vcl (master) 1
roadmapwizard.cxx
Go to the documentation of this file.
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
22#include <tools/debug.hxx>
23#include <osl/diagnose.h>
24
25#include <strings.hrc>
26#include <svdata.hxx>
27#include <wizdlg.hxx>
28
29#include <vector>
30#include <map>
31#include <set>
32
33#include "wizimpldata.hxx"
34#include <uiobject-internal.hxx>
35
36namespace vcl
37{
38 using namespace RoadmapWizardTypes;
39
40 namespace
41 {
42 typedef ::std::set< WizardTypes::WizardState > StateSet;
43
44 typedef ::std::map<
45 PathId,
47 > Paths;
48
49 typedef ::std::map<
51 ::std::pair<
52 OUString,
54 >
55 > StateDescriptions;
56 }
57
59 {
61 Paths aPaths;
63 StateDescriptions aStateDescriptors;
66
68 :pRoadmap( nullptr )
69 ,nActivePath( -1 )
70 ,bActivePathIsDefinite( false )
71 {
72 }
73
75 static sal_Int32 getStateIndexInPath( WizardTypes::WizardState _nState, const WizardPath& _rPath );
77 sal_Int32 getStateIndexInPath( WizardTypes::WizardState _nState, PathId _nPathId );
79 static sal_Int32 getFirstDifferentIndex( const WizardPath& _rLHS, const WizardPath& _rRHS );
80 };
81
82
84 {
85 sal_Int32 nStateIndexInPath = 0;
86 bool bFound = false;
87 for (auto const& path : _rPath)
88 {
89 if (path == _nState)
90 {
91 bFound = true;
92 break;
93 }
94 ++nStateIndexInPath;
95 }
96 if (!bFound)
97 nStateIndexInPath = -1;
98 return nStateIndexInPath;
99 }
100
101
103 {
104 sal_Int32 nStateIndexInPath = -1;
105 Paths::const_iterator aPathPos = aPaths.find( _nPathId );
106 if ( aPathPos != aPaths.end( ) )
107 nStateIndexInPath = getStateIndexInPath( _nState, aPathPos->second );
108 return nStateIndexInPath;
109 }
110
111
113 {
114 sal_Int32 nMinLength = ::std::min( _rLHS.size(), _rRHS.size() );
115 for ( sal_Int32 nCheck = 0; nCheck < nMinLength; ++nCheck )
116 {
117 if ( _rLHS[ nCheck ] != _rRHS[ nCheck ] )
118 return nCheck;
119 }
120 return nMinLength;
121 }
122
123 //= RoadmapWizard
125 : Dialog(pParent, nStyle, eFlag)
126 , maWizardLayoutIdle("vcl RoadmapWizard maWizardLayoutIdle")
127 , m_pFinish(nullptr)
128 , m_pCancel(nullptr)
129 , m_pNextPage(nullptr)
130 , m_pPrevPage(nullptr)
131 , m_pHelp(nullptr)
132 , m_xWizardImpl(new WizardMachineImplData)
133 , m_xRoadmapImpl(new RoadmapWizardImpl)
134 {
135 mpFirstPage = nullptr;
136 mpFirstBtn = nullptr;
137 mpCurTabPage = nullptr;
138 mpPrevBtn = nullptr;
139 mpNextBtn = nullptr;
140 mpViewWindow = nullptr;
141 mnCurLevel = 0;
142 mbEmptyViewMargin = false;
144
146 maWizardLayoutIdle.SetInvokeHandler( LINK( this, RoadmapWizard, ImplHandleWizardLayoutTimerHdl ) );
147
149
151 mbEmptyViewMargin = true;
152
153 m_xRoadmapImpl->pRoadmap.disposeAndReset( VclPtr<ORoadmap>::Create( this, WB_TABSTOP ) );
154 m_xRoadmapImpl->pRoadmap->SetText( VclResId( STR_WIZDLG_ROADMAP_TITLE ) );
155 m_xRoadmapImpl->pRoadmap->SetPosPixel( Point( 0, 0 ) );
156 m_xRoadmapImpl->pRoadmap->SetItemSelectHdl( LINK( this, RoadmapWizard, OnRoadmapItemSelected ) );
157
158 Size aRoadmapSize = LogicToPixel(Size(85, 0), MapMode(MapUnit::MapAppFont));
159 aRoadmapSize.setHeight( GetSizePixel().Height() );
160 m_xRoadmapImpl->pRoadmap->SetSizePixel( aRoadmapSize );
161
162 mpViewWindow = m_xRoadmapImpl->pRoadmap;
163 m_xRoadmapImpl->pRoadmap->Show();
164 }
165
169 {
170 m_xAssistant->connect_jump_page(LINK(this, RoadmapWizardMachine, OnRoadmapItemSelected));
171 }
172
174 {
175 m_xRoadmapImpl->pRoadmap->Show(bShow);
177 }
178
180 {
181 disposeOnce();
182 }
183
185 {
186 }
187
189 {
190 m_xRoadmapImpl.reset();
191
197
198 if (m_xWizardImpl)
199 {
200 for (WizardTypes::WizardState i = 0; i < m_xWizardImpl->nFirstUnknownPage; ++i)
201 {
202 TabPage *pPage = GetPage(i);
203 if (pPage)
204 pPage->disposeOnce();
205 }
206 m_xWizardImpl.reset();
207 }
208
210
211 // Remove all buttons
212 while ( mpFirstBtn )
214
215 // Remove all pages
216 while ( mpFirstPage )
218
224 }
225
226 void RoadmapWizard::SetRoadmapHelpId( const OString& _rId )
227 {
228 m_xRoadmapImpl->pRoadmap->SetHelpId( _rId );
229 }
230
232 {
233 m_xAssistant->set_page_side_help_id(rId);
234 }
235
236 void RoadmapWizardMachine::declarePath( PathId _nPathId, const WizardPath& _lWizardStates)
237 {
238 m_pImpl->aPaths.emplace( _nPathId, _lWizardStates );
239
240 if ( m_pImpl->aPaths.size() == 1 )
241 // the very first path -> activate it
242 activatePath( _nPathId );
243 else
245 }
246
247 void RoadmapWizardMachine::activatePath( PathId _nPathId, bool _bDecideForIt )
248 {
249 if ( ( _nPathId == m_pImpl->nActivePath ) && ( _bDecideForIt == m_pImpl->bActivePathIsDefinite ) )
250 // nothing to do
251 return;
252
253 // does the given path exist?
254 Paths::const_iterator aNewPathPos = m_pImpl->aPaths.find( _nPathId );
255 DBG_ASSERT( aNewPathPos != m_pImpl->aPaths.end(), "RoadmapWizard::activate: there is no such path!" );
256 if ( aNewPathPos == m_pImpl->aPaths.end() )
257 return;
258
259 // determine the index of the current state in the current path
260 sal_Int32 nCurrentStatePathIndex = -1;
261 if ( m_pImpl->nActivePath != -1 )
262 nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath );
263
264 DBG_ASSERT( static_cast<sal_Int32>(aNewPathPos->second.size()) > nCurrentStatePathIndex,
265 "RoadmapWizard::activate: you cannot activate a path which has less states than we've already advanced!" );
266 // If this asserts, this for instance means that we are already in state number, say, 5
267 // of our current path, and the caller tries to activate a path which has less than 5
268 // states
269 if ( static_cast<sal_Int32>(aNewPathPos->second.size()) <= nCurrentStatePathIndex )
270 return;
271
272 // assert that the current and the new path are equal, up to nCurrentStatePathIndex
273 Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath );
274 if ( aActivePathPos != m_pImpl->aPaths.end() )
275 {
276 if ( RoadmapWizardImpl::getFirstDifferentIndex( aActivePathPos->second, aNewPathPos->second ) <= nCurrentStatePathIndex )
277 {
278 OSL_FAIL( "RoadmapWizard::activate: you cannot activate a path which conflicts with the current one *before* the current state!" );
279 return;
280 }
281 }
282
283 m_pImpl->nActivePath = _nPathId;
284 m_pImpl->bActivePathIsDefinite = _bDecideForIt;
285
287 }
288
290 {
291 DBG_ASSERT( m_xRoadmapImpl->aPaths.find( m_xRoadmapImpl->nActivePath ) != m_xRoadmapImpl->aPaths.end(),
292 "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
293 const WizardPath& rActivePath( m_xRoadmapImpl->aPaths[ m_xRoadmapImpl->nActivePath ] );
294
295 sal_Int32 nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
296 if (nCurrentStatePathIndex < 0)
297 return;
298
299 // determine up to which index (in the new path) we have to display the items
300 RoadmapTypes::ItemIndex nUpperStepBoundary = static_cast<RoadmapTypes::ItemIndex>(rActivePath.size());
301 bool bIncompletePath = false;
302 if ( !m_xRoadmapImpl->bActivePathIsDefinite )
303 {
304 for (auto const& path : m_xRoadmapImpl->aPaths)
305 {
306 if ( path.first == m_xRoadmapImpl->nActivePath )
307 // it's the path we are just activating -> no need to check anything
308 continue;
309 // the index from which on both paths differ
310 sal_Int32 nDivergenceIndex = RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
311 if ( nDivergenceIndex <= nCurrentStatePathIndex )
312 // they differ in an index which we have already left behind us
313 // -> this is no conflict anymore
314 continue;
315
316 // the path conflicts with our new path -> don't activate the
317 // *complete* new path, but only up to the step which is unambiguous
318 nUpperStepBoundary = nDivergenceIndex;
319 bIncompletePath = true;
320 }
321 }
322
323 // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active
324 // path, up to (excluding) nUpperStepBoundary
325 RoadmapTypes::ItemIndex nLoopUntil = ::std::max( nUpperStepBoundary, m_xRoadmapImpl->pRoadmap->GetItemCount() );
326 for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex )
327 {
328 bool bExistentItem = ( nItemIndex < m_xRoadmapImpl->pRoadmap->GetItemCount() );
329 bool bNeedItem = ( nItemIndex < nUpperStepBoundary );
330
331 bool bInsertItem = false;
332 if ( bExistentItem )
333 {
334 if ( !bNeedItem )
335 {
336 while ( nItemIndex < m_xRoadmapImpl->pRoadmap->GetItemCount() )
337 m_xRoadmapImpl->pRoadmap->DeleteRoadmapItem( nItemIndex );
338 break;
339 }
340 else
341 {
342 // there is an item with this index in the roadmap - does it match what is requested by
343 // the respective state in the active path?
344 RoadmapTypes::ItemId nPresentItemId = m_xRoadmapImpl->pRoadmap->GetItemID( nItemIndex );
345 WizardTypes::WizardState nRequiredState = rActivePath[ nItemIndex ];
346 if ( nPresentItemId != nRequiredState )
347 {
348 m_xRoadmapImpl->pRoadmap->DeleteRoadmapItem( nItemIndex );
349 bInsertItem = true;
350 }
351 }
352 }
353 else
354 {
355 DBG_ASSERT( bNeedItem, "RoadmapWizard::implUpdateRoadmap: ehm - none needed, none present - why did the loop not terminate?" );
356 bInsertItem = bNeedItem;
357 }
358
359 WizardTypes::WizardState nState( rActivePath[ nItemIndex ] );
360 if ( bInsertItem )
361 {
362 m_xRoadmapImpl->pRoadmap->InsertRoadmapItem(
363 nItemIndex,
365 nState,
366 true
367 );
368 }
369
370 const bool bEnable = m_xRoadmapImpl->aDisabledStates.find( nState ) == m_xRoadmapImpl->aDisabledStates.end();
371 m_xRoadmapImpl->pRoadmap->EnableRoadmapItem( m_xRoadmapImpl->pRoadmap->GetItemID( nItemIndex ), bEnable );
372 }
373
374 m_xRoadmapImpl->pRoadmap->SetRoadmapComplete( !bIncompletePath );
375 }
376
378 {
379
380 DBG_ASSERT( m_pImpl->aPaths.find( m_pImpl->nActivePath ) != m_pImpl->aPaths.end(),
381 "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
382 const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
383
384 sal_Int32 nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
385 if (nCurrentStatePathIndex < 0)
386 return;
387
388 // determine up to which index (in the new path) we have to display the items
389 RoadmapTypes::ItemIndex nUpperStepBoundary = static_cast<RoadmapTypes::ItemIndex>(rActivePath.size());
390 if ( !m_pImpl->bActivePathIsDefinite )
391 {
392 for (auto const& path : m_pImpl->aPaths)
393 {
394 if ( path.first == m_pImpl->nActivePath )
395 // it's the path we are just activating -> no need to check anything
396 continue;
397 // the index from which on both paths differ
398 sal_Int32 nDivergenceIndex = RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
399 if ( nDivergenceIndex <= nCurrentStatePathIndex )
400 // they differ in an index which we have already left behind us
401 // -> this is no conflict anymore
402 continue;
403
404 // the path conflicts with our new path -> don't activate the
405 // *complete* new path, but only up to the step which is unambiguous
406 nUpperStepBoundary = nDivergenceIndex;
407 }
408 }
409
410 // can we advance from the current page?
411 bool bCurrentPageCanAdvance = true;
412 BuilderPage* pCurrentPage = GetPage( getCurrentState() );
413 if ( pCurrentPage )
414 {
416 OSL_ENSURE( pController != nullptr, "RoadmapWizard::implUpdateRoadmap: no controller for the current page!" );
417 bCurrentPageCanAdvance = !pController || pController->canAdvance();
418 }
419
420 // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active
421 // path, up to (excluding) nUpperStepBoundary
422 RoadmapTypes::ItemIndex nRoadmapItems = m_xAssistant->get_n_pages();
423 RoadmapTypes::ItemIndex nLoopUntil = ::std::max( nUpperStepBoundary, nRoadmapItems );
424 for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex )
425 {
426 bool bExistentItem = ( nItemIndex < nRoadmapItems );
427 bool bNeedItem = ( nItemIndex < nUpperStepBoundary );
428
429 bool bInsertItem = false;
430 if ( bExistentItem )
431 {
432 if ( !bNeedItem )
433 {
434 int nPages = nRoadmapItems;
435 for (int i = nPages - 1; i >= nItemIndex; --i)
436 {
437 m_xAssistant->set_page_title(m_xAssistant->get_page_ident(i), "");
438 --nRoadmapItems;
439 }
440 break;
441 }
442 else
443 {
444 // there is an item with this index in the roadmap - does it match what is requested by
445 // the respective state in the active path?
446 RoadmapTypes::ItemId nPresentItemId = m_xAssistant->get_page_ident(nItemIndex).toInt32();
447 WizardTypes::WizardState nRequiredState = rActivePath[ nItemIndex ];
448 if ( nPresentItemId != nRequiredState )
449 {
450 m_xAssistant->set_page_title(OString::number(nPresentItemId), "");
451 bInsertItem = true;
452 }
453 }
454 }
455 else
456 {
457 DBG_ASSERT( bNeedItem, "RoadmapWizard::implUpdateRoadmap: ehm - none needed, none present - why did the loop not terminate?" );
458 bInsertItem = bNeedItem;
459 }
460
461 WizardTypes::WizardState nState( rActivePath[ nItemIndex ] );
462
463 if ( bInsertItem )
464 {
466 }
467
468 OString sIdent(OString::number(nState));
469 m_xAssistant->set_page_index(sIdent, nItemIndex);
470 m_xAssistant->set_page_title(sIdent, getStateDisplayName(nState));
471
472 // if the item is *after* the current state, but the current page does not
473 // allow advancing, the disable the state. This relieves derived classes
474 // from disabling all future states just because the current state does not
475 // (yet) allow advancing.
476 const bool bUnconditionedDisable = !bCurrentPageCanAdvance && ( nItemIndex > nCurrentStatePathIndex );
477 const bool bEnable = !bUnconditionedDisable && ( m_pImpl->aDisabledStates.find( nState ) == m_pImpl->aDisabledStates.end() );
478 m_xAssistant->set_page_sensitive(sIdent, bEnable);
479 }
480 }
481
483 {
484 sal_Int32 nCurrentStatePathIndex = -1;
485
486 Paths::const_iterator aActivePathPos = m_xRoadmapImpl->aPaths.find( m_xRoadmapImpl->nActivePath );
487 if ( aActivePathPos != m_xRoadmapImpl->aPaths.end() )
488 nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( _nCurrentState, aActivePathPos->second );
489
490 DBG_ASSERT( nCurrentStatePathIndex != -1, "RoadmapWizard::determineNextState: ehm - how can we travel if there is no (valid) active path?" );
491 if ( nCurrentStatePathIndex == -1 )
492 return WZS_INVALID_STATE;
493
494 sal_Int32 nNextStateIndex = nCurrentStatePathIndex + 1;
495
496 while ( ( nNextStateIndex < static_cast<sal_Int32>(aActivePathPos->second.size()) )
497 && ( m_xRoadmapImpl->aDisabledStates.find( aActivePathPos->second[ nNextStateIndex ] ) != m_xRoadmapImpl->aDisabledStates.end() )
498 )
499 {
500 ++nNextStateIndex;
501 }
502
503 if ( nNextStateIndex >= static_cast<sal_Int32>(aActivePathPos->second.size()) )
504 // there is no next state in the current path (at least none which is enabled)
505 return WZS_INVALID_STATE;
506
507 return aActivePathPos->second[ nNextStateIndex ];
508 }
509
511 {
512 sal_Int32 nCurrentStatePathIndex = -1;
513
514 Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath );
515 if ( aActivePathPos != m_pImpl->aPaths.end() )
516 nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( _nCurrentState, aActivePathPos->second );
517
518 DBG_ASSERT( nCurrentStatePathIndex != -1, "RoadmapWizard::determineNextState: ehm - how can we travel if there is no (valid) active path?" );
519 if ( nCurrentStatePathIndex == -1 )
520 return WZS_INVALID_STATE;
521
522 sal_Int32 nNextStateIndex = nCurrentStatePathIndex + 1;
523
524 while ( ( nNextStateIndex < static_cast<sal_Int32>(aActivePathPos->second.size()) )
525 && ( m_pImpl->aDisabledStates.find( aActivePathPos->second[ nNextStateIndex ] ) != m_pImpl->aDisabledStates.end() )
526 )
527 {
528 ++nNextStateIndex;
529 }
530
531 if ( nNextStateIndex >= static_cast<sal_Int32>(aActivePathPos->second.size()) )
532 // there is no next state in the current path (at least none which is enabled)
533 return WZS_INVALID_STATE;
534
535 return aActivePathPos->second[ nNextStateIndex ];
536 }
537
539 {
540 if ( !m_pImpl->bActivePathIsDefinite )
541 {
542 // check how many paths are still allowed
543 const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
544
545 // if current path has only the base item, it is not possible to proceed without activating another path
546 if(rActivePath.size()<=1)
547 return false;
548
549 sal_Int32 nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
550
551 size_t nPossiblePaths(0);
552 for (auto const& path : m_pImpl->aPaths)
553 {
554 // the index from which on both paths differ
555 sal_Int32 nDivergenceIndex = RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
556
557 if ( nDivergenceIndex > nCurrentStatePathIndex )
558 // this path is still a possible path
559 nPossiblePaths += 1;
560 }
561
562 // if we have more than one path which is still possible, then we assume
563 // to always have a next state. Though there might be scenarios where this
564 // is not true, but this is too sophisticated (means not really needed) right now.
565 if ( nPossiblePaths > 1 )
566 return true;
567 }
568
569 const WizardPath& rPath = m_pImpl->aPaths[ m_pImpl->nActivePath ];
570 return *rPath.rbegin() != getCurrentState();
571 }
572
574 {
576
577 // disable the "Previous" button if all states in our history are disabled
578 std::vector< WizardTypes::WizardState > aHistory;
579 getStateHistory( aHistory );
580 bool bHaveEnabledState = false;
581 for (auto const& state : aHistory)
582 {
583 if ( isStateEnabled(state) )
584 {
585 bHaveEnabledState = true;
586 break;
587 }
588 }
589
590 enableButtons( WizardButtonFlags::PREVIOUS, bHaveEnabledState );
591
593 }
594
595 IMPL_LINK_NOARG(RoadmapWizard, OnRoadmapItemSelected, LinkParamNone*, void)
596 {
597 RoadmapTypes::ItemId nCurItemId = m_xRoadmapImpl->pRoadmap->GetCurrentRoadmapItemID();
598 if ( nCurItemId == getCurrentState() )
599 // nothing to do
600 return;
601
602 if ( isTravelingSuspended() )
603 return;
604
605 RoadmapWizardTravelSuspension aTravelGuard( *this );
606
607 sal_Int32 nCurrentIndex = m_xRoadmapImpl->getStateIndexInPath( getCurrentState(), m_xRoadmapImpl->nActivePath );
608 sal_Int32 nNewIndex = m_xRoadmapImpl->getStateIndexInPath( nCurItemId, m_xRoadmapImpl->nActivePath );
609
610 DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ),
611 "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
612 if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) )
613 {
614 return;
615 }
616
617 bool bResult = true;
618 if ( nNewIndex > nCurrentIndex )
619 {
620 bResult = skipUntil( static_cast<WizardTypes::WizardState>(nCurItemId) );
621 WizardTypes::WizardState nTemp = static_cast<WizardTypes::WizardState>(nCurItemId);
622 while( nTemp )
623 {
624 if( m_xRoadmapImpl->aDisabledStates.find( --nTemp ) != m_xRoadmapImpl->aDisabledStates.end() )
625 removePageFromHistory( nTemp );
626 }
627 }
628 else
629 bResult = skipBackwardUntil( static_cast<WizardTypes::WizardState>(nCurItemId) );
630
631 if ( !bResult )
632 m_xRoadmapImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() );
633 }
634
635 IMPL_LINK(RoadmapWizardMachine, OnRoadmapItemSelected, const OString&, rCurItemId, bool)
636 {
637 int nCurItemId = rCurItemId.toInt32();
638
639 if ( nCurItemId == getCurrentState() )
640 // nothing to do
641 return false;
642
643 if ( isTravelingSuspended() )
644 return false;
645
646 WizardTravelSuspension aTravelGuard( *this );
647
648 sal_Int32 nCurrentIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath );
649 sal_Int32 nNewIndex = m_pImpl->getStateIndexInPath( nCurItemId, m_pImpl->nActivePath );
650
651 DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ),
652 "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
653 if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) )
654 {
655 return false;
656 }
657
658 bool bResult = true;
659 if ( nNewIndex > nCurrentIndex )
660 {
661 bResult = skipUntil( static_cast<WizardTypes::WizardState>(nCurItemId) );
662 WizardTypes::WizardState nTemp = static_cast<WizardTypes::WizardState>(nCurItemId);
663 while( nTemp )
664 {
665 if( m_pImpl->aDisabledStates.find( --nTemp ) != m_pImpl->aDisabledStates.end() )
666 removePageFromHistory( nTemp );
667 }
668 }
669 else
670 bResult = skipBackwardUntil( static_cast<WizardTypes::WizardState>(nCurItemId) );
671
672 return bResult;
673 }
674
676 {
677 // synchronize the roadmap
679 m_xRoadmapImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() );
680 }
681
683 {
684 WizardMachine::enterState( _nState );
685
686 // synchronize the roadmap
688 }
689
691 {
692 OUString sDisplayName;
693
694 StateDescriptions::const_iterator pos = m_xRoadmapImpl->aStateDescriptors.find( _nState );
695 OSL_ENSURE( pos != m_xRoadmapImpl->aStateDescriptors.end(),
696 "RoadmapWizard::getStateDisplayName: no default implementation available for this state!" );
697 if ( pos != m_xRoadmapImpl->aStateDescriptors.end() )
698 sDisplayName = pos->second.first;
699
700 return sDisplayName;
701 }
702
704 {
705 OUString sDisplayName;
706
707 StateDescriptions::const_iterator pos = m_pImpl->aStateDescriptors.find( _nState );
708 OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(),
709 "RoadmapWizard::getStateDisplayName: no default implementation available for this state!" );
710 if ( pos != m_pImpl->aStateDescriptors.end() )
711 sDisplayName = pos->second.first;
712
713 return sDisplayName;
714 }
715
717 {
718 VclPtr<TabPage> pPage;
719
720 StateDescriptions::const_iterator pos = m_xRoadmapImpl->aStateDescriptors.find( _nState );
721 OSL_ENSURE( pos != m_xRoadmapImpl->aStateDescriptors.end(),
722 "RoadmapWizard::createPage: no default implementation available for this state!" );
723 if ( pos != m_xRoadmapImpl->aStateDescriptors.end() )
724 {
725 RoadmapPageFactory pFactory = pos->second.second;
726 pPage = (*pFactory)( *this );
727 }
728
729 return pPage;
730 }
731
733 {
734 // remember this (in case the state appears in the roadmap later on)
735 if ( _bEnable )
736 m_pImpl->aDisabledStates.erase( _nState );
737 else
738 {
739 m_pImpl->aDisabledStates.insert( _nState );
740 removePageFromHistory( _nState );
741 }
742
743 // if the state is currently in the roadmap, reflect it's new status
744 m_xAssistant->set_page_sensitive(OString::number(_nState), _bEnable);
745 }
746
748 {
749 for (auto const& path : m_pImpl->aPaths)
750 {
751 for (auto const& state : path.second)
752 {
753 if ( state == i_nState )
754 return true;
755 }
756 }
757 return false;
758 }
759
761 {
762 return m_pImpl->aDisabledStates.find( _nState ) == m_pImpl->aDisabledStates.end();
763 }
764
765 void RoadmapWizard::InsertRoadmapItem(int nItemIndex, const OUString& rText, int nItemId, bool bEnable)
766 {
767 m_xRoadmapImpl->pRoadmap->InsertRoadmapItem(nItemIndex, rText, nItemId, bEnable);
768 }
769
770 void RoadmapWizard::SelectRoadmapItemByID(int nItemId, bool bGrabFocus)
771 {
772 m_xRoadmapImpl->pRoadmap->SelectRoadmapItemByID(nItemId, bGrabFocus);
773 }
774
776 {
777 while (m_xRoadmapImpl->pRoadmap->GetItemCount())
778 m_xRoadmapImpl->pRoadmap->DeleteRoadmapItem(0);
779 }
780
782 {
783 m_xRoadmapImpl->pRoadmap->SetItemSelectHdl(_rHdl);
784 }
785
787 {
788 return m_xRoadmapImpl->pRoadmap->GetCurrentRoadmapItemID();
789 }
790
792 {
794 }
795
796} // namespace vcl
797
798/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
InitFlag
Definition: dialog.hxx:44
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
Definition: dialog.cxx:620
static std::unique_ptr< UIObject > create(vcl::Window *pWindow)
void setHeight(tools::Long nHeight)
void SetPriority(TaskPriority ePriority)
Definition: scheduler.cxx:597
void Stop()
Definition: scheduler.cxx:590
void SetInvokeHandler(const Link< Timer *, void > &rLink)
Definition: timer.hxx:56
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: vclptr.hxx:58
void disposeAndClear()
Definition: vclptr.hxx:200
void clear()
Definition: vclptr.hxx:190
virtual bool canAdvance() const =0
determines whether or not it is allowed to advance to a next page
is - no, not a wizard for a roadmap, but the base class for wizards supporting a roadmap.
void declarePath(RoadmapWizardTypes::PathId _nPathId, const RoadmapWizardTypes::WizardPath &_lWizardStates)
declares a valid path in the wizard
std::unique_ptr< RoadmapWizardImpl > m_pImpl
virtual OUString getStateDisplayName(WizardTypes::WizardState nState) const
returns a human readable name for a given state
void activatePath(RoadmapWizardTypes::PathId _nPathId, bool _bDecideForIt=false)
activates a path which has previously been declared with <member>declarePath</member>
virtual void enterState(WizardTypes::WizardState nState) override
will be called when a new page is about to be displayed
bool isStateEnabled(WizardTypes::WizardState nState) const
bool knowsState(WizardTypes::WizardState nState) const
returns true if and only if the given state is known in at least one declared path
void SetRoadmapHelpId(const OString &_rId)
virtual bool canAdvance() const override
determines whether there is a next state to which we can advance
VCL_DLLPRIVATE void implUpdateRoadmap()
updates the roadmap control to show the given path, as far as possible (modulo conflicts with other p...
virtual void updateTravelUI() override
updates the user interface which deals with traveling in the wizard
virtual WizardTypes::WizardState determineNextState(WizardTypes::WizardState nCurrentState) const override
determine the next state to travel from the given one
void enableState(WizardTypes::WizardState nState, bool _bEnable=true)
en- or disables a state
virtual ~RoadmapWizardMachine() override
RoadmapWizardMachine(weld::Window *_pParent)
helper class to temporarily suspend any traveling in the wizard
Definition: wizdlg.hxx:262
wizard for a roadmap
Definition: wizdlg.hxx:66
VclPtr< OKButton > m_pFinish
Definition: wizdlg.hxx:97
void enterState(WizardTypes::WizardState _nState)
will be called when a new page is about to be displayed
ImplWizPageData * mpFirstPage
Definition: wizdlg.hxx:70
std::unique_ptr< WizardMachineImplData > m_xWizardImpl
Definition: wizdlg.hxx:104
Idle maWizardLayoutIdle
Definition: wizdlg.hxx:68
void ShowRoadmap(bool bShow)
void SetItemSelectHdl(const Link< LinkParamNone *, void > &_rHdl)
std::unique_ptr< RoadmapWizardImpl > m_xRoadmapImpl
Definition: wizdlg.hxx:106
void implUpdateRoadmap()
updates the roadmap control to show the given path, as far as possible (modulo conflicts with other p...
VclPtr< TabPage > createPage(WizardTypes::WizardState nState)
to override to create new pages
VclPtr< PushButton > mpNextBtn
Definition: wizdlg.hxx:74
RoadmapWizard(vcl::Window *pParent, WinBits nStyle=WB_STDDIALOG, InitFlag eFlag=InitFlag::Default)
VclPtr< TabPage > mpCurTabPage
Definition: wizdlg.hxx:72
int GetCurrentRoadmapItemID() const
sal_Int16 mnLeftAlignCount
Definition: wizdlg.hxx:77
void SetLeftAlignedButtonCount(sal_Int16 _nCount)
sets the number of buttons which should be left-aligned.
void SetRoadmapHelpId(const OString &_rId)
void InsertRoadmapItem(int nIndex, const OUString &rLabel, int nId, bool bEnabled)
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
ImplWizButtonData * mpFirstBtn
Definition: wizdlg.hxx:71
void RemoveButton(Button *pButton)
VclPtr< CancelButton > m_pCancel
Definition: wizdlg.hxx:98
bool mbEmptyViewMargin
Definition: wizdlg.hxx:78
WizardTypes::WizardState getCurrentState() const
returns the current state of the machine
Definition: wizdlg.hxx:213
VclPtr< vcl::Window > mpViewWindow
Definition: wizdlg.hxx:75
FactoryFunction GetUITestFactory() const override
void SelectRoadmapItemByID(int nId, bool bGrabFocus=true)
VclPtr< PushButton > mpPrevBtn
Definition: wizdlg.hxx:73
VclPtr< PushButton > m_pNextPage
Definition: wizdlg.hxx:99
WizardTypes::WizardState determineNextState(WizardTypes::WizardState nCurrentState) const
determine the next state to travel from the given one
void RemovePage(TabPage *pPage)
sal_uInt16 mnCurLevel
Definition: wizdlg.hxx:76
VclPtr< PushButton > m_pPrevPage
Definition: wizdlg.hxx:100
VclPtr< HelpButton > m_pHelp
Definition: wizdlg.hxx:101
OUString getStateDisplayName(WizardTypes::WizardState nState) const
returns a human readable name for a given state
virtual ~RoadmapWizard() override
TabPage * GetPage(sal_uInt16 nLevel) const
void implConstruct(const WizardButtonFlags _nButtonFlags)
Point LogicToPixel(const Point &rLogicPt) const
Definition: window3.cxx:131
virtual Size GetSizePixel() const
Definition: window.cxx:2404
implements some kind of finite automata, where the states of the automata exactly correlate with tab ...
virtual void updateTravelUI()
updates the user interface which deals with traveling in the wizard
void getStateHistory(std::vector< WizardTypes::WizardState > &out_rHistory)
retrieves a copy of the state history, i.e.
void enableButtons(WizardButtonFlags _nWizardButtonFlags, bool _bEnable)
enable (or disable) buttons
virtual IWizardPageController * getPageController(BuilderPage *pCurrentPage) const
BuilderPage * GetOrCreatePage(const WizardTypes::WizardState i_nState)
virtual void enterState(WizardTypes::WizardState _nState)
will be called when a new page is about to be displayed
WizardTypes::WizardState getCurrentState() const
returns the current state of the machine
void removePageFromHistory(WizardTypes::WizardState nToRemove)
removes a page from the history.
BuilderPage * GetPage(WizardTypes::WizardState eState) const
helper class to temporarily suspend any traveling in the wizard
std::unique_ptr< weld::Assistant > m_xAssistant
Definition: weld.hxx:2608
#define DBG_ASSERT(sCon, aError)
sal_Int32 nState
OUString sDisplayName
std::function< std::unique_ptr< UIObject >(vcl::Window *)> FactoryFunction
int i
PREVIOUS
VclPtr< TabPage >(* RoadmapPageFactory)(RoadmapWizard &)
Definition: wizdlg.hxx:42
::std::vector< WizardTypes::WizardState > WizardPath
sal_Int16 WizardState
IMPL_LINK(ORoadmap, ImplClickHdl, HyperLabel *, CurHyperLabel, void)
Definition: roadmap.cxx:634
IMPL_LINK_NOARG(QuickSelectionEngine_Data, SearchStringTimeout, Timer *, void)
VclPtr< Button > mpButton
Definition: wizimpldata.hxx:34
VclPtr< TabPage > mpPage
Definition: wizdlg.hxx:32
sal_Int32 ItemIndex
Definition: roadmap.hxx:41
sal_Int16 ItemId
Definition: roadmap.hxx:40
StateDescriptions aStateDescriptors
ScopedVclPtr< ORoadmap > pRoadmap
static sal_Int32 getStateIndexInPath(WizardTypes::WizardState _nState, const WizardPath &_rPath)
returns the index of the current state in given path, or -1
static sal_Int32 getFirstDifferentIndex(const WizardPath &_rLHS, const WizardPath &_rRHS)
returns the index of the first state in which the two given paths differ
OUString VclResId(TranslateId aId)
Definition: svdata.cxx:260
@ RESIZE
Resize runs before repaint, so we won't paint twice.
NEXT
WizardButtonFlags
Definition: vclenum.hxx:257
sal_Int64 WinBits
WinBits const WB_TABSTOP
#define WZS_INVALID_STATE
size_t pos