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>