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 = true ; break ;
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_cast < const SdDrawDocument& >(rPage.getSdrModelFromSdrPage()).GetObjectVector();
for ( const 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();
for ( int 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;
for ( int 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_cast < const 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();
for ( int 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.9 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland
2026-04-02