make WizardShell use RoadmapWizardMachine

Change-Id: Id7e1e163f17cd4866c37bbd6cad73b8c721f4dae
Reviewed-on: https://gerrit.libreoffice.org/78969
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/vcl/roadmapwizard.hxx b/include/vcl/roadmapwizard.hxx
index a720cce..6a55bac 100644
--- a/include/vcl/roadmapwizard.hxx
+++ b/include/vcl/roadmapwizard.hxx
@@ -157,6 +157,10 @@ namespace vcl
        */
        void    enableState(WizardTypes::WizardState nState, bool _bEnable = true);

        /** returns true if and only if the given state is known in at least one declared path
        */
        bool    knowsState(WizardTypes::WizardState nState) const;

        // WizardMachine overriables
        virtual void            enterState(WizardTypes::WizardState nState) override;

diff --git a/svtools/UIConfig_svt.mk b/svtools/UIConfig_svt.mk
index 44963c3..dd4744f 100644
--- a/svtools/UIConfig_svt.mk
+++ b/svtools/UIConfig_svt.mk
@@ -12,6 +12,7 @@ $(eval $(call gb_UIConfig_UIConfig,svt))
$(eval $(call gb_UIConfig_add_uifiles,svt,\
	svtools/uiconfig/ui/addresstemplatedialog \
	svtools/uiconfig/ui/datewindow \
	svtools/uiconfig/ui/emptypage \
	svtools/uiconfig/ui/fileviewmenu \
	svtools/uiconfig/ui/graphicexport \
	svtools/uiconfig/ui/inputbox \
diff --git a/svtools/source/uno/wizard/unowizard.cxx b/svtools/source/uno/wizard/unowizard.cxx
index d52a69b..856d0ba 100644
--- a/svtools/source/uno/wizard/unowizard.cxx
+++ b/svtools/source/uno/wizard/unowizard.cxx
@@ -247,10 +247,10 @@ namespace {

    svt::OGenericUnoDialog::Dialog Wizard::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
    {
        VclPtrInstance<WizardShell> pDialog(VCLUnoHelper::GetWindow(rParent), m_xController, m_aWizardSteps);
        pDialog->SetHelpId(  lcl_getHelpId( m_sHelpURL ) );
        pDialog->setTitleBase( m_sTitle );
        return OGenericUnoDialog::Dialog(pDialog);
        auto xDialog = std::make_unique<WizardShell>(Application::GetFrameWeld(rParent), m_xController, m_aWizardSteps);
        xDialog->set_help_id(lcl_getHelpId(m_sHelpURL));
        xDialog->setTitleBase( m_sTitle );
        return OGenericUnoDialog::Dialog(std::move(xDialog));
    }

    OUString SAL_CALL Wizard::getImplementationName()
@@ -258,26 +258,22 @@ namespace {
        return "com.sun.star.comp.svtools.uno.Wizard";
    }


    Sequence< OUString > SAL_CALL Wizard::getSupportedServiceNames()
    {
        Sequence< OUString > aServices { "com.sun.star.ui.dialogs.Wizard" };
        return aServices;
    }


    Reference< XPropertySetInfo > SAL_CALL Wizard::getPropertySetInfo()
    {
        return createPropertySetInfo( getInfoHelper() );
    }


    ::cppu::IPropertyArrayHelper& SAL_CALL Wizard::getInfoHelper()
    {
        return *getArrayHelper();
    }


    ::cppu::IPropertyArrayHelper* Wizard::createArrayHelper( ) const
    {
        Sequence< Property > aProps;
@@ -285,7 +281,6 @@ namespace {
        return new ::cppu::OPropertyArrayHelper( aProps );
    }


    OUString SAL_CALL Wizard::getHelpURL()
    {
        SolarMutexGuard aSolarGuard;
@@ -297,7 +292,6 @@ namespace {
        return lcl_getHelpURL(m_aDialog.get_help_id());
    }


    void SAL_CALL Wizard::setHelpURL( const OUString& i_HelpURL )
    {
        SolarMutexGuard aSolarGuard;
@@ -309,71 +303,65 @@ namespace {
            m_aDialog.set_help_id(lcl_getHelpId(i_HelpURL));
    }


    Reference< XWindow > SAL_CALL Wizard::getDialogWindow()
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        ENSURE_OR_RETURN( m_aDialog.m_xVclDialog, "Wizard::getDialogWindow: illegal call (execution did not start, yet)!", nullptr );
        return Reference< XWindow >( m_aDialog.m_xVclDialog->GetComponentInterface(), UNO_QUERY );
        ENSURE_OR_RETURN( m_aDialog.m_xWeldDialog, "Wizard::getDialogWindow: illegal call (execution did not start, yet)!", nullptr );
        return m_aDialog.m_xWeldDialog->getDialog()->GetXWindow();
    }


    void SAL_CALL Wizard::enableButton( ::sal_Int16 i_WizardButton, sal_Bool i_Enable )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::enableButtons: invalid dialog implementation!" );

        pWizardImpl->enableButtons( lcl_convertWizardButtonToWZB( i_WizardButton ), i_Enable );
    }


    void SAL_CALL Wizard::setDefaultButton( ::sal_Int16 i_WizardButton )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::setDefaultButton: invalid dialog implementation!" );

        pWizardImpl->defaultButton( lcl_convertWizardButtonToWZB( i_WizardButton ) );
    }


    sal_Bool SAL_CALL Wizard::travelNext(  )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::travelNext: invalid dialog implementation!" );

        return pWizardImpl->travelNext();
    }


    sal_Bool SAL_CALL Wizard::travelPrevious(  )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::travelPrevious: invalid dialog implementation!" );

        return pWizardImpl->travelPrevious();
    }


    void SAL_CALL Wizard::enablePage( ::sal_Int16 i_PageID, sal_Bool i_Enable )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::enablePage: invalid dialog implementation!" );

        if ( !pWizardImpl->knowsPage( i_PageID ) )
@@ -385,55 +373,50 @@ namespace {
        pWizardImpl->enablePage( i_PageID, i_Enable );
    }


    void SAL_CALL Wizard::updateTravelUI(  )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::updateTravelUI: invalid dialog implementation!" );

        pWizardImpl->updateTravelUI();
    }


    sal_Bool SAL_CALL Wizard::advanceTo( ::sal_Int16 i_PageId )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::advanceTo: invalid dialog implementation!" );

        return pWizardImpl->advanceTo( i_PageId );
    }


    sal_Bool SAL_CALL Wizard::goBackTo( ::sal_Int16 i_PageId )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::goBackTo: invalid dialog implementation!" );

        return pWizardImpl->goBackTo( i_PageId );
    }


    Reference< XWizardPage > SAL_CALL Wizard::getCurrentPage(  )
    {
        SolarMutexGuard aSolarGuard;
        ::osl::MutexGuard aGuard( m_aMutex );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN( pWizardImpl, "Wizard::getCurrentPage: invalid dialog implementation!", Reference< XWizardPage >() );

        return pWizardImpl->getCurrentWizardPage();
    }


    void SAL_CALL Wizard::activatePath( ::sal_Int16 i_PathIndex, sal_Bool i_Final )
    {
        SolarMutexGuard aSolarGuard;
@@ -442,25 +425,22 @@ namespace {
        if ( ( i_PathIndex < 0 ) || ( i_PathIndex >= m_aWizardSteps.getLength() ) )
            throw NoSuchElementException( OUString(), *this );

        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xVclDialog.get() );
        WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_aDialog.m_xWeldDialog.get() );
        ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::activatePath: invalid dialog implementation!" );

        pWizardImpl->activatePath( i_PathIndex, i_Final );
    }


    void SAL_CALL Wizard::setTitle( const OUString& i_Title )
    {
        // simply disambiguate
        Wizard_Base::OGenericUnoDialog::setTitle( i_Title );
    }


    ::sal_Int16 SAL_CALL Wizard::execute(  )
    {
        return Wizard_Base::OGenericUnoDialog::execute();
    }

}

extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
diff --git a/svtools/source/uno/wizard/wizardpagecontroller.cxx b/svtools/source/uno/wizard/wizardpagecontroller.cxx
index 5c5a4a7..35f3d17 100644
--- a/svtools/source/uno/wizard/wizardpagecontroller.cxx
+++ b/svtools/source/uno/wizard/wizardpagecontroller.cxx
@@ -45,7 +45,7 @@ namespace svt { namespace uno
    //= WizardPageController


    WizardPageController::WizardPageController( WizardShell& i_rParent, const Reference< XWizardController >& i_rController,
    WizardPageController::WizardPageController( TabPageParent aParent, const Reference< XWizardController >& i_rController,
            const sal_Int16 i_nPageId )
        :m_xController( i_rController )
        ,m_xWizardPage()
@@ -53,10 +53,8 @@ namespace svt { namespace uno
        ENSURE_OR_THROW( m_xController.is(), "no controller" );
        try
        {
            m_xWizardPage.set( m_xController->createPage(
                Reference< XWindow >( i_rParent.GetComponentInterface(), UNO_QUERY_THROW ),
                i_nPageId
            ), UNO_SET_THROW );
            // Plug a toplevel SalFrame into the native page which can host our awt widgetry
            m_xWizardPage.set(m_xController->createPage(aParent.pPage->CreateChildFrame(), i_nPageId), UNO_SET_THROW);

            Reference< XWindow > xPageWindow( m_xWizardPage->getWindow(), UNO_SET_THROW );
            xPageWindow->setVisible( true );
diff --git a/svtools/source/uno/wizard/wizardpagecontroller.hxx b/svtools/source/uno/wizard/wizardpagecontroller.hxx
index b814213..0ce9f47 100644
--- a/svtools/source/uno/wizard/wizardpagecontroller.hxx
+++ b/svtools/source/uno/wizard/wizardpagecontroller.hxx
@@ -38,7 +38,7 @@ namespace svt { namespace uno
    {
    public:
        WizardPageController(
            WizardShell& i_rParent,
            TabPageParent aParent,
            const css::uno::Reference< css::ui::dialogs::XWizardController >& i_rController,
            const sal_Int16 i_nPageId
        );
diff --git a/svtools/source/uno/wizard/wizardshell.cxx b/svtools/source/uno/wizard/wizardshell.cxx
index 4b8b6e9..6cca747 100644
--- a/svtools/source/uno/wizard/wizardshell.cxx
+++ b/svtools/source/uno/wizard/wizardshell.cxx
@@ -50,10 +50,9 @@ namespace svt { namespace uno
        }
    }


    //= WizardShell
    WizardShell::WizardShell( vcl::Window* i_pParent, const Reference< XWizardController >& i_rController,
            const Sequence< Sequence< sal_Int16 > >& i_rPaths )
    WizardShell::WizardShell(weld::Window* i_pParent, const Reference< XWizardController >& i_rController,
            const Sequence< Sequence< sal_Int16 > >& i_rPaths)
        :WizardShell_Base( i_pParent )
        ,m_xController( i_rController )
        ,m_nFirstPageID( lcl_determineFirstPageID( i_rPaths ) )
@@ -71,22 +70,19 @@ namespace svt { namespace uno
        }

        // create the first page, to know the page size
        TabPage* pStartPage = GetOrCreatePage( impl_pageIdToState( i_rPaths[0][0] ) );
        SetPageSizePixel( pStartPage->GetSizePixel() );
        GetOrCreatePage( impl_pageIdToState( i_rPaths[0][0] ) );
        m_xAssistant->set_current_page(0);

        // some defaults
        SetRoadmapInteractive( true );
        enableAutomaticNextButtonState();
    }


    short WizardShell::Execute()
    short WizardShell::run()
    {
        ActivatePage();
        return WizardShell_Base::Execute();
        return WizardShell_Base::run();
    }


    sal_Int16 WizardShell::convertCommitReasonToTravelType( const CommitPageReason i_eReason )
    {
        switch ( i_eReason )
@@ -176,14 +172,21 @@ namespace svt { namespace uno
    {
        ENSURE_OR_RETURN( m_xController.is(), "WizardShell::createPage: no WizardController!", nullptr );

        std::shared_ptr< WizardPageController > pController( new WizardPageController( *this, m_xController, impl_stateToPageId( i_nState ) ) );
        sal_Int16 nPageId = impl_stateToPageId(i_nState);

        OString sIdent(OString::number(nPageId));
        weld::Container* pPageContainer = m_xAssistant->append_page(sIdent);
        // TODO eventually pass DialogController as distinct argument instead of bundling into TabPageParent
        TabPageParent aParent(pPageContainer, this);

        std::shared_ptr< WizardPageController > pController(new WizardPageController(aParent, m_xController, nPageId));
        VclPtr<TabPage> pPage = pController->getTabPage();
        OSL_ENSURE( pPage, "WizardShell::createPage: illegal tab page!" );
        if ( !pPage )
        if (!pPage)
        {
            // fallback for ill-behaved clients: empty page
            pPage = VclPtr<TabPage>::Create( this, 0 );
            pPage->SetSizePixel(LogicToPixel(Size(280, 185), MapMode(MapUnit::MapAppFont)));
            pPage = VclPtr<vcl::OWizardPage>::Create(aParent, "svt/ui/emptypage.ui", "EmptyPage");
            pPage->SetSizePixel(pPage->LogicToPixel(Size(280, 185), MapMode(MapUnit::MapAppFont)));
        }

        m_aPageControllers[ pPage ] = pController;
diff --git a/svtools/source/uno/wizard/wizardshell.hxx b/svtools/source/uno/wizard/wizardshell.hxx
index f564513..9f6fddc 100644
--- a/svtools/source/uno/wizard/wizardshell.hxx
+++ b/svtools/source/uno/wizard/wizardshell.hxx
@@ -39,18 +39,18 @@ namespace svt { namespace uno

    //= WizardShell

    typedef ::vcl::RoadmapWizard    WizardShell_Base;
    typedef ::vcl::RoadmapWizardMachine WizardShell_Base;
    class WizardShell : public WizardShell_Base
    {
    public:
        WizardShell(
            vcl::Window* _pParent,
            weld::Window* pParent,
            const css::uno::Reference< css::ui::dialogs::XWizardController >& i_rController,
            const css::uno::Sequence< css::uno::Sequence< sal_Int16 > >& i_rPaths
        );

        // Dialog overridables
        virtual short   Execute() override;
        virtual short   run() override;

        // OWizardMachine overridables
        virtual VclPtr<TabPage> createPage( WizardState i_nState ) override;
diff --git a/svtools/uiconfig/ui/emptypage.ui b/svtools/uiconfig/ui/emptypage.ui
new file mode 100644
index 0000000..c793016
--- /dev/null
+++ b/svtools/uiconfig/ui/emptypage.ui
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface domain="svt">
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkBox" id="EmptyPage">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="hexpand">True</property>
    <property name="vexpand">True</property>
    <property name="border_width">6</property>
    <property name="spacing">6</property>
    <child>
      <placeholder/>
    </child>
  </object>
</interface>
diff --git a/vcl/source/control/roadmapwizard.cxx b/vcl/source/control/roadmapwizard.cxx
index b370b49..5011222 100644
--- a/vcl/source/control/roadmapwizard.cxx
+++ b/vcl/source/control/roadmapwizard.cxx
@@ -909,6 +909,19 @@ namespace vcl
        return false;
    }

    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 RoadmapWizard::isStateEnabled( WizardTypes::WizardState _nState ) const
    {
        return m_xRoadmapImpl->aDisabledStates.find( _nState ) == m_xRoadmapImpl->aDisabledStates.end();