chart2/source/controller/inc/dlg_CreationWizard.hxx         |    2 
 compilerplugins/clang/unusedenumconstants.writeonly.results |   10 
 dbaccess/source/ui/inc/WCopyTable.hxx                       |    2 
 dbaccess/source/ui/inc/dbwizsetup.hxx                       |    2 
 extensions/source/abpilot/abspilot.hxx                      |    2 
 sdext/source/minimizer/optimizerdialog.hxx                  |    2 
 solenv/clang-format/excludelist                             |    3 
 svtools/source/uno/wizard/wizardshell.hxx                   |    2 
 sw/source/uibase/inc/mailmergewizard.hxx                    |    2 
 vcl/Library_vcl.mk                                          |    1 
 vcl/inc/wizdlg.hxx                                          |    2 
 vcl/source/control/roadmapwizard.cxx                        |  354 ----------
 vcl/source/control/roadmapwizardmachine.cxx                 |  390 ++++++++++++
 vcl/source/control/wizardmachine.cxx                        |    2 
 14 files changed, 407 insertions(+), 369 deletions(-)

New commits:
commit c854f5aaae575a0570f79a225b80b53ed420578c
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Sun May 18 01:00:33 2025 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Sun May 18 20:38:44 2025 +0200

    vcl: Move RoadmapWizardMachine to own source file
    
    Don't intersperse the method implementations of the weld::Widget
    based RoadmapWizardMachine with those for the vcl::Window based
    RoadmapWizard, but move the RoadmapWizardMachine ones to a separate
    source file, to make the distinction clearer.
    
    Also rename the roadmapwizard.hxx header to roadmapwizardmachine.hxx
    accordingly, as it contains the declaration of the RoadmapWizardMachine
    class whose method implementatons are now in the new source file
    called roadmapwizardmachine.cxx.
    
    Change-Id: I4aa2933c496c0a26a70ef3027f45c87d1a0b61bc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185466
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/chart2/source/controller/inc/dlg_CreationWizard.hxx 
b/chart2/source/controller/inc/dlg_CreationWizard.hxx
index 1c5e3642e491..152545d0bfce 100644
--- a/chart2/source/controller/inc/dlg_CreationWizard.hxx
+++ b/chart2/source/controller/inc/dlg_CreationWizard.hxx
@@ -23,7 +23,7 @@
 #include "TabPageNotifiable.hxx"
 
 #include <rtl/ref.hxx>
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 
 #include <memory>
 
diff --git a/compilerplugins/clang/unusedenumconstants.writeonly.results 
b/compilerplugins/clang/unusedenumconstants.writeonly.results
index cee5a7e9eedd..438324b902d0 100644
--- a/compilerplugins/clang/unusedenumconstants.writeonly.results
+++ b/compilerplugins/clang/unusedenumconstants.writeonly.results
@@ -4242,15 +4242,15 @@ include/vcl/rendercontext/DrawModeFlags.hxx:27
     enum DrawModeFlags Default
 include/vcl/rendercontext/SalLayoutFlags.hxx:37
     enum SalLayoutFlags UnclusteredGlyphs
-include/vcl/roadmapwizard.hxx:38
+include/vcl/roadmapwizardmachine.hxx:38
     enum vcl::RoadmapWizardTypes::PathId COMMON_FIRST_STATE
-include/vcl/roadmapwizard.hxx:39
+include/vcl/roadmapwizardmachine.hxx:39
     enum vcl::RoadmapWizardTypes::PathId COMPLETE
-include/vcl/roadmapwizard.hxx:40
+include/vcl/roadmapwizardmachine.hxx:40
     enum vcl::RoadmapWizardTypes::PathId NO_SETTINGS
-include/vcl/roadmapwizard.hxx:41
+include/vcl/roadmapwizardmachine.hxx:41
     enum vcl::RoadmapWizardTypes::PathId NO_FIELDS
-include/vcl/roadmapwizard.hxx:42
+include/vcl/roadmapwizardmachine.hxx:42
     enum vcl::RoadmapWizardTypes::PathId NO_SETTINGS_NO_FIELDS
 include/vcl/salgtype.hxx:30
     enum DeviceFormat WITH_ALPHA
diff --git a/dbaccess/source/ui/inc/WCopyTable.hxx 
b/dbaccess/source/ui/inc/WCopyTable.hxx
index d3c0672f8e0b..761b2ea3f0a7 100644
--- a/dbaccess/source/ui/inc/WCopyTable.hxx
+++ b/dbaccess/source/ui/inc/WCopyTable.hxx
@@ -26,7 +26,7 @@
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <comphelper/stl_types.hxx>
 #include "TypeInfo.hxx"
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 #include "DExport.hxx"
 #include "WTabPage.hxx"
 #include "FieldDescriptions.hxx"
diff --git a/dbaccess/source/ui/inc/dbwizsetup.hxx 
b/dbaccess/source/ui/inc/dbwizsetup.hxx
index 351762b7d09c..abad4671bf42 100644
--- a/dbaccess/source/ui/inc/dbwizsetup.hxx
+++ b/dbaccess/source/ui/inc/dbwizsetup.hxx
@@ -23,7 +23,7 @@
 #include "IItemSetHelper.hxx"
 #include <tools/urlobj.hxx>
 #include <memory>
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 
 namespace com::sun::star {
     namespace beans {
diff --git a/extensions/source/abpilot/abspilot.hxx 
b/extensions/source/abpilot/abspilot.hxx
index df15fe017260..be556379311a 100644
--- a/extensions/source/abpilot/abspilot.hxx
+++ b/extensions/source/abpilot/abspilot.hxx
@@ -19,7 +19,7 @@
 
 #pragma once
 
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 #include "addresssettings.hxx"
 #include "datasourcehandling.hxx"
 
diff --git a/include/vcl/roadmapwizard.hxx 
b/include/vcl/roadmapwizardmachine.hxx
similarity index 100%
rename from include/vcl/roadmapwizard.hxx
rename to include/vcl/roadmapwizardmachine.hxx
diff --git a/sdext/source/minimizer/optimizerdialog.hxx 
b/sdext/source/minimizer/optimizerdialog.hxx
index 7bc77df76faa..8b3266f9f68d 100644
--- a/sdext/source/minimizer/optimizerdialog.hxx
+++ b/sdext/source/minimizer/optimizerdialog.hxx
@@ -26,7 +26,7 @@
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <com/sun/star/frame/XDispatch.hpp>
 #include <cppuhelper/implbase.hxx>
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 
 #define ITEM_ID_INTRODUCTION            0
 #define ITEM_ID_SLIDES                  1
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index 11409783e3d3..8253f6bb54f4 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -6201,7 +6201,7 @@ include/vcl/prntypes.hxx
 include/vcl/ptrstyle.hxx
 include/vcl/quickselectionengine.hxx
 include/vcl/region.hxx
-include/vcl/roadmapwizard.hxx
+include/vcl/roadmapwizardmachine.hxx
 include/vcl/salctype.hxx
 include/vcl/salgtype.hxx
 include/vcl/salnativewidgets.hxx
@@ -14585,6 +14585,7 @@ vcl/source/control/prgsbar.cxx
 vcl/source/control/quickselectionengine.cxx
 vcl/source/control/roadmap.cxx
 vcl/source/control/roadmapwizard.cxx
+vcl/source/control/roadmapwizardmachine.cxx
 vcl/source/control/scrbar.cxx
 vcl/source/control/slider.cxx
 vcl/source/control/spinbtn.cxx
diff --git a/svtools/source/uno/wizard/wizardshell.hxx 
b/svtools/source/uno/wizard/wizardshell.hxx
index eb2e8150bc7f..f1ee1a2ecaec 100644
--- a/svtools/source/uno/wizard/wizardshell.hxx
+++ b/svtools/source/uno/wizard/wizardshell.hxx
@@ -20,7 +20,7 @@
 #pragma once
 
 #include <com/sun/star/ui/dialogs/XWizardController.hpp>
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 #include <map>
 #include <memory>
 
diff --git a/sw/source/uibase/inc/mailmergewizard.hxx 
b/sw/source/uibase/inc/mailmergewizard.hxx
index 1a6484583d67..4af9feab8a50 100644
--- a/sw/source/uibase/inc/mailmergewizard.hxx
+++ b/sw/source/uibase/inc/mailmergewizard.hxx
@@ -19,7 +19,7 @@
 #ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MAILMERGEWIZARD_HXX
 #define INCLUDED_SW_SOURCE_UIBASE_INC_MAILMERGEWIZARD_HXX
 
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 #include <rtl/ustring.hxx>
 
 class SwView;
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 8e5ecb88778c..123c16c0b641 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -255,6 +255,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/control/prgsbar \
     vcl/source/control/roadmap \
     vcl/source/control/roadmapwizard \
+    vcl/source/control/roadmapwizardmachine \
     vcl/source/control/scrbar \
     vcl/source/control/slider \
     vcl/source/control/spinbtn \
diff --git a/vcl/inc/wizdlg.hxx b/vcl/inc/wizdlg.hxx
index 4bdb1b70fb91..93817246330a 100644
--- a/vcl/inc/wizdlg.hxx
+++ b/vcl/inc/wizdlg.hxx
@@ -22,7 +22,7 @@
 #include <vcl/toolkit/button.hxx>
 #include <vcl/toolkit/dialog.hxx>
 #include <vcl/toolkit/roadmap.hxx>
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 #include <vcl/tabpage.hxx>
 
 #include <map>
diff --git a/vcl/source/control/roadmapwizard.cxx 
b/vcl/source/control/roadmapwizard.cxx
index 443b02436475..89b6b408575f 100644
--- a/vcl/source/control/roadmapwizard.cxx
+++ b/vcl/source/control/roadmapwizard.cxx
@@ -116,13 +116,6 @@ namespace vcl
         m_xRoadmapImpl->pRoadmap->Show();
     }
 
-    RoadmapWizardMachine::RoadmapWizardMachine(weld::Window* pParent)
-        : WizardMachine(pParent, WizardButtonFlags::NEXT | 
WizardButtonFlags::PREVIOUS | WizardButtonFlags::FINISH | 
WizardButtonFlags::CANCEL | WizardButtonFlags::HELP)
-        , m_pImpl( new RoadmapWizardImpl )
-    {
-        m_xAssistant->connect_jump_page(LINK(this, RoadmapWizardMachine, 
OnRoadmapItemSelected));
-    }
-
     void RoadmapWizard::ShowRoadmap(bool bShow)
     {
         m_xRoadmapImpl->pRoadmap->Show(bShow);
@@ -134,10 +127,6 @@ namespace vcl
         disposeOnce();
     }
 
-    RoadmapWizardMachine::~RoadmapWizardMachine()
-    {
-    }
-
     void RoadmapWizard::dispose()
     {
         m_xRoadmapImpl.reset();
@@ -890,64 +879,6 @@ namespace vcl
         m_xWizardImpl->m_bTravelingSuspended = false;
     }
 
-    void RoadmapWizardMachine::SetRoadmapHelpId(const OUString& rId)
-    {
-        m_xAssistant->set_page_side_help_id(rId);
-    }
-
-    void RoadmapWizardMachine::declarePath( PathId _nPathId, const WizardPath& 
_lWizardStates)
-    {
-        m_pImpl->aPaths.emplace( _nPathId, _lWizardStates );
-
-        if ( m_pImpl->aPaths.size() == 1 )
-            // the very first path -> activate it
-            activatePath( _nPathId );
-        else
-            implUpdateRoadmap( );
-    }
-
-    void RoadmapWizardMachine::activatePath( PathId _nPathId, bool 
_bDecideForIt )
-    {
-        if ( ( _nPathId == m_pImpl->nActivePath ) && ( _bDecideForIt == 
m_pImpl->bActivePathIsDefinite ) )
-            // nothing to do
-            return;
-
-        // does the given path exist?
-        Paths::const_iterator aNewPathPos = m_pImpl->aPaths.find( _nPathId );
-        DBG_ASSERT( aNewPathPos != m_pImpl->aPaths.end(), 
"RoadmapWizard::activate: there is no such path!" );
-        if ( aNewPathPos == m_pImpl->aPaths.end() )
-            return;
-
-        // determine the index of the current state in the current path
-        sal_Int32 nCurrentStatePathIndex = -1;
-        if ( m_pImpl->nActivePath != PathId::INVALID )
-            nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( 
getCurrentState(), m_pImpl->nActivePath );
-
-        DBG_ASSERT( static_cast<sal_Int32>(aNewPathPos->second.size()) > 
nCurrentStatePathIndex,
-            "RoadmapWizard::activate: you cannot activate a path which has 
less states than we've already advanced!" );
-            // If this asserts, this for instance means that we are already in 
state number, say, 5
-            // of our current path, and the caller tries to activate a path 
which has less than 5
-            // states
-        if ( static_cast<sal_Int32>(aNewPathPos->second.size()) <= 
nCurrentStatePathIndex )
-            return;
-
-        // assert that the current and the new path are equal, up to 
nCurrentStatePathIndex
-        Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( 
m_pImpl->nActivePath );
-        if ( aActivePathPos != m_pImpl->aPaths.end() )
-        {
-            if ( RoadmapWizardImpl::getFirstDifferentIndex( 
aActivePathPos->second, aNewPathPos->second ) <= nCurrentStatePathIndex )
-            {
-                OSL_FAIL( "RoadmapWizard::activate: you cannot activate a path 
which conflicts with the current one *before* the current state!" );
-                return;
-            }
-        }
-
-        m_pImpl->nActivePath = _nPathId;
-        m_pImpl->bActivePathIsDefinite = _bDecideForIt;
-
-        implUpdateRoadmap( );
-    }
-
     void RoadmapWizard::implUpdateRoadmap( )
     {
         DBG_ASSERT( m_xRoadmapImpl->aPaths.find( m_xRoadmapImpl->nActivePath ) 
!= m_xRoadmapImpl->aPaths.end(),
@@ -1037,112 +968,6 @@ namespace vcl
         m_xRoadmapImpl->pRoadmap->SetRoadmapComplete( !bIncompletePath );
     }
 
-    void RoadmapWizardMachine::implUpdateRoadmap( )
-    {
-
-        DBG_ASSERT( m_pImpl->aPaths.find( m_pImpl->nActivePath ) != 
m_pImpl->aPaths.end(),
-            "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
-        const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] 
);
-
-        sal_Int32 nCurrentStatePathIndex = 
RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
-        if (nCurrentStatePathIndex < 0)
-            return;
-        assert(nCurrentStatePathIndex >= 0 && 
o3tl::make_unsigned(nCurrentStatePathIndex) < rActivePath.size());
-
-        // determine up to which index (in the new path) we have to display 
the items
-        RoadmapTypes::ItemIndex nUpperStepBoundary = 
static_cast<RoadmapTypes::ItemIndex>(rActivePath.size());
-        if ( !m_pImpl->bActivePathIsDefinite )
-        {
-            for (auto const& path : m_pImpl->aPaths)
-            {
-                if ( path.first == m_pImpl->nActivePath )
-                    // it's the path we are just activating -> no need to 
check anything
-                    continue;
-                // the index from which on both paths differ
-                sal_Int32 nDivergenceIndex = 
RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
-                if ( nDivergenceIndex <= nCurrentStatePathIndex )
-                    // they differ in an index which we have already left 
behind us
-                    // -> this is no conflict anymore
-                    continue;
-
-                // the path conflicts with our new path -> don't activate the
-                // *complete* new path, but only up to the step which is 
unambiguous
-                nUpperStepBoundary = nDivergenceIndex;
-            }
-        }
-
-        // can we advance from the current page?
-        bool bCurrentPageCanAdvance = true;
-        BuilderPage* pCurrentPage = GetPage( getCurrentState() );
-        if ( pCurrentPage )
-        {
-            const IWizardPageController* pController = getPageController( 
GetPage( getCurrentState() ) );
-            OSL_ENSURE( pController != nullptr, 
"RoadmapWizard::implUpdateRoadmap: no controller for the current page!" );
-            bCurrentPageCanAdvance = !pController || pController->canAdvance();
-        }
-
-        // now, we have to remove all items after nCurrentStatePathIndex, and 
insert the items from the active
-        // path, up to (excluding) nUpperStepBoundary
-        RoadmapTypes::ItemIndex nRoadmapItems = m_xAssistant->get_n_pages();
-        RoadmapTypes::ItemIndex nLoopUntil = ::std::max( nUpperStepBoundary, 
nRoadmapItems );
-        for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; 
nItemIndex < nLoopUntil; ++nItemIndex )
-        {
-            bool bExistentItem = ( nItemIndex < nRoadmapItems );
-            bool bNeedItem = ( nItemIndex < nUpperStepBoundary );
-
-            bool bInsertItem = false;
-            if ( bExistentItem )
-            {
-                if ( !bNeedItem )
-                {
-                    int nPages = nRoadmapItems;
-                    for (int i = nPages - 1; i >= nItemIndex; --i)
-                    {
-                        
m_xAssistant->set_page_title(m_xAssistant->get_page_ident(i), u""_ustr);
-                        --nRoadmapItems;
-                    }
-                    break;
-                }
-                else
-                {
-                    // there is an item with this index in the roadmap - does 
it match what is requested by
-                    // the respective state in the active path?
-                    RoadmapTypes::ItemId nPresentItemId = 
m_xAssistant->get_page_ident(nItemIndex).toInt32();
-                    WizardTypes::WizardState nRequiredState = rActivePath[ 
nItemIndex ];
-                    if ( nPresentItemId != nRequiredState )
-                    {
-                        
m_xAssistant->set_page_title(OUString::number(nPresentItemId), u""_ustr);
-                        bInsertItem = true;
-                    }
-                }
-            }
-            else
-            {
-                DBG_ASSERT( bNeedItem, "RoadmapWizard::implUpdateRoadmap: ehm 
- none needed, none present - why did the loop not terminate?" );
-                bInsertItem = bNeedItem;
-            }
-
-            WizardTypes::WizardState nState( rActivePath[ nItemIndex ] );
-
-            if ( bInsertItem )
-            {
-                GetOrCreatePage(nState);
-            }
-
-            OUString sIdent(getPageIdentForState(nState));
-            m_xAssistant->set_page_index(sIdent, nItemIndex);
-            m_xAssistant->set_page_title(sIdent, getStateDisplayName(nState));
-
-            // if the item is *after* the current state, but the current page 
does not
-            // allow advancing, the disable the state. This relieves derived 
classes
-            // from disabling all future states just because the current state 
does not
-            // (yet) allow advancing.
-            const bool bUnconditionedDisable = !bCurrentPageCanAdvance && ( 
nItemIndex > nCurrentStatePathIndex );
-            const bool bEnable = !bUnconditionedDisable && ( 
m_pImpl->aDisabledStates.find( nState ) == m_pImpl->aDisabledStates.end() );
-            m_xAssistant->set_page_sensitive(sIdent, bEnable);
-        }
-    }
-
     WizardTypes::WizardState RoadmapWizard::determineNextState( 
WizardTypes::WizardState _nCurrentState ) const
     {
         sal_Int32 nCurrentStatePathIndex = -1;
@@ -1172,91 +997,6 @@ namespace vcl
         return aActivePathPos->second[ nNextStateIndex ];
     }
 
-    WizardTypes::WizardState RoadmapWizardMachine::determineNextState( 
WizardTypes::WizardState _nCurrentState ) const
-    {
-        sal_Int32 nCurrentStatePathIndex = -1;
-
-        Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( 
m_pImpl->nActivePath );
-        if ( aActivePathPos != m_pImpl->aPaths.end() )
-            nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( 
_nCurrentState, aActivePathPos->second );
-
-        DBG_ASSERT( nCurrentStatePathIndex != -1, 
"RoadmapWizard::determineNextState: ehm - how can we travel if there is no 
(valid) active path?" );
-        if (nCurrentStatePathIndex < 0)
-            return WZS_INVALID_STATE;
-        assert(nCurrentStatePathIndex >= 0 && 
o3tl::make_unsigned(nCurrentStatePathIndex) < aActivePathPos->second.size());
-
-        sal_Int32 nNextStateIndex = nCurrentStatePathIndex + 1;
-
-        while   (   ( nNextStateIndex < 
static_cast<sal_Int32>(aActivePathPos->second.size()) )
-                &&  ( m_pImpl->aDisabledStates.find( aActivePathPos->second[ 
nNextStateIndex ] ) != m_pImpl->aDisabledStates.end() )
-                )
-        {
-            ++nNextStateIndex;
-        }
-
-        if ( nNextStateIndex >= 
static_cast<sal_Int32>(aActivePathPos->second.size()) )
-            // there is no next state in the current path (at least none which 
is enabled)
-            return WZS_INVALID_STATE;
-
-        return aActivePathPos->second[ nNextStateIndex ];
-    }
-
-    bool RoadmapWizardMachine::canAdvance() const
-    {
-        if ( !m_pImpl->bActivePathIsDefinite )
-        {
-            // check how many paths are still allowed
-            const WizardPath& rActivePath( m_pImpl->aPaths[ 
m_pImpl->nActivePath ] );
-
-            // if current path has only the base item, it is not possible to 
proceed without activating another path
-            if(rActivePath.size()<=1)
-                return false;
-
-            sal_Int32 nCurrentStatePathIndex = 
RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
-
-            size_t nPossiblePaths(0);
-            for (auto const& path : m_pImpl->aPaths)
-            {
-                // the index from which on both paths differ
-                sal_Int32 nDivergenceIndex = 
RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
-
-                if ( nDivergenceIndex > nCurrentStatePathIndex )
-                    // this path is still a possible path
-                    nPossiblePaths += 1;
-            }
-
-            // if we have more than one path which is still possible, then we 
assume
-            // to always have a next state. Though there might be scenarios 
where this
-            // is not true, but this is too sophisticated (means not really 
needed) right now.
-            if ( nPossiblePaths > 1 )
-                return true;
-        }
-
-        const WizardPath& rPath = m_pImpl->aPaths[ m_pImpl->nActivePath ];
-        return *rPath.rbegin() != getCurrentState();
-    }
-
-    void RoadmapWizardMachine::updateTravelUI()
-    {
-        WizardMachine::updateTravelUI();
-
-        // disable the "Previous" button if all states in our history are 
disabled
-        std::vector< WizardTypes::WizardState > aHistory;
-        getStateHistory( aHistory );
-        bool bHaveEnabledState = false;
-        for (auto const& state : aHistory)
-        {
-            if ( isStateEnabled(state) )
-            {
-                bHaveEnabledState = true;
-                break;
-            }
-        }
-
-        enableButtons( WizardButtonFlags::PREVIOUS, bHaveEnabledState );
-
-        implUpdateRoadmap();
-    }
 
     IMPL_LINK_NOARG(RoadmapWizard, OnRoadmapItemSelected, LinkParamNone*, void)
     {
@@ -1298,46 +1038,6 @@ namespace vcl
             m_xRoadmapImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() 
);
     }
 
-    IMPL_LINK(RoadmapWizardMachine, OnRoadmapItemSelected, const OUString&, 
rCurItemId, bool)
-    {
-        WizardTypes::WizardState nSelectedState = 
getStateFromPageIdent(rCurItemId);
-
-        if (nSelectedState == getCurrentState())
-            // nothing to do
-            return false;
-
-        if ( isTravelingSuspended() )
-            return false;
-
-        WizardTravelSuspension aTravelGuard( *this );
-
-        sal_Int32 nCurrentIndex = m_pImpl->getStateIndexInPath( 
getCurrentState(), m_pImpl->nActivePath );
-        sal_Int32 nNewIndex     = m_pImpl->getStateIndexInPath( 
nSelectedState, m_pImpl->nActivePath );
-
-        DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ),
-            "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
-        if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) )
-        {
-            return false;
-        }
-
-        bool bResult = true;
-        if ( nNewIndex > nCurrentIndex )
-        {
-            bResult = skipUntil(nSelectedState);
-            WizardTypes::WizardState nTemp = nSelectedState;
-            while( nTemp )
-            {
-                if( m_pImpl->aDisabledStates.find( --nTemp ) != 
m_pImpl->aDisabledStates.end() )
-                    removePageFromHistory( nTemp );
-            }
-        }
-        else
-            bResult = skipBackwardUntil(nSelectedState);
-
-        return bResult;
-    }
-
     void RoadmapWizard::enterState(WizardTypes::WizardState /*nState*/)
     {
         // synchronize the roadmap
@@ -1345,14 +1045,6 @@ namespace vcl
         m_xRoadmapImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() );
     }
 
-    void RoadmapWizardMachine::enterState( WizardTypes::WizardState _nState )
-    {
-        WizardMachine::enterState( _nState );
-
-        // synchronize the roadmap
-        implUpdateRoadmap();
-    }
-
     OUString RoadmapWizard::getStateDisplayName( WizardTypes::WizardState 
_nState ) const
     {
         OUString sDisplayName;
@@ -1366,19 +1058,6 @@ namespace vcl
         return sDisplayName;
     }
 
-    OUString RoadmapWizardMachine::getStateDisplayName( 
WizardTypes::WizardState _nState ) const
-    {
-        OUString sDisplayName;
-
-        StateDescriptions::const_iterator pos = 
m_pImpl->aStateDescriptors.find( _nState );
-        OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(),
-            "RoadmapWizard::getStateDisplayName: no default implementation 
available for this state!" );
-        if ( pos != m_pImpl->aStateDescriptors.end() )
-            sDisplayName = pos->second.first;
-
-        return sDisplayName;
-    }
-
     VclPtr<TabPage> RoadmapWizard::createPage( WizardTypes::WizardState 
_nState )
     {
         VclPtr<TabPage> pPage;
@@ -1395,39 +1074,6 @@ namespace vcl
         return pPage;
     }
 
-    void RoadmapWizardMachine::enableState( WizardTypes::WizardState _nState, 
bool _bEnable )
-    {
-        // remember this (in case the state appears in the roadmap later on)
-        if ( _bEnable )
-            m_pImpl->aDisabledStates.erase( _nState );
-        else
-        {
-            m_pImpl->aDisabledStates.insert( _nState );
-            removePageFromHistory( _nState );
-        }
-
-        // if the state is currently in the roadmap, reflect it's new status
-        m_xAssistant->set_page_sensitive(getPageIdentForState(_nState), 
_bEnable);
-    }
-
-    bool RoadmapWizardMachine::knowsState( WizardTypes::WizardState i_nState ) 
const
-    {
-        for (auto const& path : m_pImpl->aPaths)
-        {
-            for (auto const& state : path.second)
-            {
-                if ( state == i_nState )
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    bool RoadmapWizardMachine::isStateEnabled( WizardTypes::WizardState 
_nState ) const
-    {
-        return m_pImpl->aDisabledStates.find( _nState ) == 
m_pImpl->aDisabledStates.end();
-    }
-
     void RoadmapWizard::InsertRoadmapItem(int nItemIndex, const OUString& 
rText, int nItemId, bool bEnable)
     {
         m_xRoadmapImpl->pRoadmap->InsertRoadmapItem(nItemIndex, rText, 
nItemId, bEnable);
diff --git a/vcl/source/control/roadmapwizardmachine.cxx 
b/vcl/source/control/roadmapwizardmachine.cxx
new file mode 100644
index 000000000000..754f0956398b
--- /dev/null
+++ b/vcl/source/control/roadmapwizardmachine.cxx
@@ -0,0 +1,390 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <strings.hrc>
+#include <svdata.hxx>
+#include <wizdlg.hxx>
+
+#include <osl/diagnose.h>
+#include <tools/debug.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
+
+#include <vector>
+
+namespace vcl
+{
+    RoadmapWizardMachine::RoadmapWizardMachine(weld::Window* pParent)
+        : WizardMachine(pParent, WizardButtonFlags::NEXT | 
WizardButtonFlags::PREVIOUS | WizardButtonFlags::FINISH | 
WizardButtonFlags::CANCEL | WizardButtonFlags::HELP)
+        , m_pImpl( new RoadmapWizardImpl )
+    {
+        m_xAssistant->connect_jump_page(LINK(this, RoadmapWizardMachine, 
OnRoadmapItemSelected));
+    }
+
+    RoadmapWizardMachine::~RoadmapWizardMachine()
+    {
+    }
+
+    void RoadmapWizardMachine::SetRoadmapHelpId(const OUString& rId)
+    {
+        m_xAssistant->set_page_side_help_id(rId);
+    }
+
+    void RoadmapWizardMachine::declarePath( PathId _nPathId, const WizardPath& 
_lWizardStates)
+    {
+        m_pImpl->aPaths.emplace( _nPathId, _lWizardStates );
+
+        if ( m_pImpl->aPaths.size() == 1 )
+            // the very first path -> activate it
+            activatePath( _nPathId );
+        else
+            implUpdateRoadmap( );
+    }
+
+    void RoadmapWizardMachine::activatePath( PathId _nPathId, bool 
_bDecideForIt )
+    {
+        if ( ( _nPathId == m_pImpl->nActivePath ) && ( _bDecideForIt == 
m_pImpl->bActivePathIsDefinite ) )
+            // nothing to do
+            return;
+
+        // does the given path exist?
+        Paths::const_iterator aNewPathPos = m_pImpl->aPaths.find( _nPathId );
+        DBG_ASSERT( aNewPathPos != m_pImpl->aPaths.end(), 
"RoadmapWizard::activate: there is no such path!" );
+        if ( aNewPathPos == m_pImpl->aPaths.end() )
+            return;
+
+        // determine the index of the current state in the current path
+        sal_Int32 nCurrentStatePathIndex = -1;
+        if ( m_pImpl->nActivePath != PathId::INVALID )
+            nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( 
getCurrentState(), m_pImpl->nActivePath );
+
+        DBG_ASSERT( static_cast<sal_Int32>(aNewPathPos->second.size()) > 
nCurrentStatePathIndex,
+                   "RoadmapWizard::activate: you cannot activate a path which 
has less states than we've already advanced!" );
+        // If this asserts, this for instance means that we are already in 
state number, say, 5
+        // of our current path, and the caller tries to activate a path which 
has less than 5
+        // states
+        if ( static_cast<sal_Int32>(aNewPathPos->second.size()) <= 
nCurrentStatePathIndex )
+            return;
+
+        // assert that the current and the new path are equal, up to 
nCurrentStatePathIndex
+        Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( 
m_pImpl->nActivePath );
+        if ( aActivePathPos != m_pImpl->aPaths.end() )
+        {
+            if ( RoadmapWizardImpl::getFirstDifferentIndex( 
aActivePathPos->second, aNewPathPos->second ) <= nCurrentStatePathIndex )
+            {
+                OSL_FAIL( "RoadmapWizard::activate: you cannot activate a path 
which conflicts with the current one *before* the current state!" );
+                return;
+            }
+        }
+
+        m_pImpl->nActivePath = _nPathId;
+        m_pImpl->bActivePathIsDefinite = _bDecideForIt;
+
+        implUpdateRoadmap( );
+    }
+
+    void RoadmapWizardMachine::implUpdateRoadmap( )
+    {
+
+        DBG_ASSERT( m_pImpl->aPaths.find( m_pImpl->nActivePath ) != 
m_pImpl->aPaths.end(),
+                   "RoadmapWizard::implUpdateRoadmap: there is no such path!" 
);
+        const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] 
);
+
+        sal_Int32 nCurrentStatePathIndex = 
RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
+        if (nCurrentStatePathIndex < 0)
+            return;
+        assert(nCurrentStatePathIndex >= 0 && 
o3tl::make_unsigned(nCurrentStatePathIndex) < rActivePath.size());
+
+        // determine up to which index (in the new path) we have to display 
the items
+        RoadmapTypes::ItemIndex nUpperStepBoundary = 
static_cast<RoadmapTypes::ItemIndex>(rActivePath.size());
+        if ( !m_pImpl->bActivePathIsDefinite )
+        {
+            for (auto const& path : m_pImpl->aPaths)
+            {
+                if ( path.first == m_pImpl->nActivePath )
+                    // it's the path we are just activating -> no need to 
check anything
+                    continue;
+                // the index from which on both paths differ
+                sal_Int32 nDivergenceIndex = 
RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
+                if ( nDivergenceIndex <= nCurrentStatePathIndex )
+                    // they differ in an index which we have already left 
behind us
+                    // -> this is no conflict anymore
+                    continue;
+
+                // the path conflicts with our new path -> don't activate the
+                // *complete* new path, but only up to the step which is 
unambiguous
+                nUpperStepBoundary = nDivergenceIndex;
+            }
+        }
+
+        // can we advance from the current page?
+        bool bCurrentPageCanAdvance = true;
+        BuilderPage* pCurrentPage = GetPage( getCurrentState() );
+        if ( pCurrentPage )
+        {
+            const IWizardPageController* pController = getPageController( 
GetPage( getCurrentState() ) );
+            OSL_ENSURE( pController != nullptr, 
"RoadmapWizard::implUpdateRoadmap: no controller for the current page!" );
+            bCurrentPageCanAdvance = !pController || pController->canAdvance();
+        }
+
+        // now, we have to remove all items after nCurrentStatePathIndex, and 
insert the items from the active
+        // path, up to (excluding) nUpperStepBoundary
+        RoadmapTypes::ItemIndex nRoadmapItems = m_xAssistant->get_n_pages();
+        RoadmapTypes::ItemIndex nLoopUntil = ::std::max( nUpperStepBoundary, 
nRoadmapItems );
+        for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; 
nItemIndex < nLoopUntil; ++nItemIndex )
+        {
+            bool bExistentItem = ( nItemIndex < nRoadmapItems );
+            bool bNeedItem = ( nItemIndex < nUpperStepBoundary );
+
+            bool bInsertItem = false;
+            if ( bExistentItem )
+            {
+                if ( !bNeedItem )
+                {
+                    int nPages = nRoadmapItems;
+                    for (int i = nPages - 1; i >= nItemIndex; --i)
+                    {
+                        
m_xAssistant->set_page_title(m_xAssistant->get_page_ident(i), u""_ustr);
+                        --nRoadmapItems;
+                    }
+                    break;
+                }
+                else
+                {
+                    // there is an item with this index in the roadmap - does 
it match what is requested by
+                    // the respective state in the active path?
+                    RoadmapTypes::ItemId nPresentItemId = 
m_xAssistant->get_page_ident(nItemIndex).toInt32();
+                    WizardTypes::WizardState nRequiredState = rActivePath[ 
nItemIndex ];
+                    if ( nPresentItemId != nRequiredState )
+                    {
+                        
m_xAssistant->set_page_title(OUString::number(nPresentItemId), u""_ustr);
+                        bInsertItem = true;
+                    }
+                }
+            }
+            else
+            {
+                DBG_ASSERT( bNeedItem, "RoadmapWizard::implUpdateRoadmap: ehm 
- none needed, none present - why did the loop not terminate?" );
+                bInsertItem = bNeedItem;
+            }
+
+            WizardTypes::WizardState nState( rActivePath[ nItemIndex ] );
+
+            if ( bInsertItem )
+            {
+                GetOrCreatePage(nState);
+            }
+
+            OUString sIdent(getPageIdentForState(nState));
+            m_xAssistant->set_page_index(sIdent, nItemIndex);
+            m_xAssistant->set_page_title(sIdent, getStateDisplayName(nState));
+
+            // if the item is *after* the current state, but the current page 
does not
+            // allow advancing, the disable the state. This relieves derived 
classes
+            // from disabling all future states just because the current state 
does not
+            // (yet) allow advancing.
+            const bool bUnconditionedDisable = !bCurrentPageCanAdvance && ( 
nItemIndex > nCurrentStatePathIndex );
+            const bool bEnable = !bUnconditionedDisable && ( 
m_pImpl->aDisabledStates.find( nState ) == m_pImpl->aDisabledStates.end() );
+            m_xAssistant->set_page_sensitive(sIdent, bEnable);
+        }
+    }
+
+    WizardTypes::WizardState RoadmapWizardMachine::determineNextState( 
WizardTypes::WizardState _nCurrentState ) const
+    {
+        sal_Int32 nCurrentStatePathIndex = -1;
+
+        Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( 
m_pImpl->nActivePath );
+        if ( aActivePathPos != m_pImpl->aPaths.end() )
+            nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( 
_nCurrentState, aActivePathPos->second );
+
+        DBG_ASSERT( nCurrentStatePathIndex != -1, 
"RoadmapWizard::determineNextState: ehm - how can we travel if there is no 
(valid) active path?" );
+        if (nCurrentStatePathIndex < 0)
+            return WZS_INVALID_STATE;
+        assert(nCurrentStatePathIndex >= 0 && 
o3tl::make_unsigned(nCurrentStatePathIndex) < aActivePathPos->second.size());
+
+        sal_Int32 nNextStateIndex = nCurrentStatePathIndex + 1;
+
+        while   (   ( nNextStateIndex < 
static_cast<sal_Int32>(aActivePathPos->second.size()) )
+               &&  ( m_pImpl->aDisabledStates.find( aActivePathPos->second[ 
nNextStateIndex ] ) != m_pImpl->aDisabledStates.end() )
+               )
+        {
+            ++nNextStateIndex;
+        }
+
+        if ( nNextStateIndex >= 
static_cast<sal_Int32>(aActivePathPos->second.size()) )
+            // there is no next state in the current path (at least none which 
is enabled)
+            return WZS_INVALID_STATE;
+
+        return aActivePathPos->second[ nNextStateIndex ];
+    }
+
+    bool RoadmapWizardMachine::canAdvance() const
+    {
+        if ( !m_pImpl->bActivePathIsDefinite )
+        {
+            // check how many paths are still allowed
+            const WizardPath& rActivePath( m_pImpl->aPaths[ 
m_pImpl->nActivePath ] );
+
+            // if current path has only the base item, it is not possible to 
proceed without activating another path
+            if(rActivePath.size()<=1)
+                return false;
+
+            sal_Int32 nCurrentStatePathIndex = 
RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
+
+            size_t nPossiblePaths(0);
+            for (auto const& path : m_pImpl->aPaths)
+            {
+                // the index from which on both paths differ
+                sal_Int32 nDivergenceIndex = 
RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
+
+                if ( nDivergenceIndex > nCurrentStatePathIndex )
+                    // this path is still a possible path
+                    nPossiblePaths += 1;
+            }
+
+            // if we have more than one path which is still possible, then we 
assume
+            // to always have a next state. Though there might be scenarios 
where this
+            // is not true, but this is too sophisticated (means not really 
needed) right now.
+            if ( nPossiblePaths > 1 )
+                return true;
+        }
+
+        const WizardPath& rPath = m_pImpl->aPaths[ m_pImpl->nActivePath ];
+        return *rPath.rbegin() != getCurrentState();
+    }
+
+    void RoadmapWizardMachine::updateTravelUI()
+    {
+        WizardMachine::updateTravelUI();
+
+        // disable the "Previous" button if all states in our history are 
disabled
+        std::vector< WizardTypes::WizardState > aHistory;
+        getStateHistory( aHistory );
+        bool bHaveEnabledState = false;
+        for (auto const& state : aHistory)
+        {
+            if ( isStateEnabled(state) )
+            {
+                bHaveEnabledState = true;
+                break;
+            }
+        }
+
+        enableButtons( WizardButtonFlags::PREVIOUS, bHaveEnabledState );
+
+        implUpdateRoadmap();
+    }
+
+    void RoadmapWizardMachine::enterState( WizardTypes::WizardState _nState )
+    {
+        WizardMachine::enterState( _nState );
+
+        // synchronize the roadmap
+        implUpdateRoadmap();
+    }
+
+    OUString RoadmapWizardMachine::getStateDisplayName( 
WizardTypes::WizardState _nState ) const
+    {
+        OUString sDisplayName;
+
+        StateDescriptions::const_iterator pos = 
m_pImpl->aStateDescriptors.find( _nState );
+        OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(),
+                   "RoadmapWizard::getStateDisplayName: no default 
implementation available for this state!" );
+        if ( pos != m_pImpl->aStateDescriptors.end() )
+            sDisplayName = pos->second.first;
+
+        return sDisplayName;
+    }
+
+    void RoadmapWizardMachine::enableState( WizardTypes::WizardState _nState, 
bool _bEnable )
+    {
+        // remember this (in case the state appears in the roadmap later on)
+        if ( _bEnable )
+            m_pImpl->aDisabledStates.erase( _nState );
+        else
+        {
+            m_pImpl->aDisabledStates.insert( _nState );
+            removePageFromHistory( _nState );
+        }
+
+        // if the state is currently in the roadmap, reflect it's new status
+        m_xAssistant->set_page_sensitive(getPageIdentForState(_nState), 
_bEnable);
+    }
+
+    bool RoadmapWizardMachine::knowsState( WizardTypes::WizardState i_nState ) 
const
+    {
+        for (auto const& path : m_pImpl->aPaths)
+        {
+            for (auto const& state : path.second)
+            {
+                if ( state == i_nState )
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    bool RoadmapWizardMachine::isStateEnabled( WizardTypes::WizardState 
_nState ) const
+    {
+        return m_pImpl->aDisabledStates.find( _nState ) == 
m_pImpl->aDisabledStates.end();
+    }
+
+    IMPL_LINK(RoadmapWizardMachine, OnRoadmapItemSelected, const OUString&, 
rCurItemId, bool)
+    {
+        WizardTypes::WizardState nSelectedState = 
getStateFromPageIdent(rCurItemId);
+
+        if (nSelectedState == getCurrentState())
+            // nothing to do
+            return false;
+
+        if ( isTravelingSuspended() )
+            return false;
+
+        WizardTravelSuspension aTravelGuard( *this );
+
+        sal_Int32 nCurrentIndex = m_pImpl->getStateIndexInPath( 
getCurrentState(), m_pImpl->nActivePath );
+        sal_Int32 nNewIndex     = m_pImpl->getStateIndexInPath( 
nSelectedState, m_pImpl->nActivePath );
+
+        DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ),
+                   "RoadmapWizard::OnRoadmapItemSelected: something's wrong 
here!" );
+        if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) )
+        {
+            return false;
+        }
+
+        bool bResult = true;
+        if ( nNewIndex > nCurrentIndex )
+        {
+            bResult = skipUntil(nSelectedState);
+            WizardTypes::WizardState nTemp = nSelectedState;
+            while( nTemp )
+            {
+                if( m_pImpl->aDisabledStates.find( --nTemp ) != 
m_pImpl->aDisabledStates.end() )
+                    removePageFromHistory( nTemp );
+            }
+        }
+        else
+            bResult = skipBackwardUntil(nSelectedState);
+
+        return bResult;
+    }
+
+}   // namespace vcl
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/source/control/wizardmachine.cxx 
b/vcl/source/control/wizardmachine.cxx
index 0e935e27619a..bf303727fe1b 100644
--- a/vcl/source/control/wizardmachine.cxx
+++ b/vcl/source/control/wizardmachine.cxx
@@ -20,7 +20,7 @@
 #include <comphelper/lok.hxx>
 #include <officecfg/Office/Common.hxx>
 #include <tools/debug.hxx>
-#include <vcl/roadmapwizard.hxx>
+#include <vcl/roadmapwizardmachine.hxx>
 #include <comphelper/diagnose_ex.hxx>
 #include <strings.hrc>
 #include <svdata.hxx>

Reply via email to