Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  sdpage.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 <algorithm>
#include <array>

#include <comphelper/classids.hxx>
#include <comphelper/embeddedobjectcontainer.hxx>
#include <comphelper/lok.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>

#include <sfx2/viewsh.hxx>
#include <vcl/svapp.hxx>
#include <editeng/outliner.hxx>
#include <editeng/eeitem.hxx>
#include <svx/svdoutl.hxx>
#include <editeng/editdata.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/bulletitem.hxx>
#include <svx/svdpagv.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/outlobj.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdograf.hxx>
#include <svx/svdopage.hxx>
#include <editeng/pbinitem.hxx>
#include <svx/svdundo.hxx>
#include <svl/hint.hxx>
#include <editeng/adjustitem.hxx>
#include <editeng/editobj.hxx>
#include <svx/unopage.hxx>
#include <editeng/flditem.hxx>
#include <svx/sdr/contact/displayinfo.hxx>
#include <svx/svditer.hxx>
#include <svx/svdlayer.hxx>
#include <svx/sdtmfitm.hxx>
#include <svx/sdtagitm.hxx>
#include <svx/sdtcfitm.hxx>
#include <svx/xfillit0.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <com/sun/star/animations/XAnimationNode.hpp>
#include <com/sun/star/animations/XTimeContainer.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <com/sun/star/xml/dom/XNode.hpp>
#include <com/sun/star/xml/dom/XNodeList.hpp>
#include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
#include <rtl/ustring.hxx>
#include <sal/log.hxx>
#include <o3tl/enumarray.hxx>
#include <o3tl/safeint.hxx>
#include <o3tl/sorted_vector.hxx>
#include <xmloff/autolayout.hxx>

#include <Annotation.hxx>
#include <Outliner.hxx>
#include <app.hrc>
#include <createunopageimpl.hxx>
#include <drawdoc.hxx>
#include <sdmod.hxx>
#include <sdpage.hxx>
#include <sdresid.hxx>
#include <stlsheet.hxx>
#include <strings.hrc>
#include <strings.hxx>
#include <bitmaps.hlst>
#include <glob.hxx>
#include <anminfo.hxx>
#include <undo/undomanager.hxx>
#include <undo/undoobjects.hxx>
#include <svx/sdr/contact/viewobjectcontact.hxx>
#include <svx/sdr/contact/viewcontact.hxx>
#include <svx/sdr/contact/objectcontact.hxx>
#include <svx/unoapi.hxx>
#include <unokywds.hxx>

using namespace ::sd;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace com::sun::star::xml::dom;
using ::com::sun::star::uno::Reference;


sal_uInt16 SdPage::mnLastPageId = 1;

/*************************************************************************
|*
|*      Ctor
|*
\************************************************************************/


SdPage::SdPage(SdDrawDocument& rNewDoc, bool bMasterPage)
:   FmFormPage(rNewDoc, bMasterPage)
,   SdrObjUserCall()
,   mePageKind(PageKind::Standard)
,   meAutoLayout(AUTOLAYOUT_NONE)
,   mbSelected(false)
,   mePresChange(PresChange::Manual)
,   mfTime(1.0)
,   mbSoundOn(false)
,   mbExcluded(false)
,   mbLoopSound(false)
,   mbStopSound(false)
,   mbScaleObjects(true)
,   meCharSet(osl_getThreadTextEncoding())
,   mnPaperBin(PAPERBIN_PRINTER_SETTINGS)
,   mpPageLink(nullptr)
,   mnTransitionType(0)
,   mnTransitionSubtype(0)
,   mbTransitionDirection(true)
,   mnTransitionFadeColor(0)
,   mfTransitionDuration(2.0)
,   mbIsPrecious(true)
,   mnPageId(mnLastPageId++)
{
    // The name of the layout of the page is used by SVDRAW to determine the
    // presentation template of the outline objects. Therefore, it already
    // contains the designator for the outline (STR_LAYOUT_OUTLINE).
    maLayoutName = SdResId(STR_LAYOUT_DEFAULT_NAME)+ SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE;

    // Stuff that former SetModel did also:
    ConnectLink();
}

namespace
{
    void clearChildNodes(css::uno::Reference<css::animations::XAnimationNode> const & rAnimationNode)
    {
        css::uno::Reference<css::container::XEnumerationAccess > xEnumerationAccess(rAnimationNode, UNO_QUERY);
        if (!xEnumerationAccess.is())
            return;
        css::uno::Reference<css::container::XEnumeration> xEnumeration = xEnumerationAccess->createEnumeration();
        if (!xEnumeration.is())
            return;
        while (xEnumeration->hasMoreElements())
        {
            css::uno::Reference<css::animations::XAnimationNode> xChildNode(xEnumeration->nextElement(), UNO_QUERY);
            if (!xChildNode.is())
                continue;
            clearChildNodes(xChildNode);
            css::uno::Reference<css::animations::XTimeContainer> xAnimationNode(rAnimationNode, UNO_QUERY);
            if (!xAnimationNode.is())
            {
                SAL_WARN("sd.core""can't remove node child, possible leak");
                continue;
            }
            xAnimationNode->removeChild(xChildNode);
        }
    }
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/


SdPage::~SdPage()
{
    DisconnectLink();

    EndListenOutlineText();

    clearChildNodes(mxAnimationNode);

    // disconnect the UserCall link, so we don't get calls
    // back into this dying object when the child objects die
    SdrObjListIter aIter( this, SdrIterMode::DeepWithGroups );
    while( aIter.IsMore() )
    {
        SdrObject* pChild = aIter.Next();
        if( pChild->GetUserCall() == this )
            pChild->SetUserCall(nullptr);
    }
}

namespace {

struct OrdNumSorter
{
    bool operator()( SdrObject const * p1, SdrObject const * p2 )
    {
        return p1->GetOrdNum() < p2->GetOrdNum();
    }
};

}

/** returns the nIndex'th object from the given PresObjKind, index starts with 1 */
SdrObject* SdPage::GetPresObj(PresObjKind eObjKind, int nIndex, bool bFuzzySearch /* = false */ )
{
    // first sort all matching shapes with z-order
    std::vector< SdrObject* > aMatches;

    SdrObject* pObj = nullptr;
    maPresentationShapeList.seekShape(0);

    while( (pObj = maPresentationShapeList.getNextShape()) )
    {
        SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(*pObj);
        if( pInfo )
        {
            bool bFound = false;
            if( pInfo->mePresObjKind == eObjKind )
            {
                bFound = true;
            }
            else if( bFuzzySearch && (eObjKind == PresObjKind::Outline) )
            {
                switch( pInfo->mePresObjKind )
                {
                case PresObjKind::Graphic:
                case PresObjKind::Object:
                case PresObjKind::Chart:
                case PresObjKind::OrgChart:
                case PresObjKind::Table:
                case PresObjKind::Calc:
                case PresObjKind::Media:
                    bFound = true;
                    break;
                default:
                    break;
                }
            }
            if( bFound )
            {
                aMatches.push_back( pObj );
            }
        }
    }

    if( nIndex > 0 )
        nIndex--;

    if( (nIndex >= 0) && ( aMatches.size() > o3tl::make_unsigned(nIndex)) )
    {
        if( aMatches.size() > 1 )
            std::nth_element( aMatches.begin(), aMatches.begin() + nIndex, aMatches.end(),
                              OrdNumSorter() );
        return aMatches[nIndex];
    }

    return nullptr;
}

/** create background properties */
void SdPage::EnsureMasterPageDefaultBackground()
{
    if(!mbMaster)
        return;

    // no hard attributes on MasterPage attributes
    getSdrPageProperties().ClearItem();
    SfxStyleSheet* pSheetForPresObj = GetStyleSheetForMasterPageBackground();

    if(pSheetForPresObj)
    {
        // set StyleSheet for background fill attributes
        getSdrPageProperties().SetStyleSheet(pSheetForPresObj);
    }
    else
    {
        // no style found, assert and set at least drawing::FillStyle_NONE
        OSL_FAIL("No Style for MasterPageBackground fill found (!)");
        getSdrPageProperties().PutItem(XFillStyleItem(drawing::FillStyle_NONE));
    }
}

/** creates a presentation object with the given PresObjKind on this page. A user call will be set
*/

SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::tools::Rectangle& rRect )
{
    SfxUndoManager* pUndoManager(static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetUndoManager());
    const bool bUndo = pUndoManager && pUndoManager->IsInListAction() && IsInserted();

    rtl::Reference<SdrObject> pSdrObj;

    bool bForceText = false;    // forces the shape text to be set even if it's empty
    bool bEmptyPresObj = true;

    switch( eObjKind )
    {
        case PresObjKind::Title:
        {
            pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), SdrObjKind::TitleText);

            if (mbMaster)
            {
                pSdrObj->SetNotVisibleAsMaster(true);
            }
        }
        break;

        case PresObjKind::Outline:
        {
            pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), SdrObjKind::OutlineText);

            if (mbMaster)
            {
                pSdrObj->SetNotVisibleAsMaster(true);
            }
        }
        break;

        case PresObjKind::Notes:
        {
            pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), SdrObjKind::Text);

            if (mbMaster)
            {
                pSdrObj->SetNotVisibleAsMaster(true);
            }
        }
        break;

        case PresObjKind::Text:
        {
            pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), SdrObjKind::Text);
        }
        break;

        case PresObjKind::Graphic:
        {
            BitmapEx aBmpEx(BMP_PRESOBJ_GRAPHIC);
            Graphic  aGraphic( aBmpEx );
            OutputDevice &aOutDev = *Application::GetDefaultDevice();
            aOutDev.Push();

            aOutDev.SetMapMode( aGraphic.GetPrefMapMode() );
            Size aSizePix = aOutDev.LogicToPixel( aGraphic.GetPrefSize() );
            aOutDev.SetMapMode(MapMode(MapUnit::Map100thMM));

            Size aSize = aOutDev.PixelToLogic(aSizePix);
            Point aPnt (0, 0);
            ::tools::Rectangle aRect (aPnt, aSize);
            pSdrObj = new SdrGrafObj(getSdrModelFromSdrPage(), aGraphic, aRect);
            aOutDev.Pop();
        }
        break;

        case PresObjKind::Media:
        case PresObjKind::Object:
        {
            pSdrObj = new SdrOle2Obj(getSdrModelFromSdrPage());
            BitmapEx aBmpEx(BMP_PRESOBJ_OBJECT);
            Graphic aGraphic( aBmpEx );
            static_cast<SdrOle2Obj*>(pSdrObj.get())->SetGraphic(aGraphic);
        }
        break;

        case PresObjKind::Chart:
        {
            pSdrObj = new SdrOle2Obj(getSdrModelFromSdrPage());
            static_cast<SdrOle2Obj*>(pSdrObj.get())->SetProgName( u"StarChart"_ustr );
            BitmapEx aBmpEx(BMP_PRESOBJ_CHART);
            Graphic aGraphic( aBmpEx );
            static_cast<SdrOle2Obj*>(pSdrObj.get())->SetGraphic(aGraphic);
        }
        break;

        case PresObjKind::OrgChart:
        {
            pSdrObj = new SdrOle2Obj(getSdrModelFromSdrPage());
            static_cast<SdrOle2Obj*>(pSdrObj.get())->SetProgName( u"StarOrg"_ustr );
            BitmapEx aBmpEx(BMP_PRESOBJ_ORGCHART);
            Graphic aGraphic( aBmpEx );
            static_cast<SdrOle2Obj*>(pSdrObj.get())->SetGraphic(aGraphic);
        }
        break;

        case PresObjKind::Table:
        case PresObjKind::Calc:
        {
            pSdrObj = new SdrOle2Obj(getSdrModelFromSdrPage());
            static_cast<SdrOle2Obj*>(pSdrObj.get())->SetProgName( u"StarCalc"_ustr );
            BitmapEx aBmpEx(BMP_PRESOBJ_TABLE);
            Graphic aGraphic( aBmpEx );
            static_cast<SdrOle2Obj*>(pSdrObj.get())->SetGraphic(aGraphic);
        }
        break;

        case PresObjKind::Handout:
        {
            // Save the first standard page at SdrPageObj
            // #i105146# We want no content to be displayed for PageKind::Handout,
            // so just never set a page as content
            pSdrObj = new SdrPageObj(getSdrModelFromSdrPage(), nullptr);
        }
        break;

        case PresObjKind::Page:
        {
            // Save note pages at SdrPageObj
            sal_uInt16 nDestPageNum(GetPageNum());

            if(nDestPageNum)
            {
                // decrement only when != 0, else we get a 0xffff
                nDestPageNum -= 1;
            }

            if (nDestPageNum < getSdrModelFromSdrPage().GetPageCount())
            {
                pSdrObj = new SdrPageObj(getSdrModelFromSdrPage(), getSdrModelFromSdrPage().GetPage(nDestPageNum));
            }
            else
            {
                pSdrObj = new SdrPageObj(getSdrModelFromSdrPage());
            }

            pSdrObj->SetResizeProtect(true);
        }
        break;

        case PresObjKind::Header:
        case PresObjKind::Footer:
        case PresObjKind::DateTime:
        case PresObjKind::SlideNumber:
        {
            pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), SdrObjKind::Text);
            bEmptyPresObj = false;
            bForceText = true;
        }
        break;
        default:
            break;
    }

    if (pSdrObj)
    {
        pSdrObj->SetEmptyPresObj(bEmptyPresObj);
        pSdrObj->SetLogicRect(rRect);

        InsertObject(pSdrObj.get());

        if ( auto pTextObj = DynCastSdrTextObj( pSdrObj.get() ) )
        {
            // Tell the object EARLY that it is vertical to have the
            // defaults for AutoGrowWidth/Height reversed
            if(bVertical)
                pTextObj->SetVerticalWriting(true);

            SfxItemSet aTempAttr(static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetPool());
            if( bVertical )
                aTempAttr.Put( makeSdrTextMinFrameWidthItem( rRect.GetSize().Width() ) );
            else
                aTempAttr.Put( makeSdrTextMinFrameHeightItem( rRect.GetSize().Height() ) );

            if (eObjKind == PresObjKind::Notes)
                aTempAttr.Put(makeSdrTextAutoGrowHeightItem(false));

            if (mbMaster)
            {
                // The size of presentation objects on the master page have to
                // be freely selectable by the user.

                // potential problem: This action was still NOT
                // adapted for vertical text. This sure needs to be done.
                if(bVertical)
                    aTempAttr.Put(makeSdrTextAutoGrowWidthItem(false));
                else
                    aTempAttr.Put(makeSdrTextAutoGrowHeightItem(false));
            }

            // check if we need another vertical adjustment than the default
            SdrTextVertAdjust eV = SDRTEXTVERTADJUST_TOP;

            if( (eObjKind == PresObjKind::Footer) && (mePageKind != PageKind::Standard) )
            {
                eV = SDRTEXTVERTADJUST_BOTTOM;
            }
            else if( (eObjKind == PresObjKind::SlideNumber) && (mePageKind != PageKind::Standard) )
            {
                eV = SDRTEXTVERTADJUST_BOTTOM;
            }

            if( eV != SDRTEXTVERTADJUST_TOP )
                aTempAttr.Put(SdrTextVertAdjustItem(eV));

            pSdrObj->SetMergedItemSet(aTempAttr);

            pSdrObj->SetLogicRect(rRect);
        }

        OUString aString = GetPresObjText(eObjKind);
        if(!aString.isEmpty() || bForceText)
            if (auto pTextObj = DynCastSdrTextObj( pSdrObj.get() ) )
            {
                SdrOutliner* pOutliner = static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetInternalOutliner();

                OutlinerMode nOutlMode = pOutliner->GetOutlinerMode();
                pOutliner->Init( OutlinerMode::TextObject );
                pOutliner->SetStyleSheet( 0, nullptr );
                pOutliner->SetVertical( bVertical );

                SetObjText( pTextObj, pOutliner, eObjKind, aString );

                pOutliner->Init( nOutlMode );
                pOutliner->SetStyleSheet( 0, nullptr );
            }

        if( (eObjKind == PresObjKind::Header) || (eObjKind == PresObjKind::Footer) || (eObjKind == PresObjKind::SlideNumber) || (eObjKind == PresObjKind::DateTime) )
        {
            SfxItemSet aTempAttr(static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetPool());
            aTempAttr.Put( SvxFontHeightItem( 493, 100, EE_CHAR_FONTHEIGHT ) );
            aTempAttr.Put( SvxFontHeightItem( 493, 100, EE_CHAR_FONTHEIGHT_CTL ) );
            aTempAttr.Put( SvxFontHeightItem( 493, 100, EE_CHAR_FONTHEIGHT_CJK ) );

            SvxAdjust eH = SvxAdjust::Left;

            if( (eObjKind == PresObjKind::DateTime) && (mePageKind != PageKind::Standard ) )
            {
                eH = SvxAdjust::Right;
            }
            else if( (eObjKind == PresObjKind::Footer) && (mePageKind == PageKind::Standard ) )
            {
                eH = SvxAdjust::Center;
            }
            else if( eObjKind == PresObjKind::SlideNumber )
            {
                eH = SvxAdjust::Right;
            }

            if( eH != SvxAdjust::Left )
                aTempAttr.Put(SvxAdjustItem(eH, EE_PARA_JUST ));

            pSdrObj->SetMergedItemSet(aTempAttr);
        }

        if (mbMaster)
        {
            SdrLayerAdmin& rLayerAdmin(getSdrModelFromSdrPage().GetLayerAdmin());

            // background objects of the master page
            pSdrObj->SetLayer( rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects) );
        }

        // Subscribe object at the style sheet
        // Set style only when one was found (as in 5.2)
        if( mePageKind != PageKind::Handout )
        {
            SfxStyleSheet* pSheetForPresObj = GetStyleSheetForPresObj(eObjKind);
            if(pSheetForPresObj)
                pSdrObj->SetStyleSheet(pSheetForPresObj, false);
        }

        if (eObjKind == PresObjKind::Outline)
        {
            for (sal_uInt16 nLevel = 1; nLevel < 10; nLevel++)
            {
                OUString aName( maLayoutName + " " + OUString::number( nLevel ) );
                SfxStyleSheet* pSheet = static_cast<SfxStyleSheet*>(getSdrModelFromSdrPage().GetStyleSheetPool()->Find(aName, SfxStyleFamily::Page));
                DBG_ASSERT(pSheet, "StyleSheet for outline object not found");
                if (pSheet)
                    pSdrObj->StartListening(*pSheet, DuplicateHandling::Allow);
            }
        }

        if ( eObjKind == PresObjKind::Object   ||
             eObjKind == PresObjKind::Chart    ||
             eObjKind == PresObjKind::OrgChart ||
             eObjKind == PresObjKind::Calc    ||
             eObjKind == PresObjKind::Graphic )
        {
            SfxItemSet aSet( static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetPool() );
            aSet.Put( makeSdrTextContourFrameItem( true ) );
            aSet.Put( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) );

            pSdrObj->SetMergedItemSet(aSet);
        }

        if( bUndo )
        {
            pUndoManager->AddUndoAction(getSdrModelFromSdrPage().GetSdrUndoFactory().CreateUndoNewObject(*pSdrObj));

            pUndoManager->AddUndoAction( std::make_unique<UndoObjectPresentationKind>( *pSdrObj ) );
            pUndoManager->AddUndoAction( std::make_unique<UndoObjectUserCall>(*pSdrObj) );
        }

        InsertPresObj(pSdrObj.get(), eObjKind);
        pSdrObj->SetUserCall(this);

        pSdrObj->RecalcBoundRect();
    }

    return pSdrObj.get();
}

/*************************************************************************
|*
|* Creates presentation objects on the master page.
|* All presentation objects get a UserCall to the page.
|*
\************************************************************************/


SfxStyleSheet* SdPage::GetStyleSheetForMasterPageBackground() const
{
    OUString aName(GetLayoutName());
    OUString aSep( SD_LT_SEPARATOR );
    sal_Int32 nPos = aName.indexOf(aSep);

    if (nPos != -1)
    {
        nPos = nPos + aSep.getLength();
        aName = aName.copy(0, nPos);
    }

    aName += STR_LAYOUT_BACKGROUND;

    SfxStyleSheetBasePool* pStShPool = getSdrModelFromSdrPage().GetStyleSheetPool();
    SfxStyleSheetBase*     pResult   = pStShPool->Find(aName, SfxStyleFamily::Page);
    return static_cast<SfxStyleSheet*>(pResult);
}

SfxStyleSheet* SdPage::GetStyleSheetForPresObj(PresObjKind eObjKind) const
{
    OUString aName(GetLayoutName());
    OUString aSep( SD_LT_SEPARATOR );
    sal_Int32 nPos = aName.indexOf(aSep);
    if (nPos != -1)
    {
        nPos = nPos + aSep.getLength();
        aName = aName.copy(0, nPos);
    }

    switch (eObjKind)
    {
        case PresObjKind::Outline:
        {
            aName = GetLayoutName() + " " + OUString::number( 1 );
        }
        break;

        case PresObjKind::Title:
            aName += STR_LAYOUT_TITLE;
            break;

        case PresObjKind::Notes:
            aName += STR_LAYOUT_NOTES;
            break;

        case PresObjKind::Text:
            aName += STR_LAYOUT_SUBTITLE;
            break;

        case PresObjKind::Header:
        case PresObjKind::Footer:
        case PresObjKind::DateTime:
        case PresObjKind::SlideNumber:
            aName += STR_LAYOUT_BACKGROUNDOBJECTS;
            break;

        default:
            break;
    }

    SfxStyleSheetBasePool* pStShPool = getSdrModelFromSdrPage().GetStyleSheetPool();
    SfxStyleSheetBase*     pResult   = pStShPool->Find(aName, SfxStyleFamily::Page);
    return static_cast<SfxStyleSheet*>(pResult);
}

/** returns the presentation style with the given helpid from this masterpage or this
    slides masterpage */

SdStyleSheet* SdPage::getPresentationStyle( sal_uInt32 nHelpId ) const
{
    OUString aStyleName( GetLayoutName() );
    const OUString aSep( SD_LT_SEPARATOR );
    sal_Int32 nIndex = aStyleName.indexOf(aSep);
    if( nIndex != -1 )
        aStyleName = aStyleName.copy(0, nIndex + aSep.getLength());

    OUString pNameId;
    bool bOutline = false;
    switch( nHelpId )
    {
    case HID_PSEUDOSHEET_TITLE:             pNameId = STR_LAYOUT_TITLE;             break;
    case HID_PSEUDOSHEET_SUBTITLE:          pNameId = STR_LAYOUT_SUBTITLE;          break;
    case HID_PSEUDOSHEET_OUTLINE1:
    case HID_PSEUDOSHEET_OUTLINE2:
    case HID_PSEUDOSHEET_OUTLINE3:
    case HID_PSEUDOSHEET_OUTLINE4:
    case HID_PSEUDOSHEET_OUTLINE5:
    case HID_PSEUDOSHEET_OUTLINE6:
    case HID_PSEUDOSHEET_OUTLINE7:
    case HID_PSEUDOSHEET_OUTLINE8:
    case HID_PSEUDOSHEET_OUTLINE9:          pNameId = STR_LAYOUT_OUTLINE; bOutline = truebreak;
    case HID_PSEUDOSHEET_BACKGROUNDOBJECTS: pNameId = STR_LAYOUT_BACKGROUNDOBJECTS; break;
    case HID_PSEUDOSHEET_BACKGROUND:        pNameId = STR_LAYOUT_BACKGROUND;        break;
    case HID_PSEUDOSHEET_NOTES:             pNameId = STR_LAYOUT_NOTES;             break;

    default:
        OSL_FAIL( "SdPage::getPresentationStyle(), illegal argument!" );
        return nullptr;
    }
    aStyleName += pNameId;
    if (bOutline)
    {
        aStyleName += " " +
            OUString::number( sal_Int32( nHelpId - HID_PSEUDOSHEET_OUTLINE ));
    }

    SfxStyleSheetBasePool* pStShPool = getSdrModelFromSdrPage().GetStyleSheetPool();
    SfxStyleSheetBase*     pResult   = pStShPool->Find(aStyleName, SfxStyleFamily::Page);
    return dynamic_cast<SdStyleSheet*>(pResult);
}

/*************************************************************************
|*
|* The presentation object rObj has changed and is no longer referenced by the
|* presentation object of the master page.
|* The UserCall is deleted.
|*
\************************************************************************/


void SdPage::Changed(const SdrObject& rObj, SdrUserCallType eType, const ::tools::Rectangle& )
{
    if (maLockAutoLayoutArrangement.isLocked())
        return;

    switch (eType)
    {
        case SdrUserCallType::MoveOnly:
        case SdrUserCallType::Resize:
        {
            if ( getSdrModelFromSdrPage().isLocked())
                break;

            if (!mbMaster)
            {
                if (rObj.GetUserCall())
                {
                    SdrObject& _rObj = const_cast<SdrObject&>(rObj);
                    SfxUndoManager* pUndoManager
                        = static_cast<SdDrawDocument&>(getSdrModelFromSdrPage())
                              .GetUndoManager();
                    const bool bUndo
                        = pUndoManager && pUndoManager->IsInListAction() && IsInserted();

                    if (bUndo)
                        pUndoManager->AddUndoAction(
                            std::make_unique<UndoObjectUserCall>(_rObj));

                    // Object was resized by user and does not listen to its slide anymore
                    _rObj.SetUserCall(nullptr);
                }
            }
            else
            {
                // Object of the master page changed, therefore adjust
                // object on all pages
                sal_uInt16 nPageCount = static_cast<SdDrawDocument&>(getSdrModelFromSdrPage())
                                            .GetSdPageCount(mePageKind);

                for (sal_uInt16 i = 0; i < nPageCount; i++)
                {
                    SdPage* pLoopPage = static_cast<SdDrawDocument&>(getSdrModelFromSdrPage())
                                            .GetSdPage(i, mePageKind);

                    if (pLoopPage && this == &(pLoopPage->TRG_GetMasterPage()))
                    {
                        // Page listens to this master page, therefore
                        // adjust AutoLayout
                        pLoopPage->SetAutoLayout(pLoopPage->GetAutoLayout());
                    }
                }
            }
        }
        break;

        case SdrUserCallType::Delete:
        case SdrUserCallType::Removed:
        default:
            break;
    }
}

/*************************************************************************
|*
|* Creates on a master page: background, title- and layout area
|*
\************************************************************************/


void SdPage::CreateTitleAndLayout(bool bInit, bool bCreate )
{
    SfxUndoManager* pUndoManager(static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetUndoManager());
    const bool bUndo = pUndoManager && pUndoManager->IsInListAction() && IsInserted();

    SdPage* pMasterPage = this;

    if (!mbMaster)
    {
        pMasterPage = static_cast<SdPage*>(&(TRG_GetMasterPage()));
    }

    if (!pMasterPage)
    {
        return;
    }

    /**************************************************************************
    * create background, title- and layout area
    **************************************************************************/

    if( mePageKind == PageKind::Standard )
    {
        pMasterPage->EnsureMasterPageDefaultBackground();
    }

    if (static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetDocumentType() != DocumentType::Impress)
        return;

    if( mePageKind == PageKind::Handout && bInit )
    {
        // handout template

        // delete all available handout presentation objects
        rtl::Reference<SdrObject> pObj;
        while( (pObj = pMasterPage->GetPresObj(PresObjKind::Handout)) )
        {
            pMasterPage->RemoveObject(pObj->GetOrdNum());

            if( bUndo )
            {
                pUndoManager->AddUndoAction(getSdrModelFromSdrPage().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
            }
            pObj.clear();
        }

        std::vector< ::tools::Rectangle > aAreas;
        CalculateHandoutAreas(static_cast<SdDrawDocument&>(getSdrModelFromSdrPage()),
                              pMasterPage->GetAutoLayout(), false, aAreas,
                              pMasterPage->GetOrientation());

        const bool bSkip = pMasterPage->GetAutoLayout() == AUTOLAYOUT_HANDOUT3;
        std::vector< ::tools::Rectangle >::iterator iter( aAreas.begin() );

        while( iter != aAreas.end() )
        {
            SdrPageObj* pPageObj = static_cast<SdrPageObj*>(pMasterPage->CreatePresObj(PresObjKind::Handout, false, (*iter++)) );
            // #i105146# We want no content to be displayed for PageKind::Handout,
            // so just never set a page as content
            pPageObj->SetReferencedPage(nullptr);

            if( bSkip && iter != aAreas.end() )
                ++iter;
        }
    }

    if( mePageKind != PageKind::Handout )
    {
        SdrObject* pMasterTitle = pMasterPage->GetPresObj( PresObjKind::Title );
        if( pMasterTitle == nullptr )
            pMasterPage->CreateDefaultPresObj(PresObjKind::Title);

        SdrObject* pMasterOutline = pMasterPage->GetPresObj( mePageKind==PageKind::Notes ? PresObjKind::Notes : PresObjKind::Outline );
        if( pMasterOutline == nullptr )
            pMasterPage->CreateDefaultPresObj( mePageKind == PageKind::Standard ? PresObjKind::Outline : PresObjKind::Notes );
    }

    // create header&footer objects

    if( !bCreate )
        return;

    if( mePageKind != PageKind::Standard )
    {
        SdrObject* pHeader = pMasterPage->GetPresObj( PresObjKind::Header );
        if( pHeader == nullptr )
            pMasterPage->CreateDefaultPresObj( PresObjKind::Header );
    }

    SdrObject* pDate   = pMasterPage->GetPresObj( PresObjKind::DateTime );
    if( pDate == nullptr )
        pMasterPage->CreateDefaultPresObj( PresObjKind::DateTime );

    SdrObject* pFooter = pMasterPage->GetPresObj( PresObjKind::Footer );
    if( pFooter == nullptr )
        pMasterPage->CreateDefaultPresObj( PresObjKind::Footer );

    SdrObject* pNumber = pMasterPage->GetPresObj( PresObjKind::SlideNumber );
    if( pNumber == nullptr )
        pMasterPage->CreateDefaultPresObj( PresObjKind::SlideNumber );
}

namespace {

const o3tl::enumarray<PageKind, char const *> PageKindVector = {
    "PageKind::Standard""PageKind::Notes""PageKind::Handout"
};

const o3tl::enumarray<PresObjKind, const char*> PresObjKindVector = {
    "PRESOBJ_NONE""PRESOBJ_TITLE""PRESOBJ_OUTLINE",
    "PRESOBJ_TEXT" ,"PRESOBJ_GRAPHIC" , "PRESOBJ_OBJECT",
    "PRESOBJ_CHART""PRESOBJ_ORGCHART""PRESOBJ_TABLE",
    "PRESOBJ_PAGE""PRESOBJ_HANDOUT",
    "PRESOBJ_NOTES","PRESOBJ_HEADER""PRESOBJ_FOOTER",
    "PRESOBJ_DATETIME""PRESOBJ_SLIDENUMBER""PRESOBJ_CALC",
    "PRESOBJ_MEDIA"
};

void getPresObjProp( const SdPage& rPage, const char* sObjKind, const char* sPageKind, double presObjPropValue[] )
{
    bool bNoObjectFound = true;  //used to break from outer loop

    const std::vector< Reference<XNode> >& objectInfo = static_castconst SdDrawDocument& ;>(rPage.getSdrModelFromSdrPage()).GetObjectVector();
    forconst Reference<XNode>& objectNode : objectInfo )
    {
        if(bNoObjectFound)
        {
            Reference<XNamedNodeMap> objectattrlist = objectNode->getAttributes();
            Reference<XNode> objectattr = objectattrlist->getNamedItem(u"type"_ustr);
            OUString sObjType = objectattr->getNodeValue();

            if (sObjType.equalsAscii(sObjKind))
            {
                Reference<XNodeList> objectChildren = objectNode->getChildNodes();
                const int objSize = objectChildren->getLength();

                forint j=0; j< objSize; j++)
                {
                    Reference<XNode> obj = objectChildren->item(j);
                    OUString nodename = obj->getNodeName();

                    //check whether child is blank 'text-node' or 'object-prop' node
                    if(nodename == "object-prop")
                    {
                        Reference<XNamedNodeMap> ObjAttributes = obj->getAttributes();
                        Reference<XNode> ObjPageKind = ObjAttributes->getNamedItem(u"pagekind"_ustr);
                        OUString sObjPageKind = ObjPageKind->getNodeValue();

                        if (sObjPageKind.equalsAscii(sPageKind))
                        {
                            Reference<XNode> ObjSizeHeight = ObjAttributes->getNamedItem(u"relative-height"_ustr);
                            OUString sValue = ObjSizeHeight->getNodeValue();
                            presObjPropValue[0] = sValue.toDouble();

                            Reference<XNode> ObjSizeWidth = ObjAttributes->getNamedItem(u"relative-width"_ustr);
                            sValue = ObjSizeWidth->getNodeValue();
                            presObjPropValue[1] = sValue.toDouble();

                            Reference<XNode> ObjPosX = ObjAttributes->getNamedItem(u"relative-posX"_ustr);
                            sValue = ObjPosX->getNodeValue();
                            presObjPropValue[2] = sValue.toDouble();

                            Reference<XNode> ObjPosY = ObjAttributes->getNamedItem(u"relative-posY"_ustr);
                            sValue = ObjPosY->getNodeValue();
                            presObjPropValue[3] = sValue.toDouble();

                            bNoObjectFound = false;
                            break;
                        }
                    }
                }
            }
        }
        else
            break;
    }
}

}

rtl::Reference<SdrObject> SdPage::CreateDefaultPresObj(PresObjKind eObjKind)
{
    if( eObjKind == PresObjKind::Title )
    {
        ::tools::Rectangle aTitleRect( GetTitleRect() );
        return CreatePresObj(PresObjKind::Title, false, aTitleRect);
    }
    else if( eObjKind == PresObjKind::Outline )
    {
        ::tools::Rectangle aLayoutRect( GetLayoutRect() );
        return CreatePresObj( PresObjKind::Outline, false, aLayoutRect);
    }
    else if( eObjKind == PresObjKind::Notes )
    {
        ::tools::Rectangle aLayoutRect( GetLayoutRect() );
        return CreatePresObj( PresObjKind::Notes, false, aLayoutRect);
    }
    else if( (eObjKind == PresObjKind::Footer) || (eObjKind == PresObjKind::DateTime) || (eObjKind == PresObjKind::SlideNumber) || (eObjKind == PresObjKind::Header ) )
    {
        double propvalue[] = {0,0,0,0};
        const char* sObjKind = PresObjKindVector[eObjKind];
        const char* sPageKind = PageKindVector[mePageKind];
        // create footer objects for standard master page
        if( mePageKind == PageKind::Standard )
        {
            const ::tools::Long nLftBorder = GetLeftBorder();
            const ::tools::Long nUppBorder = GetUpperBorder();

            Point aPos ( nLftBorder, nUppBorder );
            Size aSize ( GetSize() );

            aSize.AdjustWidth( -(nLftBorder + GetRightBorder()) );
            aSize.AdjustHeight( -(nUppBorder + GetLowerBorder()) );

            getPresObjProp( *this, sObjKind, sPageKind, propvalue);
            aPos.AdjustX(::tools::Long( aSize.Width() * propvalue[2] ) );
            aPos.AdjustY(::tools::Long( aSize.Height() * propvalue[3] ) );
            aSize.setWidth( ::tools::Long( aSize.Width() * propvalue[1] ) );
            aSize.setHeight( ::tools::Long( aSize.Height() * propvalue[0] ) );

            if(eObjKind == PresObjKind::Header )
            {
                OSL_FAIL( "SdPage::CreateDefaultPresObj() - can't create a header placeholder for a master slide" );
                return nullptr;
            }
            else
            {
                ::tools::Rectangle aRect( aPos, aSize );
                return CreatePresObj( eObjKind, false, aRect );
            }
        }
        else
        {
            // create header&footer objects for handout and notes master
            Size aPageSize ( GetSize() );
            aPageSize.AdjustWidth( -(GetLeftBorder() + GetRightBorder()) );
            aPageSize.AdjustHeight( -(GetUpperBorder() + GetLowerBorder()) );

            Point aPosition ( GetLeftBorder(), GetUpperBorder() );

            getPresObjProp( *this, sObjKind, sPageKind, propvalue);
            int NOTES_HEADER_FOOTER_WIDTH = ::tools::Long(aPageSize.Width() * propvalue[1]);
            int NOTES_HEADER_FOOTER_HEIGHT = ::tools::Long(aPageSize.Height() * propvalue[0]);
            Size aSize( NOTES_HEADER_FOOTER_WIDTH, NOTES_HEADER_FOOTER_HEIGHT );
            Point aPos ( 0 ,0 );
            if( propvalue[2] == 0 )
                aPos.setX( aPosition.X() );
            else
                aPos.setX( aPosition.X() + ::tools::Long( aPageSize.Width() - NOTES_HEADER_FOOTER_WIDTH ) );
            if( propvalue[3] == 0 )
                aPos.setY( aPosition.Y() );
            else
                aPos.setY( aPosition.Y() + ::tools::Long( aPageSize.Height() - NOTES_HEADER_FOOTER_HEIGHT ) );

            ::tools::Rectangle aRect( aPos, aSize );
            return CreatePresObj( eObjKind, false, aRect );
        }
    }
    else
    {
        OSL_FAIL("SdPage::CreateDefaultPresObj() - unknown PRESOBJ kind" );
        return nullptr;
    }
}

void SdPage::DestroyDefaultPresObj(PresObjKind eObjKind)
{
    SdrObject* pObject = GetPresObj( eObjKind );

    if( pObject )
    {
        SdDrawDocument* pDoc(static_cast< SdDrawDocument* >(&getSdrModelFromSdrPage()));
        const bool bUndo = pDoc->IsUndoEnabled();
        if( bUndo )
            pDoc->AddUndo(pDoc->GetSdrUndoFactory().CreateUndoDeleteObject(*pObject));
        SdrObjList* pOL = pObject->getParentSdrObjListFromSdrObject();
        pOL->RemoveObject(pObject->GetOrdNumDirect());
    }
}

/*************************************************************************
|*
|* return title area
|*
\************************************************************************/


::tools::Rectangle SdPage::GetTitleRect() const
{
    ::tools::Rectangle aTitleRect;

    if (mePageKind != PageKind::Handout)
    {
        double propvalue[] = {0,0,0,0};

        /******************************************************************
        * standard- or note page: title area
        ******************************************************************/

        Point aTitlePos ( GetLeftBorder(), GetUpperBorder() );
        Size aTitleSize ( GetSize() );
        aTitleSize.AdjustWidth( -(GetLeftBorder() + GetRightBorder()) );
        aTitleSize.AdjustHeight( -(GetUpperBorder() + GetLowerBorder()) );
        const char* sPageKind = PageKindVector[mePageKind];

        if (mePageKind == PageKind::Standard)
        {
            getPresObjProp( *this , "PRESOBJ_TITLE" ,sPageKind, propvalue);
            aTitlePos.AdjustX(::tools::Long( aTitleSize.Width() * propvalue[2] ) );
            aTitlePos.AdjustY(::tools::Long( aTitleSize.Height() * propvalue[3] ) );
            aTitleSize.setWidth( ::tools::Long( aTitleSize.Width() * propvalue[1] ) );
            aTitleSize.setHeight( ::tools::Long( aTitleSize.Height() * propvalue[0] ) );
        }
        else if (mePageKind == PageKind::Notes)
        {
            Point aPos = aTitlePos;
            getPresObjProp( *this"PRESOBJ_TITLE" ,sPageKind, propvalue);
            aPos.AdjustX(::tools::Long( aTitleSize.Width() * propvalue[2] ) );
            aPos.AdjustY(::tools::Long( aTitleSize.Height() * propvalue[3] ) );

            // limit height
            aTitleSize.setHeight( ::tools::Long( aTitleSize.Height() * propvalue[0] ) );
            aTitleSize.setWidth( ::tools::Long( aTitleSize.Width() * propvalue[1] ) );

            Size aPartArea = aTitleSize;
            Size aSize;
            sal_uInt16 nDestPageNum(GetPageNum());
            SdrPage* pRefPage = nullptr;

            if(nDestPageNum)
            {
                // only decrement if != 0, else we get 0xffff
                nDestPageNum -= 1;
            }

            if(nDestPageNum < getSdrModelFromSdrPage().GetPageCount())
            {
                pRefPage = getSdrModelFromSdrPage().GetPage(nDestPageNum);
            }

            if ( pRefPage )
            {
                // scale actually page size into handout rectangle
                double fH = pRefPage->GetWidth() == 0
                    ? 0 : static_cast<double>(aPartArea.Width())  / pRefPage->GetWidth();
                double fV = pRefPage->GetHeight() == 0
                    ? 0 : static_cast<double>(aPartArea.Height()) / pRefPage->GetHeight();

                if ( fH > fV )
                    fH = fV;
                aSize.setWidth( static_cast<::tools::Long>(fH * pRefPage->GetWidth()) );
                aSize.setHeight( static_cast<::tools::Long>(fH * pRefPage->GetHeight()) );

                aPos.AdjustX((aPartArea.Width() - aSize.Width()) / 2 );
                aPos.AdjustY((aPartArea.Height()- aSize.Height())/ 2 );
            }

            aTitlePos = aPos;
            aTitleSize = aSize;
        }

        aTitleRect.SetPos(aTitlePos);
        aTitleRect.SetSize(aTitleSize);
    }

    return aTitleRect;
}

/*************************************************************************
|*
|* return outline area
|*
\************************************************************************/


::tools::Rectangle SdPage::GetLayoutRect() const
{
    ::tools::Rectangle aLayoutRect;

    if (mePageKind != PageKind::Handout)
    {
        double propvalue[] = {0,0,0,0};

        Point aLayoutPos ( GetLeftBorder(), GetUpperBorder() );
        Size aLayoutSize ( GetSize() );
        aLayoutSize.AdjustWidth( -(GetLeftBorder() + GetRightBorder()) );
        aLayoutSize.AdjustHeight( -(GetUpperBorder() + GetLowerBorder()) );
        const char* sPageKind = PageKindVector[mePageKind];

        if (mePageKind == PageKind::Standard)
        {
            getPresObjProp( *this ,"PRESOBJ_OUTLINE", sPageKind, propvalue);
            aLayoutPos.AdjustX(::tools::Long( aLayoutSize.Width() * propvalue[2] ) );
            aLayoutPos.AdjustY(::tools::Long( aLayoutSize.Height() * propvalue[3] ) );
            aLayoutSize.setWidth( ::tools::Long( aLayoutSize.Width() * propvalue[1] ) );
            aLayoutSize.setHeight( ::tools::Long( aLayoutSize.Height() * propvalue[0] ) );
            aLayoutRect.SetPos(aLayoutPos);
            aLayoutRect.SetSize(aLayoutSize);
        }
        else if (mePageKind == PageKind::Notes)
        {
            getPresObjProp( *this"PRESOBJ_NOTES", sPageKind, propvalue);
            aLayoutPos.AdjustX(::tools::Long( aLayoutSize.Width() * propvalue[2] ) );
            aLayoutPos.AdjustY(::tools::Long( aLayoutSize.Height() * propvalue[3] ) );
            aLayoutSize.setWidth( ::tools::Long( aLayoutSize.Width() * propvalue[1] ) );
            aLayoutSize.setHeight( ::tools::Long( aLayoutSize.Height() * propvalue[0] ) );
            aLayoutRect.SetPos(aLayoutPos);
            aLayoutRect.SetSize(aLayoutSize);
        }
    }

    return aLayoutRect;
}

/**************************************************************************
|*
|* assign an AutoLayout
|*
\*************************************************************************/


const int MAX_PRESOBJS = 7; // maximum number of presentation objects per layout
const int VERTICAL = 0x8000;

static constexpr PresObjKind operator|(PresObjKind e, int x)
{
    return static_cast<PresObjKind>(static_cast<int>(e) | x);
}

namespace {

struct LayoutDescriptor
{
    PresObjKind meKind[MAX_PRESOBJS];
    bool mbVertical[MAX_PRESOBJS];

    LayoutDescriptor( PresObjKind k0 = PresObjKind::NONE, PresObjKind k1 = PresObjKind::NONE, PresObjKind k2 = PresObjKind::NONE, PresObjKind k3 = PresObjKind::NONE, PresObjKind k4 = PresObjKind::NONE, PresObjKind k5 = PresObjKind::NONE, PresObjKind k6 = PresObjKind::NONE );
};

}

LayoutDescriptor::LayoutDescriptor( PresObjKind k0, PresObjKind k1, PresObjKind k2, PresObjKind k3, PresObjKind k4, PresObjKind k5, PresObjKind k6 )
{
    auto removeVertical = [] (PresObjKind k) { return static_cast<PresObjKind>(static_cast<int>(k) & ~VERTICAL); };
    auto isVertical = [] (PresObjKind k) { return bool(static_cast<int>(k) & VERTICAL); };
    meKind[0] = removeVertical(k0); mbVertical[0] = isVertical(k0);
    meKind[1] = removeVertical(k1); mbVertical[1] = isVertical(k1);
    meKind[2] = removeVertical(k2); mbVertical[2] = isVertical(k2);
    meKind[3] = removeVertical(k3); mbVertical[3] = isVertical(k3);
    meKind[4] = removeVertical(k4); mbVertical[4] = isVertical(k4);
    meKind[5] = removeVertical(k5); mbVertical[5] = isVertical(k5);
    meKind[6] = removeVertical(k6); mbVertical[6] = isVertical(k6);
}

static const LayoutDescriptor& GetLayoutDescriptor( AutoLayout eLayout )
{
    static const LayoutDescriptor aLayouts[AUTOLAYOUT_END-AUTOLAYOUT_START] =
    {
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Text ),                                 // AUTOLAYOUT_TITLE
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline ),                              // AUTOLAYOUT_TITLE_CONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline ),                              // AUTOLAYOUT_CHART
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_TITLE_2CONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_TEXTCHART
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline ),                              // AUTOLAYOUT_ORG
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_TEXTCLbIP
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_CHARTTEXT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline ),                              // AUTOLAYOUT_TAB
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_CLIPTEXT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_TEXTOBJ
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Object ),                               // AUTOLAYOUT_OBJ
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline, PresObjKind::Outline ),    // AUTOLAYOUT_TITLE_CONTENT_2CONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_TEXTOBJ
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_TITLE_CONTENT_OVER_CONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline, PresObjKind::Outline ),    // AUTOLAYOUT_TITLE_2CONTENT_CONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline, PresObjKind::Outline ),    // AUTOLAYOUT_TITLE_2CONTENT_OVER_CONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline ),             // AUTOLAYOUT_TEXTOVEROBJ
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline,                   // AUTOLAYOUT_TITLE_4CONTENT
            PresObjKind::Outline, PresObjKind::Outline ),
        LayoutDescriptor( PresObjKind::Title, PresObjKind::NONE ),                                 // AUTOLAYOUT_TITLE_ONLY
        LayoutDescriptor( PresObjKind::NONE ),                                                // AUTOLAYOUT_NONE
        LayoutDescriptor( PresObjKind::Page, PresObjKind::Notes ),                                 // AUTOLAYOUT_NOTES
        LayoutDescriptor( ),                                                              // AUTOLAYOUT_HANDOUT1
        LayoutDescriptor( ),                                                              // AUTOLAYOUT_HANDOUT2
        LayoutDescriptor( ),                                                              // AUTOLAYOUT_HANDOUT3
        LayoutDescriptor( ),                                                              // AUTOLAYOUT_HANDOUT4
        LayoutDescriptor( ),                                                              // AUTOLAYOUT_HANDOUT6
        LayoutDescriptor( PresObjKind::Title|VERTICAL, PresObjKind::Outline|VERTICAL, PresObjKind::Outline ),// AUTOLAYOUT_VTITLE_VCONTENT_OVER_VCONTENT
        LayoutDescriptor( PresObjKind::Title|VERTICAL, PresObjKind::Outline|VERTICAL ),            // AUTOLAYOUT_VTITLE_VCONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline|VERTICAL ),                     // AUTOLAYOUT_TITLE_VCONTENT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline|VERTICAL, PresObjKind::Outline|VERTICAL ),   // AUTOLAYOUT_TITLE_2VTEXT
        LayoutDescriptor( ),                                                              // AUTOLAYOUT_HANDOUT9
        LayoutDescriptor( PresObjKind::Text, PresObjKind::NONE ),                                 // AUTOLAYOUT_ONLY_TEXT
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline,               // AUTOLAYOUT_4CLIPART
            PresObjKind::Graphic, PresObjKind::Graphic ),
        LayoutDescriptor( PresObjKind::Title, PresObjKind::Outline, PresObjKind::Outline,              // AUTOLAYOUT_TITLE_6CONTENT
            PresObjKind::Outline, PresObjKind::Outline, PresObjKind::Outline, PresObjKind::Outline )
    };

    if( (eLayout < AUTOLAYOUT_START) || (eLayout >= AUTOLAYOUT_END) )
        eLayout = AUTOLAYOUT_NONE;

    return aLayouts[ eLayout - AUTOLAYOUT_START ];
}

static OUString enumtoString(AutoLayout aut)
{
    OUString retstr;
    switch (aut)
    {
        case AUTOLAYOUT_TITLE_CONTENT:
            retstr="AUTOLAYOUT_TITLE_CONTENT";
            break;
        case AUTOLAYOUT_TITLE_CONTENT_OVER_CONTENT:
            retstr="AUTOLAYOUT_TITLE_CONTENT_OVER_CONTENT";
            break;
        case AUTOLAYOUT_TITLE_CONTENT_2CONTENT:
            retstr="AUTOLAYOUT_TITLE_CONTENT_2CONTENT";
            break;
        case AUTOLAYOUT_TITLE_4CONTENT:
            retstr="AUTOLAYOUT_TITLE_4CONTENT";
            break;
        case AUTOLAYOUT_ONLY_TEXT:
            retstr="AUTOLAYOUT_ONLY_TEXT";
            break;
        case AUTOLAYOUT_TITLE_ONLY:
            retstr="AUTOLAYOUT_TITLE_ONLY";
            break;
        case AUTOLAYOUT_TITLE_6CONTENT:
            retstr="AUTOLAYOUT_TITLE_6CONTENT";
            break;
        case AUTOLAYOUT_START:
            retstr="AUTOLAYOUT_START";
            break;
        case AUTOLAYOUT_TITLE_2CONTENT_CONTENT:
            retstr="AUTOLAYOUT_TITLE_2CONTENT_CONTENT";
            break;
        case AUTOLAYOUT_TITLE_2CONTENT_OVER_CONTENT:
            retstr="AUTOLAYOUT_TITLE_2CONTENT_OVER_CONTENT";
            break;
        case AUTOLAYOUT_TITLE_2CONTENT:
            retstr="AUTOLAYOUT_TITLE_2CONTENT";
            break;
        case AUTOLAYOUT_VTITLE_VCONTENT:
            retstr="AUTOLAYOUT_VTITLE_VCONTENT";
            break;
        case AUTOLAYOUT_VTITLE_VCONTENT_OVER_VCONTENT:
            retstr="AUTOLAYOUT_VTITLE_VCONTENT_OVER_VCONTENT";
            break;
        case AUTOLAYOUT_TITLE_VCONTENT:
            retstr="AUTOLAYOUT_TITLE_VCONTENT";
            break;
        case AUTOLAYOUT_TITLE_2VTEXT:
            retstr="AUTOLAYOUT_TITLE_2VTEXT";
            break;
        default:
            retstr="unknown";
            break;
        // case AUTOLAYOUT_TITLE_4SCONTENT:            return "AUTOLAYOUT_TITLE_4SCONTENT";
    }
    return retstr;
}

AutoLayout SdPage::stringToAutoLayout(std::u16string_view rLayoutName)
{
    for (int i = AUTOLAYOUT_START; i < AUTOLAYOUT_END; i++)
    {
        AutoLayout nLId = static_cast<AutoLayout>(i);
        if (autoLayoutToString(nLId) == rLayoutName)
        {
            return nLId;
        }
    }
    return AUTOLAYOUT_END;
}

OUString SdPage::autoLayoutToString(AutoLayout nLayoutId)
{
    if (nLayoutId == AUTOLAYOUT_TITLE)
    {
        return "AUTOLAYOUT_TITLE";
    }
    return enumtoString(nLayoutId);
}

static void CalcAutoLayoutRectangles( SdPage const & rPage,::tools::Rectangle* rRectangle ,const OUString& sLayoutType )
{
    ::tools::Rectangle aTitleRect;
    ::tools::Rectangle aLayoutRect;

    if( rPage.GetPageKind() != PageKind::Handout )
    {
        SdPage& rMasterPage = static_cast<SdPage&>(rPage.TRG_GetMasterPage());
        SdrObject* pMasterTitle = rMasterPage.GetPresObj( PresObjKind::Title );
        SdrObject* pMasterSubTitle = rMasterPage.GetPresObj( PresObjKind::Text );
        SdrObject* pMasterOutline = rMasterPage.GetPresObj( rPage.GetPageKind()==PageKind::Notes ? PresObjKind::Notes : PresObjKind::Outline );

        if( pMasterTitle )
            aTitleRect = pMasterTitle->GetLogicRect();

        if (aTitleRect.IsEmpty() )
            aTitleRect = rPage.GetTitleRect();
        if( pMasterSubTitle )
            aLayoutRect = pMasterSubTitle->GetLogicRect();
        else if( pMasterOutline )
            aLayoutRect = pMasterOutline->GetLogicRect();

        if (aLayoutRect.IsEmpty() )
            aLayoutRect = rPage.GetLayoutRect();
    }

    rRectangle[0] = aTitleRect;
    forint i = 1; i < MAX_PRESOBJS; i++ )
        rRectangle[i] = aLayoutRect;

    const Point aTitlePos( aTitleRect.TopLeft() );
    const Size  aLayoutSize( aLayoutRect.GetSize() );
    const Point aLayoutPos( aLayoutRect.TopLeft() );
    double propvalue[] = {0,0,0,0};

    const std::vector< Reference<XNode> >& layoutInfo = static_castconst SdDrawDocument& ;>(rPage.getSdrModelFromSdrPage()).GetLayoutVector();
    auto aIter = std::find_if(layoutInfo.begin(), layoutInfo.end(),
        [&sLayoutType](const Reference<XNode>& layoutNode) {
            Reference<XNamedNodeMap> layoutAttrList = layoutNode->getAttributes();

            // get the attribute value of layout (i.e it's type)
            OUString sLayoutAttName = layoutAttrList->getNamedItem(u"type"_ustr)->getNodeValue();
            return sLayoutAttName == sLayoutType;
        });
    if (aIter == layoutInfo.end())
        return;

    int count=0;
    const Reference<XNode>& layoutNode = *aIter;
    Reference<XNodeList> layoutChildren = layoutNode->getChildNodes();
    const int presobjsize = layoutChildren->getLength();
    forint j=0; j< presobjsize ; j++)
    {
        OUString nodename;
        Reference<XNode> presobj = layoutChildren->item(j);
        nodename=presobj->getNodeName();

        //check whether child is blank 'text-node' or 'presobj' node
        if(nodename == "presobj")
        {
            // TODO: rework sd to permit arbitrary number of presentation objects
            assert(count < MAX_PRESOBJS);

            Reference<XNamedNodeMap> presObjAttributes = presobj->getAttributes();

            Reference<XNode> presObjSizeHeight = presObjAttributes->getNamedItem(u"relative-height"_ustr);
            OUString sValue = presObjSizeHeight->getNodeValue();
            propvalue[0] = sValue.toDouble();

            Reference<XNode> presObjSizeWidth = presObjAttributes->getNamedItem(u"relative-width"_ustr);
            sValue = presObjSizeWidth->getNodeValue();
            propvalue[1] = sValue.toDouble();

            Reference<XNode> presObjPosX = presObjAttributes->getNamedItem(u"relative-posX"_ustr);
            sValue = presObjPosX->getNodeValue();
            propvalue[2] = sValue.toDouble();

            Reference<XNode> presObjPosY = presObjAttributes->getNamedItem(u"relative-posY"_ustr);
            sValue = presObjPosY->getNodeValue();
            propvalue[3] = sValue.toDouble();

            if(count == 0)
            {
                Size aSize ( aTitleRect.GetSize() );
                aSize.setHeight( basegfx::fround<::tools::Long>(aSize.Height() * propvalue[0]) );
                aSize.setWidth( basegfx::fround<::tools::Long>(aSize.Width() * propvalue[1]) );
                Point aPos( basegfx::fround<::tools::Long>(aTitlePos.X() +(aSize.Width() * propvalue[2])),
                            basegfx::fround<::tools::Long>(aTitlePos.Y() + (aSize.Height() * propvalue[3])) );
                rRectangle[count] = ::tools::Rectangle(aPos, aSize);
                count = count+1;
            }
            else
            {
                Size aSize( basegfx::fround<::tools::Long>(aLayoutSize.Width() * propvalue[1]),
                            basegfx::fround<::tools::Long>(aLayoutSize.Height() * propvalue[0]) );
                Point aPos( basegfx::fround<::tools::Long>(aLayoutPos.X() +(aSize.Width() * propvalue[2])),
                            basegfx::fround<::tools::Long>(aLayoutPos.Y() + (aSize.Height() * propvalue[3])) );
                rRectangle[count] = ::tools::Rectangle (aPos, aSize);
                count = count+1;
            }
        }
    }
}

static void findAutoLayoutShapesImpl( SdPage& rPage, const LayoutDescriptor& rDescriptor, std::array<SdrObject*, MAX_PRESOBJS>& rShapes, bool bInit, bool bSwitchLayout )
{
    // init list of indexes for each presentation shape kind
    // this is used to find subsequent shapes with the same presentation shape kind
    o3tl::enumarray<PresObjKind,int> PresObjIndex;
    PresObjIndex.fill(1);

    bool bMissing = false;

    // for each entry in the layoutdescriptor, arrange a presentation shape
    for (int i = 0; (i < MAX_PRESOBJS) && (rDescriptor.meKind[i] != PresObjKind::NONE); i++)
    {
        PresObjKind eKind = rDescriptor.meKind[i];
        SdrObject* pObj = nullptr;
        while( (pObj = rPage.GetPresObj( eKind, PresObjIndex[eKind], true )) != nullptr )
        {
            PresObjIndex[eKind]++; // on next search for eKind, find next shape with same eKind

            if( !bSwitchLayout || !pObj->IsEmptyPresObj() )
            {
                rShapes[i] = pObj;
                break;
            }
        }

        if( !pObj )
            bMissing = true;
    }

    if( !(bMissing && bInit) )
        return;

    // for each entry in the layoutdescriptor, look for an alternative shape
    for (int i = 0; (i < MAX_PRESOBJS) && (rDescriptor.meKind[i] != PresObjKind::NONE); i++)
    {
        if( rShapes[i] )
            continue;

        PresObjKind eKind = rDescriptor.meKind[i];

        SdrObject* pObj = nullptr;
        bool bFound = false;

        const size_t nShapeCount = rPage.GetObjCount();
        for(size_t nShapeIndex = 0; nShapeIndex < nShapeCount && !bFound; ++nShapeIndex )
        {
            pObj = rPage.GetObj(nShapeIndex);

            if( pObj->IsEmptyPresObj() )
                continue;

            if( pObj->GetObjInventor() != SdrInventor::Default )
                continue;

            // do not reuse shapes that are already part of the layout
            if( std::find( rShapes.begin(), rShapes.end(), pObj ) != rShapes.end() )
                continue;

            bool bPresStyle = pObj->GetStyleSheet() && (pObj->GetStyleSheet()->GetFamily() == SfxStyleFamily::Page);
            SdrObjKind eSdrObjKind = pObj->GetObjIdentifier();

            switch( eKind )
            {
            case PresObjKind::Title:
                bFound = eSdrObjKind == SdrObjKind::TitleText;
                break;
            case PresObjKind::Table:
                bFound = eSdrObjKind == SdrObjKind::Table;
                break;
            case PresObjKind::Media:
                bFound = eSdrObjKind == SdrObjKind::Media;
                break;
            case PresObjKind::Outline:
                bFound = (eSdrObjKind == SdrObjKind::OutlineText) ||
                         ((eSdrObjKind == SdrObjKind::Text) && bPresStyle) ||
                         (eSdrObjKind == SdrObjKind::Table) || (eSdrObjKind == SdrObjKind::Media) || (eSdrObjKind == SdrObjKind::Graphic) || (eSdrObjKind == SdrObjKind::OLE2);
                break;
            case PresObjKind::Graphic:
                bFound = eSdrObjKind == SdrObjKind::Graphic;
                break;
            case PresObjKind::Object:
                if( eSdrObjKind == SdrObjKind::OLE2 )
                {
                    SdrOle2Obj* pOle2 = dynamic_cast< SdrOle2Obj* >( pObj );
                    if( pOle2 )
                    {
                        if( pOle2->IsEmpty() )
                            bFound = true;
                        else
                        {
                            ::comphelper::IEmbeddedHelper* pPersist(rPage.getSdrModelFromSdrPage().GetPersist());

                            if( pPersist )
                            {
                                uno::Reference < embed::XEmbeddedObject > xObject = pPersist->getEmbeddedObjectContainer().
                                        GetEmbeddedObject( pOle2->GetPersistName() );

                                // TODO CL->KA: Why is this not working anymore?
                                if( xObject.is() )
                                {
                                    SvGlobalName aClassId( xObject->getClassID() );

                                    const SvGlobalName aAppletClassId( SO3_APPLET_CLASSID );
                                    const SvGlobalName aPluginClassId( SO3_PLUGIN_CLASSID );
                                    const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID );

                                    if( aPluginClassId != aClassId && aAppletClassId != aClassId && aIFrameClassId != aClassId )
                                    {
                                        bFound = true;
                                    }
                                }
                            }
                         }
                    }
                }
                break;
            case PresObjKind::Chart:
            case PresObjKind::Calc:
                if( eSdrObjKind == SdrObjKind::OLE2 )
                {
                    SdrOle2Obj* pOle2 = dynamic_cast< SdrOle2Obj* >( pObj );
                    if( pOle2 )
                    {
                        if(
                            ((eKind == PresObjKind::Chart) &&
                                ( pOle2->GetProgName() == "StarChart" || pOle2->IsChart() ) )
                            ||
                            ((eKind == PresObjKind::Calc) &&
                                ( pOle2->GetProgName() == "StarCalc" || pOle2->IsCalc() ) ) )
                        {
                            bFound = true;
                        }
                    }
                    break;
                }
                else if( eSdrObjKind == SdrObjKind::Table )
                {
                    bFound = true;
                }
                break;
            case PresObjKind::Page:
            case PresObjKind::Handout:
                bFound = eSdrObjKind == SdrObjKind::Page;
                break;
            case PresObjKind::Notes:
            case PresObjKind::Text:
                bFound = (bPresStyle && (eSdrObjKind == SdrObjKind::Text)) || (eSdrObjKind == SdrObjKind::OutlineText);
                break;
            default:
                break;
            }
        }

        if( bFound )
            rShapes[i] = pObj;
    }
}

void SdPage::SetAutoLayout(AutoLayout eLayout, bool bInit, bool bCreate )
{
    sd::ScopeLockGuard aGuard( maLockAutoLayoutArrangement );

    const bool bSwitchLayout = eLayout != GetAutoLayout();

    SfxUndoManager* pUndoManager(static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetUndoManager());
    const bool bUndo = pUndoManager && pUndoManager->IsInListAction() && IsInserted();

    meAutoLayout = eLayout;

    // if needed, creates and initialises the presentation shapes on this slides master page
    CreateTitleAndLayout(bInit, bCreate);

    if((meAutoLayout == AUTOLAYOUT_NONE && maPresentationShapeList.isEmpty()) || mbMaster)
    {
        // MasterPage or no layout and no presentation shapes available, nothing to do
        return;
    }

    ::tools::Rectangle aRectangle[MAX_PRESOBJS];
    const LayoutDescriptor& aDescriptor = GetLayoutDescriptor( meAutoLayout );
    OUString sLayoutName( enumtoString(meAutoLayout) );
    CalcAutoLayoutRectangles( *this, aRectangle, sLayoutName);

    o3tl::sorted_vector< SdrObject* > aUsedPresentationObjects;

    std::array<SdrObject*, MAX_PRESOBJS > aLayoutShapes;
    aLayoutShapes.fill(nullptr);
    findAutoLayoutShapesImpl( *this, aDescriptor, aLayoutShapes, bInit, bSwitchLayout );

    // for each entry in the layoutdescriptor, arrange a presentation shape
    for (int i = 0; (i < MAX_PRESOBJS) && (aDescriptor.meKind[i] != PresObjKind::NONE); i++)
    {
        PresObjKind eKind = aDescriptor.meKind[i];
        SdrObject* pObj = InsertAutoLayoutShape( aLayoutShapes[i], eKind, aDescriptor.mbVertical[i], aRectangle[i], bInit );
        if( pObj )
            aUsedPresentationObjects.insert(pObj); // remember that we used this empty shape
    }

    // now delete all empty presentation objects that are no longer used by the new layout
    if( !bInit )
        return;

    maPresentationShapeList.seekShape(0);

    rtl::Reference<SdrObject> pObj;
    while( (pObj = maPresentationShapeList.getNextShape()) )
    {
        if( aUsedPresentationObjects.count(pObj.get()) == 0 )
        {

--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=93 G=92

¤ Dauer der Verarbeitung: 0.28 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge