Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/vcl/source/control/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 37 kB image not shown  

Quelle  roadmapwizard.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * 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 <tools/debug.hxx>
#include <tools/json_writer.hxx>
#include <osl/diagnose.h>
#include <vcl/event.hxx>

#include <strings.hrc>
#include <svdata.hxx>
#include <wizdlg.hxx>

#include <vector>

#include "wizimpldata.hxx"
#include <uiobject-internal.hxx>

#define WIZARDDIALOG_BUTTON_OFFSET_Y        6
#define WIZARDDIALOG_BUTTON_DLGOFFSET_X     6
#define WIZARDDIALOG_BUTTON_STDOFFSET_X     6
#define WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X 3
#define WIZARDDIALOG_VIEW_DLGOFFSET_X       6
#define WIZARDDIALOG_VIEW_DLGOFFSET_Y       6

namespace vcl
{
    sal_Int32 RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState, const WizardPath& _rPath )
    {
        sal_Int32 nStateIndexInPath = 0;
        for (auto const& path : _rPath)
        {
            if (path == _nState)
                return nStateIndexInPath;
            ++nStateIndexInPath;
        }
        return -1;
    }

    sal_Int32 RoadmapWizardImpl::getStateIndexInPath( WizardTypes::WizardState _nState, PathId _nPathId )
    {
        sal_Int32 nStateIndexInPath = -1;
        Paths::const_iterator aPathPos = aPaths.find( _nPathId );
        if ( aPathPos != aPaths.end( ) )
            nStateIndexInPath = getStateIndexInPath( _nState, aPathPos->second );
        return nStateIndexInPath;
    }

    sal_Int32 RoadmapWizardImpl::getFirstDifferentIndex( const WizardPath& _rLHS, const WizardPath& _rRHS )
    {
        sal_Int32 nMinLength = ::std::min( _rLHS.size(), _rRHS.size() );
        for ( sal_Int32 nCheck = 0; nCheck < nMinLength; ++nCheck )
        {
            if ( _rLHS[ nCheck ] != _rRHS[ nCheck ] )
                return nCheck;
        }
        return nMinLength;
    }

    //= RoadmapWizard
    RoadmapWizard::RoadmapWizard(vcl::Window* pParent, WinBits nStyle, InitFlag eFlag)
        : Dialog(pParent, nStyle, eFlag)
        , maWizardLayoutIdle("vcl RoadmapWizard maWizardLayoutIdle")
        , m_pFinish(nullptr)
        , m_pCancel(nullptr)
        , m_pNextPage(nullptr)
        , m_pPrevPage(nullptr)
        , m_pHelp(nullptr)
        , m_xWizardImpl(new WizardMachineImplData)
        , m_xRoadmapImpl(new RoadmapWizardImpl)
    {
        mpFirstPage     = nullptr;
        mpFirstBtn      = nullptr;
        mpCurTabPage    = nullptr;
        mpPrevBtn       = nullptr;
        mpNextBtn       = nullptr;
        mnCurLevel      = 0;
        mbEmptyViewMargin =  false;
        mnLeftAlignCount = 0;

        maWizardLayoutIdle.SetPriority(TaskPriority::RESIZE);
        maWizardLayoutIdle.SetInvokeHandler( LINK( this, RoadmapWizard, ImplHandleWizardLayoutTimerHdl ) );

        implConstruct();

        SetLeftAlignedButtonCount( 1 );
        mbEmptyViewMargin = true;

        mpRoadmap = VclPtr<ORoadmap>::Create(this, WB_TABSTOP);
        mpRoadmap->SetText( VclResId( STR_WIZDLG_ROADMAP_TITLE ) );
        mpRoadmap->SetPosPixel( Point( 0, 0 ) );
        mpRoadmap->SetItemSelectHdl( LINK( this, RoadmapWizard, OnRoadmapItemSelected ) );

        Size aRoadmapSize = LogicToPixel(Size(85, 0), MapMode(MapUnit::MapAppFont));
        aRoadmapSize.setHeight( GetSizePixel().Height() );
        mpRoadmap->SetSizePixel( aRoadmapSize );

        mpRoadmap->Show();
    }

    void RoadmapWizard::ShowRoadmap(bool bShow)
    {
        mpRoadmap->Show(bShow);
        CalcAndSetSize();
    }

    RoadmapWizard::~RoadmapWizard()
    {
        disposeOnce();
    }

    void RoadmapWizard::dispose()
    {
        m_xRoadmapImpl.reset();

        m_pFinish.disposeAndClear();
        m_pCancel.disposeAndClear();
        m_pNextPage.disposeAndClear();
        m_pPrevPage.disposeAndClear();
        m_pHelp.disposeAndClear();

        if (m_xWizardImpl)
        {
            for (WizardTypes::WizardState i = 0; i < m_xWizardImpl->nFirstUnknownPage; ++i)
            {
                TabPage *pPage = GetPage(i);
                if (pPage)
                    pPage->disposeOnce();
            }
            m_xWizardImpl.reset();
        }

        maWizardLayoutIdle.Stop();

        // Remove all buttons
        while ( mpFirstBtn )
            RemoveButton( mpFirstBtn->mpButton );

        // Remove all pages
        while ( mpFirstPage )
            RemovePage( mpFirstPage->mpPage );

        mpCurTabPage.reset();
        mpPrevBtn.reset();
        mpNextBtn.reset();
        mpRoadmap.disposeAndClear();
        maResponses.clear();
        Dialog::dispose();
    }

    void RoadmapWizard::SetRoadmapHelpId( const OUString& _rId )
    {
        mpRoadmap->SetHelpId( _rId );
    }

    void RoadmapWizard::SetRoadmapBitmap(const BitmapEx& rBmp)
    {
        mpRoadmap->SetRoadmapBitmap(rBmp);
    }

    void RoadmapWizard::SetLeftAlignedButtonCount( sal_Int16 _nCount )
    {
        mnLeftAlignCount = _nCount;
    }

    void RoadmapWizard::ImplCalcSize( Size& rSize )
    {
        // calculate ButtonBar height and width
        tools::Long                nMaxHeight = 0;
        tools::Long                nBarWidth = WIZARDDIALOG_BUTTON_DLGOFFSET_X * 2 + LogicalCoordinateToPixel(6);
        ImplWizButtonData*  pBtnData = mpFirstBtn;
        while (pBtnData)
        {
            auto nBtnHeight = pBtnData->mpButton->GetSizePixel().Height();
            auto nBtnWidth = pBtnData->mpButton->GetSizePixel().Width();
            if (pBtnData->mpButton->IsVisible())
            {
                nBarWidth += nBtnWidth;
                nBarWidth += pBtnData->mnOffset;
            }
            if ( nBtnHeight > nMaxHeight )
                nMaxHeight = nBtnHeight;
            pBtnData = pBtnData->mpNext;
        }
        if ( nMaxHeight )
            nMaxHeight += WIZARDDIALOG_BUTTON_OFFSET_Y*2;
        rSize.AdjustHeight(nMaxHeight);

        // add in the view window size
        if ( mpRoadmap && mpRoadmap->IsVisible() )
        {
            Size aViewSize = mpRoadmap->GetSizePixel();
            // align left
            rSize.AdjustWidth(aViewSize.Width() );
        }

        if (nBarWidth > rSize.Width())
            rSize.setWidth(nBarWidth);
    }

    void RoadmapWizard::queue_resize(StateChangedType /*eReason*/)
    {
        if (maWizardLayoutIdle.IsActive())
            return;
        if (IsInClose())
            return;
        maWizardLayoutIdle.Start();
    }

    IMPL_LINK_NOARG(RoadmapWizard, ImplHandleWizardLayoutTimerHdl, Timer*, void)
    {
        ImplPosCtrls();
        ImplPosTabPage();
    }

    void RoadmapWizard::ImplPosCtrls()
    {
        Size    aDlgSize = GetOutputSizePixel();
        tools::Long    nBtnWidth = 0;
        tools::Long    nMaxHeight = 0;
        tools::Long    nOffY = aDlgSize.Height();

        ImplWizButtonData* pBtnData = mpFirstBtn;
        int j = 0;
        while ( pBtnData )
        {
            if (j >= mnLeftAlignCount)
            {
                Size aBtnSize = pBtnData->mpButton->GetSizePixel();
                tools::Long nBtnHeight = aBtnSize.Height();
                if ( nBtnHeight > nMaxHeight )
                    nMaxHeight = nBtnHeight;
                nBtnWidth += aBtnSize.Width();
                nBtnWidth += pBtnData->mnOffset;
            }
            pBtnData = pBtnData->mpNext;
            j++;
        }

        if ( nMaxHeight )
        {
            tools::Long nOffX = aDlgSize.Width()-nBtnWidth-WIZARDDIALOG_BUTTON_DLGOFFSET_X;
            tools::Long nOffLeftAlignX = LogicalCoordinateToPixel(6);
            nOffY -= WIZARDDIALOG_BUTTON_OFFSET_Y+nMaxHeight;

            pBtnData = mpFirstBtn;
            int i = 0;
            while ( pBtnData )
            {
                Size aBtnSize = pBtnData->mpButton->GetSizePixel();
                if (i >= mnLeftAlignCount)
                {
                    Point aPos( nOffX, nOffY+((nMaxHeight-aBtnSize.Height())/2) );
                    pBtnData->mpButton->SetPosPixel( aPos );
                    nOffX += aBtnSize.Width();
                    nOffX += pBtnData->mnOffset;
                }
                else
                {
                    Point aPos( nOffLeftAlignX, nOffY+((nMaxHeight-aBtnSize.Height())/2) );
                    pBtnData->mpButton->SetPosPixel( aPos );
                    nOffLeftAlignX += aBtnSize.Width();
                    nOffLeftAlignX += pBtnData->mnOffset;
                }

                pBtnData = pBtnData->mpNext;
                i++;
            }

            nOffY -= WIZARDDIALOG_BUTTON_OFFSET_Y;
        }

        if ( !(mpRoadmap && mpRoadmap->IsVisible()) )
            return;

        tools::Long    nViewOffX = 0;
        tools::Long    nViewOffY = 0;
        tools::Long    nViewWidth = 0;
        tools::Long    nViewHeight = 0;
        tools::Long    nDlgHeight = nOffY;
        PosSizeFlags nViewPosFlags = PosSizeFlags::Pos;
        // align left
        {
            if ( mbEmptyViewMargin )
            {
                nViewOffX       = 0;
                nViewOffY       = 0;
                nViewHeight     = nDlgHeight;
            }
            else
            {
                nViewOffX       = WIZARDDIALOG_VIEW_DLGOFFSET_X;
                nViewOffY       = WIZARDDIALOG_VIEW_DLGOFFSET_Y;
                nViewHeight     = nDlgHeight-(WIZARDDIALOG_VIEW_DLGOFFSET_Y*2);
            }
            nViewPosFlags  |= PosSizeFlags::Height;
        }
        mpRoadmap->setPosSizePixel( nViewOffX, nViewOffY,
                                      nViewWidth, nViewHeight,
                                      nViewPosFlags );
    }

    tools::Long RoadmapWizard::LogicalCoordinateToPixel(int iCoordinate) const
    {
        Size aLocSize = LogicToPixel(Size(iCoordinate, 0), MapMode(MapUnit::MapAppFont));
        int iPixelCoordinate =  aLocSize.Width();
        return iPixelCoordinate;
    }

    void RoadmapWizard::ImplPosTabPage()
    {
        if ( !mpCurTabPage )
            return;

        if ( !IsInInitShow() )
        {
            // #100199# - On Unix initial size is equal to screen size, on Windows
            // it's 0,0. One cannot calculate the size unless dialog is visible.
            if ( !IsReallyVisible() )
                return;
        }

        // calculate height of ButtonBar
        tools::Long                nMaxHeight = 0;
        ImplWizButtonData*  pBtnData = mpFirstBtn;
        while ( pBtnData )
        {
            tools::Long nBtnHeight = pBtnData->mpButton->GetSizePixel().Height();
            if ( nBtnHeight > nMaxHeight )
                nMaxHeight = nBtnHeight;
            pBtnData = pBtnData->mpNext;
        }
        if ( nMaxHeight )
            nMaxHeight += WIZARDDIALOG_BUTTON_OFFSET_Y*2;

        // position TabPage
        Size aDlgSize = GetOutputSizePixel();
        aDlgSize.AdjustHeight( -nMaxHeight );
        tools::Long nOffX = 0;
        tools::Long nOffY = 0;
        if ( mpRoadmap && mpRoadmap->IsVisible() )
        {
            Size aViewSize = mpRoadmap->GetSizePixel();
            // align left
            tools::Long nViewOffset = mbEmptyViewMargin ? 0 : WIZARDDIALOG_VIEW_DLGOFFSET_X;
            nOffX += aViewSize.Width() + nViewOffset;
            aDlgSize.AdjustWidth( -nOffX );
        }
        Point aPos( nOffX, nOffY );
        mpCurTabPage->SetPosSizePixel( aPos, aDlgSize );
    }

    void RoadmapWizard::ImplShowTabPage( TabPage* pTabPage )
    {
        if ( mpCurTabPage == pTabPage )
            return;

        TabPage* pOldTabPage = mpCurTabPage;

        mpCurTabPage = pTabPage;
        if ( pTabPage )
        {
            ImplPosTabPage();
            pTabPage->Show();
        }

        if ( pOldTabPage )
            pOldTabPage->Hide();
    }

    TabPage* RoadmapWizard::ImplGetPage( sal_uInt16 nLevel ) const
    {
        sal_uInt16              nTempLevel = 0;
        ImplWizPageData*    pPageData = mpFirstPage;
        while ( pPageData )
        {
            if ( (nTempLevel == nLevel) || !pPageData->mpNext )
                break;

            nTempLevel++;
            pPageData = pPageData->mpNext;
        }

        if ( pPageData )
            return pPageData->mpPage;
        return nullptr;
    }

    void RoadmapWizard::AddButtonResponse( Button* pButton, int response)
    {
        maResponses[pButton] = response;
    }

    void RoadmapWizard::implConstruct()
    {
        m_xWizardImpl->sTitleBase = GetText();

        // create buttons
        // the help button
        m_pHelp= VclPtr<HelpButton>::Create(this, WB_TABSTOP);
        m_pHelp->SetSizePixel(LogicToPixel(Size(50, 14), MapMode(MapUnit::MapAppFont)));
        m_pHelp->Show();
        m_pHelp->set_id(u"help"_ustr);
        AddButtonResponse(m_pHelp, RET_HELP);
        AddButton( m_pHelp, WIZARDDIALOG_BUTTON_STDOFFSET_X);

        // the previous button
        m_pPrevPage = VclPtr<PushButton>::Create(this, WB_TABSTOP);
        m_pPrevPage->SetHelpId( HID_WIZARD_PREVIOUS );
        m_pPrevPage->SetSizePixel(LogicToPixel(Size(50, 14), MapMode(MapUnit::MapAppFont)));
        m_pPrevPage->SetText(VclResId(STR_WIZDLG_PREVIOUS));
        m_pPrevPage->Show();
        m_pPrevPage->set_id(u"previous"_ustr);
        AddButton( m_pPrevPage, ( WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X) );      // half x-offset to the next button
        mpPrevBtn = m_pPrevPage;
        m_pPrevPage->SetClickHdl( LINK( this, RoadmapWizard, OnPrevPage ) );

        // the next button
        m_pNextPage = VclPtr<PushButton>::Create(this, WB_TABSTOP);
        m_pNextPage->SetHelpId( HID_WIZARD_NEXT );
        m_pNextPage->SetSizePixel(LogicToPixel(Size(50, 14), MapMode(MapUnit::MapAppFont)));
        m_pNextPage->SetText(VclResId(STR_WIZDLG_NEXT));
        m_pNextPage->Show();
        m_pNextPage->set_id(u"next"_ustr);
        AddButton( m_pNextPage, WIZARDDIALOG_BUTTON_STDOFFSET_X );
        mpNextBtn = m_pNextPage;
        m_pNextPage->SetClickHdl( LINK( this, RoadmapWizard, OnNextPage ) );

        // the finish button
        m_pFinish = VclPtr<OKButton>::Create(this, WB_TABSTOP);
        m_pFinish->SetSizePixel(LogicToPixel(Size(50, 14), MapMode(MapUnit::MapAppFont)));
        m_pFinish->SetText(VclResId(STR_WIZDLG_FINISH));
        m_pFinish->Show();
        m_pFinish->set_id(u"finish"_ustr);
        AddButton( m_pFinish, WIZARDDIALOG_BUTTON_STDOFFSET_X );
        m_pFinish->SetClickHdl( LINK( this, RoadmapWizard, OnFinish ) );

        // the cancel button
        m_pCancel = VclPtr<CancelButton>::Create(this, WB_TABSTOP);
        m_pCancel->SetSizePixel(LogicToPixel(Size(50, 14), MapMode(MapUnit::MapAppFont)));
        m_pCancel->Show();
        AddButton( m_pCancel, WIZARDDIALOG_BUTTON_STDOFFSET_X );
    }

    void RoadmapWizard::Resize()
    {
        if ( IsReallyShown() && !IsInInitShow() )
        {
            ImplPosCtrls();
            ImplPosTabPage();
        }

        Dialog::Resize();
    }

    void RoadmapWizard::CalcAndSetSize()
    {
        Size aDlgSize = GetPageSizePixel();
        if ( !aDlgSize.Width() || !aDlgSize.Height() )
        {
            ImplWizPageData*  pPageData = mpFirstPage;
            while ( pPageData )
            {
                if ( pPageData->mpPage )
                {
                    Size aPageSize = pPageData->mpPage->GetSizePixel();
                    if ( aPageSize.Width() > aDlgSize.Width() )
                        aDlgSize.setWidth( aPageSize.Width() );
                    if ( aPageSize.Height() > aDlgSize.Height() )
                        aDlgSize.setHeight( aPageSize.Height() );
                }

                pPageData = pPageData->mpNext;
            }
        }
        ImplCalcSize( aDlgSize );
        SetMinOutputSizePixel( aDlgSize );
        SetOutputSizePixel( aDlgSize );
    }

    void RoadmapWizard::StateChanged( StateChangedType nType )
    {
        if ( nType == StateChangedType::InitShow )
        {
            if ( IsDefaultSize() )
            {
                CalcAndSetSize();
            }

            ImplPosCtrls();
            ImplPosTabPage();
            ImplShowTabPage( ImplGetPage( mnCurLevel ) );
        }

        Dialog::StateChanged( nType );
    }

    bool RoadmapWizard::EventNotify( NotifyEvent& rNEvt )
    {
        if ( (rNEvt.GetType() == NotifyEventType::KEYINPUT) && mpPrevBtn && mpNextBtn )
        {
            const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
            vcl::KeyCode aKeyCode = pKEvt->GetKeyCode();
            sal_uInt16 nKeyCode = aKeyCode.GetCode();

            if ( aKeyCode.IsMod1() )
            {
                if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) )
                {
                    if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) )
                    {
                        if ( mpPrevBtn->IsVisible() &&
                            mpPrevBtn->IsEnabled() && mpPrevBtn->IsInputEnabled() )
                        {
                            mpPrevBtn->SetPressed( true );
                            mpPrevBtn->SetPressed( false );
                            mpPrevBtn->Click();
                        }
                        return true;
                    }
                }
                else
                {
                    if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) )
                    {
                        if ( mpNextBtn->IsVisible() &&
                            mpNextBtn->IsEnabled() && mpNextBtn->IsInputEnabled() )
                        {
                            mpNextBtn->SetPressed( true );
                            mpNextBtn->SetPressed( false );
                            mpNextBtn->Click();
                        }
                        return true;
                    }
                }
            }
        }

        return Dialog::EventNotify( rNEvt );
    }

    void RoadmapWizard::ShowPage(sal_uInt16 nLevel)
    {
        mnCurLevel = nLevel;

        // synchronize the roadmap
        implUpdateRoadmap();
        mpRoadmap->SelectRoadmapItemByID(getCurrentState());

        ImplShowTabPage( ImplGetPage( mnCurLevel ) );
    }

    void RoadmapWizard::Finish( tools::Long nResult )
    {
        if ( IsInExecute() )
            EndDialog( nResult );
        else if ( GetStyle() & WB_CLOSEABLE )
            Close();
    }

    void RoadmapWizard::AddPage( TabPage* pPage )
    {
        ImplWizPageData* pNewPageData = new ImplWizPageData;
        pNewPageData->mpNext    = nullptr;
        pNewPageData->mpPage    = pPage;

        if ( !mpFirstPage )
            mpFirstPage = pNewPageData;
        else
        {
            pPage->Hide();
            ImplWizPageData* pPageData = mpFirstPage;
            while ( pPageData->mpNext )
                pPageData = pPageData->mpNext;
            pPageData->mpNext = pNewPageData;
        }
    }

    void RoadmapWizard::RemovePage( TabPage* pPage )
    {
        ImplWizPageData*  pPrevPageData = nullptr;
        ImplWizPageData*  pPageData = mpFirstPage;
        while ( pPageData )
        {
            if ( pPageData->mpPage == pPage )
            {
                if ( pPrevPageData )
                    pPrevPageData->mpNext = pPageData->mpNext;
                else
                    mpFirstPage = pPageData->mpNext;
                if ( pPage == mpCurTabPage )
                    mpCurTabPage = nullptr;
                delete pPageData;
                return;
            }

            pPrevPageData = pPageData;
            pPageData = pPageData->mpNext;
        }

        OSL_FAIL( "RoadmapWizard::RemovePage() - Page not in list" );
    }

    void RoadmapWizard::SetPage( sal_uInt16 nLevel, TabPage* pPage )
    {
        sal_uInt16              nTempLevel = 0;
        ImplWizPageData*    pPageData = mpFirstPage;
        while ( pPageData )
        {
            if ( (nTempLevel == nLevel) || !pPageData->mpNext )
                break;

            nTempLevel++;
            pPageData = pPageData->mpNext;
        }

        if ( pPageData )
        {
            if ( pPageData->mpPage == mpCurTabPage )
                mpCurTabPage = nullptr;
            pPageData->mpPage = pPage;
        }
    }

    TabPage* RoadmapWizard::GetPage( sal_uInt16 nLevel ) const
    {
        sal_uInt16 nTempLevel = 0;

        for (ImplWizPageData* pPageData = mpFirstPage; pPageData;
             pPageData = pPageData->mpNext)
        {
            if ( nTempLevel == nLevel )
                return pPageData->mpPage;
            nTempLevel++;
        }

        return nullptr;
    }

    void RoadmapWizard::AddButton( Button* pButton, tools::Long nOffset )
    {
        ImplWizButtonData* pNewBtnData = new ImplWizButtonData;
        pNewBtnData->mpNext     = nullptr;
        pNewBtnData->mpButton   = pButton;
        pNewBtnData->mnOffset   = nOffset;

        if ( !mpFirstBtn )
            mpFirstBtn = pNewBtnData;
        else
        {
            ImplWizButtonData* pBtnData = mpFirstBtn;
            while ( pBtnData->mpNext )
                pBtnData = pBtnData->mpNext;
            pBtnData->mpNext = pNewBtnData;
        }
    }

    void RoadmapWizard::RemoveButton( Button* pButton )
    {
        ImplWizButtonData*  pPrevBtnData = nullptr;
        ImplWizButtonData*  pBtnData = mpFirstBtn;
        while ( pBtnData )
        {
            if ( pBtnData->mpButton == pButton )
            {
                if ( pPrevBtnData )
                    pPrevBtnData->mpNext = pBtnData->mpNext;
                else
                    mpFirstBtn = pBtnData->mpNext;
                delete pBtnData;
                return;
            }

            pPrevBtnData = pBtnData;
            pBtnData = pBtnData->mpNext;
        }

        OSL_FAIL( "RoadmapWizard::RemoveButton() - Button not in list" );
    }

    IMPL_LINK_NOARG(RoadmapWizard, OnFinish, Button*, void)
    {
        if ( isTravelingSuspended() )
            return;
        RoadmapWizardTravelSuspension aTravelGuard( *this );
        Finish( RET_OK );
    }

    void RoadmapWizard::skipBackwardUntil(WizardTypes::WizardState _nTargetState)
    {
        // don't travel directly on m_xWizardImpl->aStateHistory, in case something goes wrong
        std::stack< WizardTypes::WizardState > aTravelVirtually = m_xWizardImpl->aStateHistory;

        WizardTypes::WizardState nCurrentRollbackState = getCurrentState();
        while ( nCurrentRollbackState != _nTargetState )
        {
            assert(!aTravelVirtually.empty() && "RoadmapWizard::skipBackwardUntil: this target state does not exist in the history!");
            nCurrentRollbackState = aTravelVirtually.top();
            aTravelVirtually.pop();
        }
        m_xWizardImpl->aStateHistory = std::move(aTravelVirtually);
        ShowPage(_nTargetState);
    }

    void RoadmapWizard::skipUntil(WizardTypes::WizardState _nTargetState)
    {
        WizardTypes::WizardState nCurrentState = getCurrentState();

        // don't travel directly on m_xWizardImpl->aStateHistory, in case something goes wrong
        std::stack< WizardTypes::WizardState > aTravelVirtually = m_xWizardImpl->aStateHistory;
        while ( nCurrentState != _nTargetState )
        {
            WizardTypes::WizardState nNextState = determineNextState( nCurrentState );
            assert(nNextState != WZS_INVALID_STATE && "RoadmapWizard::skipUntil: the given target state does not exist!");

            // remember the skipped state in the history
            aTravelVirtually.push( nCurrentState );

            // get the next state
            nCurrentState = nNextState;
        }
        m_xWizardImpl->aStateHistory = std::move(aTravelVirtually);
        // show the target page
        ShowPage(nCurrentState);
    }

    void RoadmapWizard::travelNext()
    {
        // determine the next state to travel to
        WizardTypes::WizardState nCurrentState = getCurrentState();
        WizardTypes::WizardState nNextState = determineNextState(nCurrentState);
        if (WZS_INVALID_STATE == nNextState)
            return;

        // the state history is used by the enterState method
        // all fine
        m_xWizardImpl->aStateHistory.push(nCurrentState);
        ShowPage(nNextState);
    }

    void RoadmapWizard::travelPrevious()
    {
        DBG_ASSERT(!m_xWizardImpl->aStateHistory.empty(), "RoadmapWizard::travelPrevious: have no previous page!");

        // the next state to switch to
        WizardTypes::WizardState nPreviousState = m_xWizardImpl->aStateHistory.top();

        // the state history is used by the enterState method
        m_xWizardImpl->aStateHistory.pop();
        // show this page
        ShowPage(nPreviousState);
    }

    void  RoadmapWizard::removePageFromHistory( WizardTypes::WizardState nToRemove )
    {

        std::stack< WizardTypes::WizardState > aTemp;
        while(!m_xWizardImpl->aStateHistory.empty())
        {
            WizardTypes::WizardState nPreviousState = m_xWizardImpl->aStateHistory.top();
            m_xWizardImpl->aStateHistory.pop();
            if(nPreviousState != nToRemove)
                aTemp.push( nPreviousState );
            else
                break;
        }
        while(!aTemp.empty())
        {
            m_xWizardImpl->aStateHistory.push( aTemp.top() );
            aTemp.pop();
        }
    }

    IMPL_LINK_NOARG(RoadmapWizard, OnPrevPage, Button*, void)
    {
        if ( isTravelingSuspended() )
            return;
        RoadmapWizardTravelSuspension aTravelGuard( *this );
        travelPrevious();
    }

    IMPL_LINK_NOARG(RoadmapWizard, OnNextPage, Button*, void)
    {
        if ( isTravelingSuspended() )
            return;
        RoadmapWizardTravelSuspension aTravelGuard( *this );
        travelNext();
    }

    bool RoadmapWizard::isTravelingSuspended() const
    {
        return m_xWizardImpl->m_bTravelingSuspended;
    }

    void RoadmapWizard::suspendTraveling( AccessGuard )
    {
        DBG_ASSERT( !m_xWizardImpl->m_bTravelingSuspended, "RoadmapWizard::suspendTraveling: already suspended!" );
        m_xWizardImpl->m_bTravelingSuspended = true;
    }

    void RoadmapWizard::resumeTraveling( AccessGuard )
    {
        DBG_ASSERT( m_xWizardImpl->m_bTravelingSuspended, "RoadmapWizard::resumeTraveling: nothing to resume!" );
        m_xWizardImpl->m_bTravelingSuspended = false;
    }

    void RoadmapWizard::implUpdateRoadmap( )
    {
        DBG_ASSERT( m_xRoadmapImpl->aPaths.find( m_xRoadmapImpl->nActivePath ) != m_xRoadmapImpl->aPaths.end(),
            "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
        const WizardPath& rActivePath( m_xRoadmapImpl->aPaths[ m_xRoadmapImpl->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());
        bool bIncompletePath = false;
        if ( !m_xRoadmapImpl->bActivePathIsDefinite )
        {
            for (auto const& path : m_xRoadmapImpl->aPaths)
            {
                if ( path.first == m_xRoadmapImpl->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;
                bIncompletePath = true;
            }
        }

        // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active
        // path, up to (excluding) nUpperStepBoundary
        RoadmapTypes::ItemIndex nLoopUntil = ::std::max( nUpperStepBoundary, mpRoadmap->GetItemCount() );
        for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex )
        {
            bool bExistentItem = ( nItemIndex < mpRoadmap->GetItemCount() );
            bool bNeedItem = ( nItemIndex < nUpperStepBoundary );

            bool bInsertItem = false;
            if ( bExistentItem )
            {
                if ( !bNeedItem )
                {
                    while ( nItemIndex < mpRoadmap->GetItemCount() )
                        mpRoadmap->DeleteRoadmapItem( nItemIndex );
                    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 = mpRoadmap->GetItemID( nItemIndex );
                    WizardTypes::WizardState nRequiredState = rActivePath[ nItemIndex ];
                    if ( nPresentItemId != nRequiredState )
                    {
                        mpRoadmap->DeleteRoadmapItem( nItemIndex );
                        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 )
            {
                mpRoadmap->InsertRoadmapItem(
                    nItemIndex,
                    getStateDisplayName( nState ),
                    nState,
                    true
                );
            }

            const bool bEnable = m_xRoadmapImpl->aDisabledStates.find( nState ) == m_xRoadmapImpl->aDisabledStates.end();
            mpRoadmap->EnableRoadmapItem( mpRoadmap->GetItemID( nItemIndex ), bEnable );
        }

        mpRoadmap->SetRoadmapComplete( !bIncompletePath );
    }

    WizardTypes::WizardState RoadmapWizard::determineNextState( WizardTypes::WizardState _nCurrentState ) const
    {
        sal_Int32 nCurrentStatePathIndex = -1;

        Paths::const_iterator aActivePathPos = m_xRoadmapImpl->aPaths.find( m_xRoadmapImpl->nActivePath );
        if ( aActivePathPos != m_xRoadmapImpl->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_xRoadmapImpl->aDisabledStates.find( aActivePathPos->second[ nNextStateIndex ] ) != m_xRoadmapImpl->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 ];
    }


    IMPL_LINK_NOARG(RoadmapWizard, OnRoadmapItemSelected, LinkParamNone*, void)
    {
        RoadmapTypes::ItemId nCurItemId = mpRoadmap->GetCurrentRoadmapItemID();
        if ( nCurItemId == getCurrentState() )
            // nothing to do
            return;

        if ( isTravelingSuspended() )
            return;

        RoadmapWizardTravelSuspension aTravelGuard( *this );

        sal_Int32 nCurrentIndex = m_xRoadmapImpl->getStateIndexInPath( getCurrentState(), m_xRoadmapImpl->nActivePath );
        sal_Int32 nNewIndex     = m_xRoadmapImpl->getStateIndexInPath( nCurItemId, m_xRoadmapImpl->nActivePath );

        DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ),
            "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
        if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) )
        {
            return;
        }

        if ( nNewIndex > nCurrentIndex )
        {
            skipUntil(static_cast<WizardTypes::WizardState>(nCurItemId));
            WizardTypes::WizardState nTemp = static_cast<WizardTypes::WizardState>(nCurItemId);
            while( nTemp )
            {
                if( m_xRoadmapImpl->aDisabledStates.find( --nTemp ) != m_xRoadmapImpl->aDisabledStates.end() )
                    removePageFromHistory( nTemp );
            }
        }
        else
            skipBackwardUntil(static_cast<WizardTypes::WizardState>(nCurItemId));
    }

    OUString RoadmapWizard::getStateDisplayName( WizardTypes::WizardState /* _nState */)
    {
        SAL_WARN("vcl""RoadmapWizard::getStateDisplayName: no name available for this state!");
        return OUString();
    }

    void RoadmapWizard::InsertRoadmapItem(int nItemIndex, const OUString& rText, int nItemId, bool bEnable)
    {
        mpRoadmap->InsertRoadmapItem(nItemIndex, rText, nItemId, bEnable);
    }

    void RoadmapWizard::SelectRoadmapItemByID(int nItemId, bool bGrabFocus)
    {
        mpRoadmap->SelectRoadmapItemByID(nItemId, bGrabFocus);
    }

    void RoadmapWizard::DeleteRoadmapItems()
    {
        while (mpRoadmap->GetItemCount())
            mpRoadmap->DeleteRoadmapItem(0);
    }

    void RoadmapWizard::SetItemSelectHdl( const Link<LinkParamNone*,void>& _rHdl )
    {
        mpRoadmap->SetItemSelectHdl(_rHdl);
    }

    int RoadmapWizard::GetCurrentRoadmapItemID() const
    {
        return mpRoadmap->GetCurrentRoadmapItemID();
    }

    FactoryFunction RoadmapWizard::GetUITestFactory() const
    {
        return RoadmapWizardUIObject::create;
    }

    namespace
    {
        bool isButton(WindowType eType)
        {
            return eType == WindowType::PUSHBUTTON || eType == WindowType::OKBUTTON
                || eType == WindowType::CANCELBUTTON || eType == WindowType::HELPBUTTON;
        }
    }

    void RoadmapWizard::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
    {
        rJsonWriter.put("id", get_id());
        rJsonWriter.put("type""dialog");
        rJsonWriter.put("title", GetText());

        OUString sDialogId = GetHelpId();
        sal_Int32 nStartPos = sDialogId.lastIndexOf('/');
        nStartPos = nStartPos >= 0 ? nStartPos + 1 : 0;
        rJsonWriter.put("dialogid", sDialogId.copy(nStartPos));
        {
            auto aResponses = rJsonWriter.startArray("responses");
            for (const auto& rResponse : maResponses)
            {
                auto aResponse = rJsonWriter.startStruct();
                rJsonWriter.put("id", rResponse.first->get_id());
                rJsonWriter.put("response", rResponse.second);
            }
        }

        vcl::Window* pFocusControl = GetFirstControlForFocus();
        if (pFocusControl)
            rJsonWriter.put("init_focus_id", pFocusControl->get_id());

        {
            auto childrenNode = rJsonWriter.startArray("children");

            auto containerNode = rJsonWriter.startStruct();
            rJsonWriter.put("id""container");
            rJsonWriter.put("type""container");
            rJsonWriter.put("vertical"true);

            {
                auto containerChildrenNode = rJsonWriter.startArray("children");

                // tabpages
                for (int i = 0; i < GetChildCount(); i++)
                {
                    vcl::Window* pChild = GetChild(i);

                    if (!isButton(pChild->GetType()) && pChild != mpRoadmap)
                    {
                        auto childNode = rJsonWriter.startStruct();
                        pChild->DumpAsPropertyTree(rJsonWriter);
                    }
                }

                // buttons
                {
                    auto buttonsNode = rJsonWriter.startStruct();
                    rJsonWriter.put("id""buttons");
                    rJsonWriter.put("type""buttonbox");
                    rJsonWriter.put("layoutstyle""end");
                    {
                        auto buttonsChildrenNode = rJsonWriter.startArray("children");
                        for (int i = 0; i < GetChildCount(); i++)
                        {
                            vcl::Window* pChild = GetChild(i);

                            if (isButton(pChild->GetType()))
                            {
                                auto childNode = rJsonWriter.startStruct();
                                pChild->DumpAsPropertyTree(rJsonWriter);
                            }
                        }
                    }
                }
            }
        }
    }

}   // namespace vcl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=82 G=89

¤ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.