/* -*- 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 <svx/svdobj.hxx>
#include <config_features.h>
#include <sal/config.h>
#include <com/sun/star/text/RelOrientation.hpp>
#include <com/sun/star/frame/XTerminateListener.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/range/b2drange.hxx>
#include <drawinglayer/processor2d/contourextractor2d.hxx>
#include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
#include <comphelper/processfactory.hxx>
#include <editeng/editeng.hxx>
#include <editeng/outlobj.hxx>
#include <o3tl/deleter.hxx>
#include <math.h>
#include <svl/grabbagitem.hxx>
#include <tools/bigint.hxx>
#include <tools/helpers.hxx>
#include <comphelper/configuration.hxx>
#include <vcl/canvastools.hxx>
#include <vcl/ptrstyle.hxx>
#include <vector>
#include <svx/svdotable.hxx>
#include <svx/sdr/contact/displayinfo.hxx>
#include <sdr/contact/objectcontactofobjlistpainter.hxx>
#include <svx/sdr/contact/viewcontactofsdrobj.hxx>
#include <sdr/properties/emptyproperties.hxx>
#include <svx/annotation/ObjectAnnotationData.hxx>
#include <svx/sdrhittesthelper.hxx>
#include <svx/sdrobjectuser.hxx>
#include <svx/sdrobjectfilter.hxx>
#include <svx/svddrag.hxx>
#include <svx/svdetc.hxx>
#include <svx/svdhdl.hxx>
#include <svx/svditer.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdoashp.hxx>
#include <svx/svdocapt.hxx>
#include <svx/svdocirc.hxx>
#include <svx/svdoedge.hxx>
#include <svx/svdograf.hxx>
#include <svx/svdogrp.hxx>
#include <svx/svdomeas.hxx>
#include <svx/svdomedia.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdopage.hxx>
#include <svx/svdopath.hxx>
#include <svx/svdorect.hxx>
#include <svx/svdotext.hxx>
#include <svx/svdouno.hxx>
#include <svx/svdovirt.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdpool.hxx>
#include <svx/strings.hrc>
#include <svx/dialmgr.hxx>
#include <svx/svdtrans.hxx>
#include <svx/svdundo.hxx>
#include <svx/svdview.hxx>
#include <sxlayitm.hxx>
#include <sxlogitm.hxx>
#include <sxmovitm.hxx>
#include <sxoneitm.hxx>
#include <sxopitm.hxx>
#include <sxreoitm.hxx>
#include <sxrooitm.hxx>
#include <sxsaitm.hxx>
#include <sxsoitm.hxx>
#include <sxtraitm.hxx>
#include <svx/unopage.hxx>
#include <svx/unoshape.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xflclit.hxx>
#include <svx/xfltrit.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlnclit.hxx>
#include <svx/xlnedwit.hxx>
#include <svx/xlnstwit.hxx>
#include <svx/xlntrit.hxx>
#include <svx/xlnwtit.hxx>
#include <svx/svdglue.hxx>
#include <svx/svdsob.hxx>
#include <svdobjplusdata.hxx>
#include <svdobjuserdatalist.hxx>
#include <optional>
#include <libxml/xmlwriter.h>
#include <memory>
#include <svx/scene3d.hxx>
#include <rtl/character.hxx>
#include <tools/UnitConversion.hxx>
#include <o3tl/string_view.hxx>
#include <tools/lazydelete.hxx>
using namespace ::com::sun::star;
SdrObjUserCall::~SdrObjUserCall()
{
}
void SdrObjUserCall::Changed(
const SdrObject&
/*rObj*/, SdrUserCallType /*eType*/, const tools::Rectangle& /*rOldBoundRect*/)
{
}
void const * SdrObjUserCall::GetPDFAnchorStructureElementKey(SdrObject
const &)
{
return nullptr;
}
SdrObjMacroHitRec::SdrObjMacroHitRec() :
pVisiLayer(nullptr),
pPageView(nullptr),
nTol(0) {}
SdrObjUserData::SdrObjUserData(SdrInventor nInv, sal_uInt16 nId) :
m_nInventor(nInv),
m_nIdentifier(nId) {}
SdrObjUserData::SdrObjUserData(
const SdrObjUserData& rData) :
m_nInventor(rData.m_nInventor),
m_nIdentifier(rData.m_nIdentifier) {}
SdrObjUserData::~SdrObjUserData() {}
SdrObjGeoData::SdrObjGeoData():
bMovProt(
false ),
bSizProt(
false ),
bNoPrint(
false ),
bClosedObj(
false ),
mbVisible(
true ),
mnLayerID(0)
{
}
SdrObjGeoData::~SdrObjGeoData()
{
}
SdrObjTransformInfoRec::SdrObjTransformInfoRec() :
bMoveAllowed(
true ),
bResizeFreeAllowed(
true ),
bResizePropAllowed(
true ),
bRotateFreeAllowed(
true ),
bRotate90Allowed(
true ),
bMirrorFreeAllowed(
true ),
bMirror45Allowed(
true ),
bMirror90Allowed(
true ),
bTransparenceAllowed(
true ),
bShearAllowed(
true ),
bEdgeRadiusAllowed(
true ),
bNoOrthoDesired(
true ),
bNoContortion(
true ),
bCanConvToPath(
true ),
bCanConvToPoly(
true ),
bCanConvToContour(
false ),
bCanConvToPathLineToArea(
true ),
bCanConvToPolyLineToArea(
true ) {}
struct SdrObject::Impl
{
sdr::ObjectUserVector maObjectUsers;
std::optional<
double > mnRelativeWidth;
std::optional<
double > mnRelativeHeight;
sal_Int16 meRelativeWidthRelation;
sal_Int16 meRelativeHeightRelation;
Impl() :
meRelativeWidthRelation(text::RelOrientation::PAGE_FRAME),
meRelativeHeightRelation(text::RelOrientation::PAGE_FRAME) {}
};
const std::shared_ptr< svx::diagram::IDiagramHelper >& SdrObject::getDiagramHelper
() const
{
static std::shared_ptr< svx::diagram::IDiagramHelper > aEmpty;
return aEmpty;
}
// BaseProperties section
sdr::properties::BaseProperties& SdrObject::GetProperties() const
{
if (!mpProperties)
{
// CAUTION(!) Do *not* call this during SdrObject construction,
// that will lead to wrong type-casts (dependent on constructor-level)
// and thus eventually create the wrong sdr::properties (!). Is there
// a way to check if on the stack is a SdrObject-constructor (?)
const_cast < SdrObject* >(this )->mpProperties =
const_cast < SdrObject* >(this )->CreateObjectSpecificProperties();
}
return *mpProperties;
}
// ObjectUser section
void SdrObject::AddObjectUser(sdr::ObjectUser& rNewUser)
{
mpImpl->maObjectUsers.push_back(&rNewUser);
}
void SdrObject::RemoveObjectUser(sdr::ObjectUser& rOldUser)
{
const sdr::ObjectUserVector::iterator aFindResult =
std::find(mpImpl->maObjectUsers.begin(), mpImpl->maObjectUsers.end(), &rOldUser);
if (aFindResult != mpImpl->maObjectUsers.end())
{
mpImpl->maObjectUsers.erase(aFindResult);
}
}
// DrawContact section
std::unique_ptr<sdr::contact::ViewContact> SdrObject::CreateObjectSpecificViewContact()
{
return std::make_unique<sdr::contact::ViewContactOfSdrObj>(*this );
}
sdr::contact::ViewContact& SdrObject::GetViewContact() const
{
if (!mpViewContact)
{
const_cast < SdrObject* >(this )->mpViewContact =
const_cast < SdrObject* >(this )->CreateObjectSpecificViewContact();
}
return *mpViewContact;
}
// DrawContact support: Methods for handling Object changes
void SdrObject::ActionChanged() const
{
// Do necessary ViewContact actions
GetViewContact().ActionChanged();
}
SdrPage* SdrObject::getSdrPageFromSdrObject() const
{
if (SdrObjList* pParentList = getParentSdrObjListFromSdrObject())
{
return pParentList->getSdrPageFromSdrObjList();
}
return nullptr;
}
SdrModel& SdrObject::getSdrModelFromSdrObject() const
{
return mrSdrModelFromSdrObject;
}
void SdrObject::setParentOfSdrObject(SdrObjList* pNewObjList)
{
assert(!pNewObjList || mpParentOfSdrObject != pNewObjList);
if (mpParentOfSdrObject == pNewObjList)
return ;
// we need to be removed from the old parent before we are attached to the new parent
assert(bool (mpParentOfSdrObject) != bool (pNewObjList) && "may only transition empty->full or full->empty" );
// remember current page
SdrPage* pOldPage(getSdrPageFromSdrObject());
// set new parent
mpParentOfSdrObject = pNewObjList;
// get new page
SdrPage* pNewPage(getSdrPageFromSdrObject());
// broadcast page change over objects if needed
if (pOldPage != pNewPage)
{
handlePageChange(pOldPage, pNewPage);
}
}
SdrObjList* SdrObject::getParentSdrObjListFromSdrObject() const
{
return mpParentOfSdrObject;
}
SdrObjList* SdrObject::getChildrenOfSdrObject() const
{
// default has no children
return nullptr;
}
void SdrObject::SetBoundRectDirty()
{
resetOutRectangle();
}
void impAddIncarnatedSdrObjectToSdrModel(SdrObject& rSdrObject, SdrModel& rSdrModel)
{
rSdrModel.maAllIncarnatedObjects.insert(&rSdrObject);
}
void impRemoveIncarnatedSdrObjectToSdrModel(SdrObject& rSdrObject, SdrModel& rSdrModel)
{
if (!rSdrModel.maAllIncarnatedObjects.erase(&rSdrObject))
{
assert(false && "SdrObject::~SdrObject: Destructed incarnation of SdrObject not member of this SdrModel (!)" );
}
}
SdrObject::SdrObject(SdrModel& rSdrModel)
: mpFillGeometryDefiningShape(nullptr)
, mrSdrModelFromSdrObject(rSdrModel)
, m_pUserCall(nullptr)
, mpImpl(new Impl)
, mpParentOfSdrObject(nullptr)
, m_nOrdNum(0)
, mnNavigationPosition(SAL_MAX_UINT32)
, mnLayerID(0)
, mpSvxShape( nullptr )
, mbDoNotInsertIntoPageAutomatically(false )
{
m_bVirtObj =false ;
m_bSnapRectDirty =true ;
m_bMovProt =false ;
m_bSizProt =false ;
m_bNoPrint =false ;
m_bEmptyPresObj =false ;
m_bNotVisibleAsMaster=false ;
m_bClosedObj =false ;
mbVisible = true ;
// #i25616#
mbLineIsOutsideGeometry = false ;
// #i25616#
mbSupportTextIndentingOnLineWidthChange = false ;
m_bIsEdge=false ;
m_bIs3DObj=false ;
m_bMarkProt=false ;
m_bIsUnoObj=false ;
impAddIncarnatedSdrObjectToSdrModel(*this , getSdrModelFromSdrObject());
}
SdrObject::SdrObject(SdrModel& rSdrModel, SdrObject const & rSource)
: mpFillGeometryDefiningShape(nullptr)
, mrSdrModelFromSdrObject(rSdrModel)
, m_pUserCall(nullptr)
, mpImpl(new Impl)
, mpParentOfSdrObject(nullptr)
, m_nOrdNum(0)
, mnNavigationPosition(SAL_MAX_UINT32)
, mnLayerID(0)
, mpSvxShape( nullptr )
, mbDoNotInsertIntoPageAutomatically(false )
{
m_bVirtObj =false ;
m_bSnapRectDirty =true ;
m_bMovProt =false ;
m_bSizProt =false ;
m_bNoPrint =false ;
m_bEmptyPresObj =false ;
m_bNotVisibleAsMaster=false ;
m_bClosedObj =false ;
mbVisible = true ;
// #i25616#
mbLineIsOutsideGeometry = false ;
// #i25616#
mbSupportTextIndentingOnLineWidthChange = false ;
m_bIsEdge=false ;
m_bIs3DObj=false ;
m_bMarkProt=false ;
m_bIsUnoObj=false ;
mpProperties.reset();
mpViewContact.reset();
// The CloneSdrObject() method uses the local copy constructor from the individual
// sdr::properties::BaseProperties class. Since the target class maybe for another
// draw object, an SdrObject needs to be provided, as in the normal constructor.
mpProperties = rSource.GetProperties().Clone(*this );
setOutRectangle(rSource.getOutRectangle());
mnLayerID = rSource.mnLayerID;
m_aAnchor =rSource.m_aAnchor;
m_bVirtObj=rSource.m_bVirtObj;
m_bSizProt=rSource.m_bSizProt;
m_bMovProt=rSource.m_bMovProt;
m_bNoPrint=rSource.m_bNoPrint;
mbVisible=rSource.mbVisible;
m_bMarkProt=rSource.m_bMarkProt;
m_bEmptyPresObj =rSource.m_bEmptyPresObj;
m_bNotVisibleAsMaster=rSource.m_bNotVisibleAsMaster;
m_bSnapRectDirty=true ;
m_pPlusData.reset();
if (rSource.m_pPlusData!=nullptr) {
m_pPlusData.reset(rSource.m_pPlusData->Clone(this ));
}
if (m_pPlusData!=nullptr && m_pPlusData->pBroadcast!=nullptr) {
m_pPlusData->pBroadcast.reset(); // broadcaster isn't copied
}
m_pGrabBagItem.reset();
if (rSource.m_pGrabBagItem!=nullptr)
m_pGrabBagItem.reset(rSource.m_pGrabBagItem->Clone());
impAddIncarnatedSdrObjectToSdrModel(*this , getSdrModelFromSdrObject());
}
SdrObject::~SdrObject()
{
#ifdef DBG_UTIL
// see logic in SdrObject::release
assert(m_refCount == -1);
#endif
// Tell all the registered ObjectUsers that the page is in destruction.
// And clear the vector. This means that user do not need to call RemoveObjectUser()
// when they get called from ObjectInDestruction().
sdr::ObjectUserVector aList;
aList.swap(mpImpl->maObjectUsers);
for (sdr::ObjectUser* pObjectUser : aList)
{
DBG_ASSERT(pObjectUser, "SdrObject::~SdrObject: corrupt ObjectUser list (!)" );
pObjectUser->ObjectInDestruction(*this );
}
// UserCall
SendUserCall(SdrUserCallType::Delete , GetLastBoundRect());
o3tl::reset_preserve_ptr_during(m_pPlusData);
m_pGrabBagItem.reset();
mpProperties.reset();
mpViewContact.reset();
impRemoveIncarnatedSdrObjectToSdrModel(*this , getSdrModelFromSdrObject());
}
void SdrObject::acquire() noexcept
{
#ifdef DBG_UTIL
assert(m_refCount != -1);
#endif
osl_atomic_increment( &m_refCount );
}
void SdrObject::release() noexcept
{
oslInterlockedCount x = osl_atomic_decrement( &m_refCount );
if ( x == 0 )
{
disposeWeakConnectionPoint();
#ifdef DBG_UTIL
// make sure it doesn't accidentally come back to life, see assert in acquire()
osl_atomic_decrement( &m_refCount );
#endif
delete this ;
}
}
void SdrObject::SetBoundAndSnapRectsDirty(bool bNotMyself, bool bRecursive)
{
if (!bNotMyself)
{
SetBoundRectDirty();
m_bSnapRectDirty=true ;
}
if (bRecursive && nullptr != getParentSdrObjListFromSdrObject())
{
getParentSdrObjListFromSdrObject()->SetSdrObjListRectsDirty();
}
}
void SdrObject::handlePageChange(SdrPage*, SdrPage* )
{
}
// init global static itempool
SdrItemPool& SdrObject::GetGlobalDrawObjectItemPool()
{
static tools::DeleteRtlReferenceOnDeinit<SdrItemPool> xGlobalItemPool( []() {
rtl::Reference<SdrItemPool> xNewPool(new SdrItemPool());
rtl::Reference<SfxItemPool> pGlobalOutlPool = EditEngine::CreatePool();
xNewPool->SetSecondaryPool(pGlobalOutlPool.get());
xNewPool->SetDefaultMetric(SdrEngineDefaults::GetMapUnit());
if (comphelper::IsFuzzing())
xNewPool->acquire();
return xNewPool;
}() );
return *xGlobalItemPool.get();
}
void SdrObject::SetRelativeWidth( double nValue )
{
mpImpl->mnRelativeWidth = nValue;
}
void SdrObject::SetRelativeWidthRelation( sal_Int16 eValue )
{
mpImpl->meRelativeWidthRelation = eValue;
}
void SdrObject::SetRelativeHeight( double nValue )
{
mpImpl->mnRelativeHeight = nValue;
}
void SdrObject::SetRelativeHeightRelation( sal_Int16 eValue )
{
mpImpl->meRelativeHeightRelation = eValue;
}
const double * SdrObject::GetRelativeWidth( ) const
{
if (!mpImpl->mnRelativeWidth)
return nullptr;
return &*mpImpl->mnRelativeWidth;
}
sal_Int16 SdrObject::GetRelativeWidthRelation() const
{
return mpImpl->meRelativeWidthRelation;
}
const double * SdrObject::GetRelativeHeight( ) const
{
if (!mpImpl->mnRelativeHeight)
return nullptr;
return &*mpImpl->mnRelativeHeight;
}
sal_Int16 SdrObject::GetRelativeHeightRelation() const
{
return mpImpl->meRelativeHeightRelation;
}
SfxItemPool& SdrObject::GetObjectItemPool() const
{
return getSdrModelFromSdrObject().GetItemPool();
}
SdrInventor SdrObject::GetObjInventor() const
{
return SdrInventor::Default ;
}
SdrObjKind SdrObject::GetObjIdentifier() const
{
return SdrObjKind::NONE;
}
void SdrObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
{
rInfo.bRotateFreeAllowed=false ;
rInfo.bMirrorFreeAllowed=false ;
rInfo.bTransparenceAllowed = false ;
rInfo.bShearAllowed =false ;
rInfo.bEdgeRadiusAllowed=false ;
rInfo.bCanConvToPath =false ;
rInfo.bCanConvToPoly =false ;
rInfo.bCanConvToContour = false ;
rInfo.bCanConvToPathLineToArea=false ;
rInfo.bCanConvToPolyLineToArea=false ;
}
SdrLayerID SdrObject::GetLayer() const
{
return mnLayerID;
}
bool SdrObject::isVisibleOnAnyOfTheseLayers(const SdrLayerIDSet& rSet) const
{
if (rSet.IsSet(GetLayer()))
return true ;
SdrObjList* pOL=GetSubList();
if (!pOL)
return false ;
for (const rtl::Reference<SdrObject>& pObject : *pOL)
if (pObject->isVisibleOnAnyOfTheseLayers(rSet))
return true ;
return false ;
}
void SdrObject::NbcSetLayer(SdrLayerID nLayer)
{
mnLayerID = nLayer;
}
void SdrObject::SetLayer(SdrLayerID nLayer)
{
NbcSetLayer(nLayer);
SetChanged();
BroadcastObjectChange();
}
void SdrObject::AddListener(SfxListener& rListener)
{
ImpForcePlusData();
if (m_pPlusData->pBroadcast==nullptr) m_pPlusData->pBroadcast.reset(new SfxBroadcaster);
// SdrEdgeObj may be connected to same SdrObject on both ends so allow it
// to listen twice
SdrEdgeObj const *const pEdge(dynamic_cast <SdrEdgeObj const *>(&rListener));
rListener.StartListening(*m_pPlusData->pBroadcast, pEdge ? DuplicateHandling::Allow : DuplicateHandling::Unexpected);
}
void SdrObject::RemoveListener(SfxListener& rListener)
{
if (m_pPlusData!=nullptr && m_pPlusData->pBroadcast!=nullptr) {
rListener.EndListening(*m_pPlusData->pBroadcast);
if (!m_pPlusData->pBroadcast->HasListeners()) {
m_pPlusData->pBroadcast.reset();
}
}
}
SfxBroadcaster* SdrObject::GetBroadcaster() const
{
return m_pPlusData!=nullptr ? m_pPlusData->pBroadcast.get() : nullptr;
}
void SdrObject::AddReference(SdrVirtObj& rVrtObj)
{
AddListener(rVrtObj);
}
void SdrObject::DelReference(SdrVirtObj& rVrtObj)
{
RemoveListener(rVrtObj);
}
bool SdrObject::IsGroupObject() const
{
return GetSubList()!=nullptr;
}
SdrObjList* SdrObject::GetSubList() const
{
return nullptr;
}
SdrObject* SdrObject::getParentSdrObjectFromSdrObject() const
{
SdrObjList* pParent(getParentSdrObjListFromSdrObject());
if (nullptr == pParent)
{
return nullptr;
}
return pParent->getSdrObjectFromSdrObjList();
}
void SdrObject::SetName(const OUString& rStr, const bool bSetChanged)
{
if (!rStr.isEmpty() && !m_pPlusData)
{
ImpForcePlusData();
}
if (!(m_pPlusData && m_pPlusData->aObjName != rStr))
return ;
// Undo/Redo for setting object's name (#i73249#)
bool bUndo( false );
if ( getSdrModelFromSdrObject().IsUndoEnabled() )
{
bUndo = true ;
std::unique_ptr<SdrUndoAction> pUndoAction =
SdrUndoFactory::CreateUndoObjectStrAttr(
*this ,
SdrUndoObjStrAttr::ObjStrAttrType::Name,
GetName(),
rStr );
getSdrModelFromSdrObject().BegUndo( pUndoAction->GetComment() );
getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction) );
}
m_pPlusData->aObjName = rStr;
// Undo/Redo for setting object's name (#i73249#)
if ( bUndo )
{
getSdrModelFromSdrObject().EndUndo();
}
if (bSetChanged)
{
SetChanged();
BroadcastObjectChange();
}
}
const OUString & SdrObject::GetName() const
{
if (m_pPlusData)
{
return m_pPlusData->aObjName;
}
return EMPTY_OUSTRING;
}
void SdrObject::SetTitle(const OUString& rStr)
{
if (!rStr.isEmpty() && !m_pPlusData)
{
ImpForcePlusData();
}
if (!(m_pPlusData && m_pPlusData->aObjTitle != rStr))
return ;
// Undo/Redo for setting object's title (#i73249#)
bool bUndo( false );
if ( getSdrModelFromSdrObject().IsUndoEnabled() )
{
bUndo = true ;
std::unique_ptr<SdrUndoAction> pUndoAction =
SdrUndoFactory::CreateUndoObjectStrAttr(
*this ,
SdrUndoObjStrAttr::ObjStrAttrType::Title,
GetTitle(),
rStr );
getSdrModelFromSdrObject().BegUndo( pUndoAction->GetComment() );
getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction) );
}
m_pPlusData->aObjTitle = rStr;
// Undo/Redo for setting object's title (#i73249#)
if ( bUndo )
{
getSdrModelFromSdrObject().EndUndo();
}
SetChanged();
BroadcastObjectChange();
}
OUString SdrObject::GetTitle() const
{
if (m_pPlusData)
{
return m_pPlusData->aObjTitle;
}
return OUString();
}
void SdrObject::SetDescription(const OUString& rStr)
{
if (!rStr.isEmpty() && !m_pPlusData)
{
ImpForcePlusData();
}
if (!(m_pPlusData && m_pPlusData->aObjDescription != rStr))
return ;
// Undo/Redo for setting object's description (#i73249#)
bool bUndo( false );
if ( getSdrModelFromSdrObject().IsUndoEnabled() )
{
bUndo = true ;
std::unique_ptr<SdrUndoAction> pUndoAction =
SdrUndoFactory::CreateUndoObjectStrAttr(
*this ,
SdrUndoObjStrAttr::ObjStrAttrType::Description,
GetDescription(),
rStr );
getSdrModelFromSdrObject().BegUndo( pUndoAction->GetComment() );
getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction) );
}
m_pPlusData->aObjDescription = rStr;
// Undo/Redo for setting object's description (#i73249#)
if ( bUndo )
{
getSdrModelFromSdrObject().EndUndo();
}
SetChanged();
BroadcastObjectChange();
}
OUString SdrObject::GetDescription() const
{
if (m_pPlusData)
{
return m_pPlusData->aObjDescription;
}
return OUString();
}
void SdrObject::SetDecorative(bool const isDecorative)
{
ImpForcePlusData();
if (m_pPlusData->isDecorative == isDecorative)
{
return ;
}
if (getSdrModelFromSdrObject().IsUndoEnabled())
{
std::unique_ptr<SdrUndoAction> pUndoAction(
SdrUndoFactory::CreateUndoObjectDecorative(
*this , m_pPlusData->isDecorative));
getSdrModelFromSdrObject().BegUndo(pUndoAction->GetComment());
getSdrModelFromSdrObject().AddUndo(std::move(pUndoAction));
}
m_pPlusData->isDecorative = isDecorative;
if (getSdrModelFromSdrObject().IsUndoEnabled())
{
getSdrModelFromSdrObject().EndUndo();
}
SetChanged();
BroadcastObjectChange();
}
bool SdrObject::IsDecorative() const
{
return m_pPlusData == nullptr ? false : m_pPlusData->isDecorative;
}
void SdrObject::setAsAnnotationObject()
{
if (!mpAnnotationData)
mpAnnotationData = std::make_unique<sdr::annotation::ObjectAnnotationData>();
}
std::unique_ptr<sdr::annotation::ObjectAnnotationData>& SdrObject::getAnnotationData()
{
return mpAnnotationData;
}
sal_uInt32 SdrObject::GetOrdNum() const
{
if (SdrObjList* pParentList = getParentSdrObjListFromSdrObject())
{
if (pParentList->IsObjOrdNumsDirty())
{
pParentList->RecalcObjOrdNums();
}
} else const_cast <SdrObject*>(this )->m_nOrdNum=0;
return m_nOrdNum;
}
void SdrObject::SetOrdNum(sal_uInt32 nNum)
{
m_nOrdNum = nNum;
}
/// Try to ensure the desired result __without__ triggering RecalcObjOrdNums
void SdrObject::ensureSortedImmediatelyAfter(const SdrObject& rFirst)
{
SdrObjList* pParentList = getParentSdrObjListFromSdrObject();
assert(pParentList == rFirst.getParentSdrObjListFromSdrObject());
bool bDirty = pParentList->IsObjOrdNumsDirty();
if (!bDirty)
{
pParentList->SetObjectOrdNum(GetOrdNum(), rFirst.GetOrdNum() + 1);
}
else
{
std::optional<decltype(pParentList->begin())> itFound1, itFound2;
for (auto it = pParentList->begin(), itEnd = pParentList->end(); it != itEnd; ++it)
{
if (*it == this )
itFound1 = it;
else if (*it == &rFirst)
itFound2 = it;
if (itFound1 && itFound2)
{
auto ord1 = std::distance(pParentList->begin(), *itFound1);
auto ord2 = std::distance(pParentList->begin(), *itFound2);
pParentList->SetObjectOrdNum(ord1, ord2 + 1);
break ;
}
}
}
}
void SdrObject::GetGrabBagItem(css::uno::Any& rVal) const
{
if (m_pGrabBagItem != nullptr)
m_pGrabBagItem->QueryValue(rVal);
else
rVal <<= uno::Sequence<beans::PropertyValue>();
}
void SdrObject::SetGrabBagItem(const css::uno::Any& rVal)
{
if (m_pGrabBagItem == nullptr)
m_pGrabBagItem.reset(new SfxGrabBagItem);
m_pGrabBagItem->PutValue(rVal, 0);
SetChanged();
BroadcastObjectChange();
}
sal_uInt32 SdrObject::GetNavigationPosition() const
{
if (nullptr != getParentSdrObjListFromSdrObject() && getParentSdrObjListFromSdrObject()->RecalcNavigationPositions())
{
return mnNavigationPosition;
}
else
return GetOrdNum();
}
void SdrObject::SetNavigationPosition (const sal_uInt32 nNewPosition)
{
mnNavigationPosition = nNewPosition;
}
// To make clearer that this method may trigger RecalcBoundRect and thus may be
// expensive and sometimes problematic (inside a bigger object change you will get
// non-useful BoundRects sometimes) I rename that method from GetBoundRect() to
// GetCurrentBoundRect().
const tools::Rectangle& SdrObject::GetCurrentBoundRect() const
{
auto const & rRectangle = getOutRectangle();
if (rRectangle.IsEmpty())
{
const_cast < SdrObject* >(this )->RecalcBoundRect();
}
return rRectangle;
}
// To have a possibility to get the last calculated BoundRect e.g for producing
// the first rectangle for repaints (old and new need to be used) without forcing
// a RecalcBoundRect (which may be problematical and expensive sometimes) I add here
// a new method for accessing the last BoundRect.
const tools::Rectangle& SdrObject::GetLastBoundRect() const
{
return getOutRectangle();
}
void SdrObject::RecalcBoundRect()
{
// #i101680# suppress BoundRect calculations on import(s)
if ((getSdrModelFromSdrObject().isLocked()) || comphelper::IsFuzzing())
return ;
auto const & rRectangle = getOutRectangle();
// central new method which will calculate the BoundRect using primitive geometry
if (!rRectangle.IsEmpty())
return ;
// Use view-independent data - we do not want any connections
// to e.g. GridOffset in SdrObject-level
drawinglayer::primitive2d::Primitive2DContainer xPrimitives;
GetViewContact().getViewIndependentPrimitive2DContainer(xPrimitives);
if (xPrimitives.empty())
return ;
// use neutral ViewInformation and get the range of the primitives
const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
const basegfx::B2DRange aRange(xPrimitives.getB2DRange(aViewInformation2D));
if (!aRange.isEmpty())
{
tools::Rectangle aNewRectangle(
tools::Long (floor(aRange.getMinX())),
tools::Long (floor(aRange.getMinY())),
tools::Long (ceil(aRange.getMaxX())),
tools::Long (ceil(aRange.getMaxY())));
setOutRectangle(aNewRectangle);
return ;
}
}
void SdrObject::BroadcastObjectChange() const
{
if ((getSdrModelFromSdrObject().isLocked()) || getSdrModelFromSdrObject().IsInDestruction() || comphelper::IsFuzzing())
return ;
bool bPlusDataBroadcast(m_pPlusData && m_pPlusData->pBroadcast);
bool bObjectChange(IsInserted());
if (!(bPlusDataBroadcast || bObjectChange))
return ;
SdrHint aHint(SdrHintKind::ObjectChange, *this );
if (bPlusDataBroadcast)
{
m_pPlusData->pBroadcast->Broadcast(aHint);
}
if (bObjectChange)
{
getSdrModelFromSdrObject().Broadcast(aHint);
}
}
void SdrObject::SetChanged()
{
// For testing purposes, use the new ViewContact for change
// notification now.
ActionChanged();
// TTTT Need to check meaning/usage of IsInserted in one
// of the next changes. It should not mean to have a SdrModel
// set (this is guaranteed now), but should be connected to
// being added to a SdrPage (?)
// TTTT tdf#120066 Indeed - This triggers e.g. by CustomShape
// geometry-presenting SdrObjects that are in a SdrObjGroup,
// but the SdrObjGroup is *by purpose* not inserted.
// Need to check deeper and maybe identify all ::IsInserted()
// calls by rename and let the compiler work...
if (nullptr != getSdrPageFromSdrObject())
{
getSdrModelFromSdrObject().SetChanged();
}
}
// tooling for painting a single object to an OutputDevice.
void SdrObject::SingleObjectPainter(OutputDevice& rOut) const
{
sdr::contact::SdrObjectVector aObjectVector;
aObjectVector.push_back(const_cast < SdrObject* >(this ));
sdr::contact::ObjectContactOfObjListPainter aPainter(rOut, std::move(aObjectVector), getSdrPageFromSdrObject());
sdr::contact::DisplayInfo aDisplayInfo;
aPainter.ProcessDisplay(aDisplayInfo);
}
bool SdrObject::LineGeometryUsageIsNecessary() const
{
drawing::LineStyle eXLS = GetMergedItem(XATTR_LINESTYLE).GetValue();
return (eXLS != drawing::LineStyle_NONE);
}
bool SdrObject::HasLimitedRotation() const
{
// RotGrfFlyFrame: Default is false, support full rotation
return false ;
}
OUString SdrObject::TakeObjNameSingul() const
{
OUString sName(SvxResId(STR_ObjNameSingulNONE));
OUString aName(GetName());
if (!aName.isEmpty())
sName += " '" + aName + "'" ;
return sName;
}
OUString SdrObject::TakeObjNamePlural() const
{
return SvxResId(STR_ObjNamePluralNONE);
}
OUString SdrObject::ImpGetDescriptionStr(TranslateId pStrCacheID) const
{
OUString aStr = SvxResId(pStrCacheID);
sal_Int32 nPos = aStr.indexOf("%1" );
if (nPos >= 0)
{
// Replace '%1' with the object name.
OUString aObjName(TakeObjNameSingul());
aStr = aStr.replaceAt(nPos, 2, aObjName);
}
nPos = aStr.indexOf("%2" );
if (nPos >= 0)
// Replace '%2' with the passed value.
aStr = aStr.replaceAt(nPos, 2, u"0" );
return aStr;
}
void SdrObject::ImpForcePlusData()
{
if (!m_pPlusData)
m_pPlusData.reset( new SdrObjPlusData );
}
OUString SdrObject::GetMetrStr(tools::Long nVal) const
{
return getSdrModelFromSdrObject().GetMetricString(nVal);
}
basegfx::B2DPolyPolygon SdrObject::TakeXorPoly() const
{
basegfx::B2DPolyPolygon aRetval;
const tools::Rectangle aR(GetCurrentBoundRect());
aRetval.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aR)));
return aRetval;
}
basegfx::B2DPolyPolygon SdrObject::TakeContour() const
{
basegfx::B2DPolyPolygon aRetval;
// create cloned object without text, but with drawing::LineStyle_SOLID,
// COL_BLACK as line color and drawing::FillStyle_NONE
rtl::Reference<SdrObject> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
if (pClone)
{
const SdrTextObj* pTextObj = DynCastSdrTextObj(this );
if (pTextObj)
{
// no text and no text animation
pClone->SetMergedItem(SdrTextAniKindItem(SdrTextAniKind::NONE));
pClone->SetOutlinerParaObject(std::nullopt);
}
const SdrEdgeObj* pEdgeObj = dynamic_cast < const SdrEdgeObj* >(this );
if (pEdgeObj)
{
// create connections if connector, will be cleaned up when
// deleting the connector again
SdrObject* pLeft = pEdgeObj->GetConnectedNode(true );
SdrObject* pRight = pEdgeObj->GetConnectedNode(false );
if (pLeft)
{
pClone->ConnectToNode(true , pLeft);
}
if (pRight)
{
pClone->ConnectToNode(false , pRight);
}
}
SfxItemSet aNewSet(GetObjectItemPool());
// #i101980# ignore LineWidth; that's what the old implementation
// did. With line width, the result may be huge due to fat/thick
// line decompositions
aNewSet.Put(XLineWidthItem(0));
// solid black lines and no fill
aNewSet.Put(XLineStyleItem(drawing::LineStyle_SOLID));
aNewSet.Put(XLineColorItem(OUString(), COL_BLACK));
aNewSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
pClone->SetMergedItemSet(aNewSet);
// get sequence from clone
const sdr::contact::ViewContact& rVC(pClone->GetViewContact());
drawinglayer::primitive2d::Primitive2DContainer xSequence;
rVC.getViewIndependentPrimitive2DContainer(xSequence);
if (!xSequence.empty())
{
// use neutral ViewInformation
const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
// create extractor, process and get result (with hairlines as opened polygons)
drawinglayer::processor2d::ContourExtractor2D aExtractor(aViewInformation2D, false );
aExtractor.process(xSequence);
const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour());
const sal_uInt32 nSize(rResult.size());
// when count is one, it is implied that the object has only its normal
// contour anyways and TakeContour() is to return an empty PolyPolygon
// (see old implementation for historical reasons)
if (nSize > 1)
{
// the topology for contour is correctly a vector of PolyPolygons; for
// historical reasons cut it back to a single tools::PolyPolygon here
for (sal_uInt32 a(0); a < nSize; a++)
{
aRetval.append(rResult[a]);
}
}
}
}
return aRetval;
}
sal_uInt32 SdrObject::GetHdlCount() const
{
return 8;
}
void SdrObject::AddToHdlList(SdrHdlList& rHdlList) const
{
const tools::Rectangle& rR=GetSnapRect();
for (sal_uInt32 nHdlNum=0; nHdlNum<8; ++nHdlNum)
{
std::unique_ptr<SdrHdl> pH;
switch (nHdlNum) {
case 0: pH.reset(new SdrHdl(rR.TopLeft(), SdrHdlKind::UpperLeft)); break ;
case 1: pH.reset(new SdrHdl(rR.TopCenter(), SdrHdlKind::Upper)); break ;
case 2: pH.reset(new SdrHdl(rR.TopRight(), SdrHdlKind::UpperRight)); break ;
case 3: pH.reset(new SdrHdl(rR.LeftCenter(), SdrHdlKind::Left )); break ;
case 4: pH.reset(new SdrHdl(rR.RightCenter(), SdrHdlKind::Right)); break ;
case 5: pH.reset(new SdrHdl(rR.BottomLeft(), SdrHdlKind::LowerLeft)); break ;
case 6: pH.reset(new SdrHdl(rR.BottomCenter(),SdrHdlKind::Lower)); break ;
case 7: pH.reset(new SdrHdl(rR.BottomRight(), SdrHdlKind::LowerRight)); break ;
}
rHdlList.AddHdl(std::move(pH));
}
}
void SdrObject::AddToPlusHdlList(SdrHdlList&, SdrHdl&) const
{
}
void SdrObject::addCropHandles(SdrHdlList& /*rTarget*/) const
{
// Default implementation, does nothing. Overloaded in
// SdrGrafObj and SwVirtFlyDrawObj
}
tools::Rectangle SdrObject::ImpDragCalcRect(const SdrDragStat& rDrag) const
{
tools::Rectangle aTmpRect(GetSnapRect());
tools::Rectangle aRect(aTmpRect);
const SdrHdl* pHdl=rDrag.GetHdl();
SdrHdlKind eHdl=pHdl==nullptr ? SdrHdlKind::Move : pHdl->GetKind();
bool bEcke=(eHdl==SdrHdlKind::UpperLeft || eHdl==SdrHdlKind::UpperRight || eHdl==SdrHdlKind::LowerLeft || eHdl==SdrHdlKind::LowerRight);
bool bOrtho=rDrag.GetView()!=nullptr && rDrag.GetView()->IsOrtho();
bool bBigOrtho=bEcke && bOrtho && rDrag.GetView()->IsBigOrtho();
Point aPos(rDrag.GetNow());
bool bLft=(eHdl==SdrHdlKind::UpperLeft || eHdl==SdrHdlKind::Left || eHdl==SdrHdlKind::LowerLeft);
bool bRgt=(eHdl==SdrHdlKind::UpperRight || eHdl==SdrHdlKind::Right || eHdl==SdrHdlKind::LowerRight);
bool bTop=(eHdl==SdrHdlKind::UpperRight || eHdl==SdrHdlKind::Upper || eHdl==SdrHdlKind::UpperLeft);
bool bBtm=(eHdl==SdrHdlKind::LowerRight || eHdl==SdrHdlKind::Lower || eHdl==SdrHdlKind::LowerLeft);
if (bLft) aTmpRect.SetLeft(aPos.X() );
if (bRgt) aTmpRect.SetRight(aPos.X() );
if (bTop) aTmpRect.SetTop(aPos.Y() );
if (bBtm) aTmpRect.SetBottom(aPos.Y() );
if (bOrtho) { // Ortho
tools::Long nWdt0=aRect.Right() -aRect.Left();
tools::Long nHgt0=aRect.Bottom()-aRect.Top();
tools::Long nXMul=aTmpRect.Right() -aTmpRect.Left();
tools::Long nYMul=aTmpRect.Bottom()-aTmpRect.Top();
tools::Long nXDiv=nWdt0;
tools::Long nYDiv=nHgt0;
bool bXNeg=(nXMul<0)!=(nXDiv<0);
bool bYNeg=(nYMul<0)!=(nYDiv<0);
nXMul=std::abs(nXMul);
nYMul=std::abs(nYMul);
nXDiv=std::abs(nXDiv);
nYDiv=std::abs(nYDiv);
Fraction aXFact(nXMul,nXDiv); // fractions for canceling
Fraction aYFact(nYMul,nYDiv); // and for comparing
nXMul=aXFact.GetNumerator();
nYMul=aYFact.GetNumerator();
nXDiv=aXFact.GetDenominator();
nYDiv=aYFact.GetDenominator();
if (bEcke) { // corner point handles
bool bUseX=(aXFact<aYFact) != bBigOrtho;
if (bUseX) {
tools::Long nNeed=tools::Long (BigInt(nHgt0)*BigInt(nXMul)/BigInt(nXDiv));
if (bYNeg) nNeed=-nNeed;
if (bTop) aTmpRect.SetTop(aTmpRect.Bottom()-nNeed );
if (bBtm) aTmpRect.SetBottom(aTmpRect.Top()+nNeed );
} else {
tools::Long nNeed=tools::Long (BigInt(nWdt0)*BigInt(nYMul)/BigInt(nYDiv));
if (bXNeg) nNeed=-nNeed;
if (bLft) aTmpRect.SetLeft(aTmpRect.Right()-nNeed );
if (bRgt) aTmpRect.SetRight(aTmpRect.Left()+nNeed );
}
} else { // apex handles
if ((bLft || bRgt) && nXDiv!=0) {
tools::Long nHgt0b=aRect.Bottom()-aRect.Top();
tools::Long nNeed=tools::Long (BigInt(nHgt0b)*BigInt(nXMul)/BigInt(nXDiv));
aTmpRect.AdjustTop( -((nNeed-nHgt0b)/2) );
aTmpRect.SetBottom(aTmpRect.Top()+nNeed );
}
if ((bTop || bBtm) && nYDiv!=0) {
tools::Long nWdt0b=aRect.Right()-aRect.Left();
tools::Long nNeed=tools::Long (BigInt(nWdt0b)*BigInt(nYMul)/BigInt(nYDiv));
aTmpRect.AdjustLeft( -((nNeed-nWdt0b)/2) );
aTmpRect.SetRight(aTmpRect.Left()+nNeed );
}
}
}
aTmpRect.Normalize();
return aTmpRect;
}
bool SdrObject::hasSpecialDrag() const
{
return false ;
}
bool SdrObject::supportsFullDrag() const
{
return true ;
}
rtl::Reference<SdrObject> SdrObject::getFullDragClone() const
{
// default uses simple clone
return CloneSdrObject(getSdrModelFromSdrObject());
}
bool SdrObject::beginSpecialDrag(SdrDragStat& rDrag) const
{
const SdrHdl* pHdl = rDrag.GetHdl();
SdrHdlKind eHdl = (pHdl == nullptr) ? SdrHdlKind::Move : pHdl->GetKind();
return eHdl==SdrHdlKind::UpperLeft || eHdl==SdrHdlKind::Upper || eHdl==SdrHdlKind::UpperRight ||
eHdl==SdrHdlKind::Left || eHdl==SdrHdlKind::Right || eHdl==SdrHdlKind::LowerLeft ||
eHdl==SdrHdlKind::Lower || eHdl==SdrHdlKind::LowerRight;
}
bool SdrObject::applySpecialDrag(SdrDragStat& rDrag)
{
tools::Rectangle aNewRect(ImpDragCalcRect(rDrag));
if (aNewRect != GetSnapRect())
{
NbcSetSnapRect(aNewRect);
}
return true ;
}
OUString SdrObject::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const
{
return OUString();
}
basegfx::B2DPolyPolygon SdrObject::getSpecialDragPoly(const SdrDragStat& /*rDrag*/) const
{
// default has nothing to add
return basegfx::B2DPolyPolygon();
}
// Create
bool SdrObject::BegCreate(SdrDragStat& rStat)
{
rStat.SetOrtho4Possible();
tools::Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
aRect1.Normalize();
rStat.SetActionRect(aRect1);
setOutRectangle(aRect1);
return true ;
}
bool SdrObject::MovCreate(SdrDragStat& rStat)
{
tools::Rectangle aRectangle;
rStat.TakeCreateRect(aRectangle);
rStat.SetActionRect(aRectangle);
aRectangle.Normalize();
setOutRectangle(aRectangle);
return true ;
}
bool SdrObject::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
{
tools::Rectangle aRectangle;
rStat.TakeCreateRect(aRectangle);
aRectangle.Normalize();
setOutRectangle(aRectangle);
return (eCmd==SdrCreateCmd::ForceEnd || rStat.GetPointCount()>=2);
}
void SdrObject::BrkCreate(SdrDragStat& /*rStat*/)
{
}
bool SdrObject::BckCreate(SdrDragStat& /*rStat*/)
{
return false ;
}
basegfx::B2DPolyPolygon SdrObject::TakeCreatePoly(const SdrDragStat& rDrag) const
{
tools::Rectangle aRect1;
rDrag.TakeCreateRect(aRect1);
aRect1.Normalize();
basegfx::B2DPolyPolygon aRetval;
aRetval.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aRect1)));
return aRetval;
}
PointerStyle SdrObject::GetCreatePointer() const
{
return PointerStyle::Cross;
}
// transformations
void SdrObject::NbcMove(const Size& rSize)
{
moveOutRectangle(rSize.Width(), rSize.Height());
SetBoundAndSnapRectsDirty();
}
void SdrObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
{
bool bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
bool bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
if (bXMirr || bYMirr) {
Point aRef1(GetSnapRect().Center());
if (bXMirr) {
Point aRef2(aRef1);
aRef2.AdjustY( 1 );
NbcMirrorGluePoints(aRef1,aRef2);
}
if (bYMirr) {
Point aRef2(aRef1);
aRef2.AdjustX( 1 );
NbcMirrorGluePoints(aRef1,aRef2);
}
}
auto aRectangle = getOutRectangle();
ResizeRect(aRectangle, rRef, xFact, yFact);
setOutRectangle(aRectangle);
SetBoundAndSnapRectsDirty();
}
bool SdrObject::IsSizeValid(Size /* aTargetSize */)
{
return true ;
}
void SdrObject::NbcRotate(const Point& rRef, Degree100 nAngle)
{
if (nAngle)
{
double a = toRadians(nAngle);
NbcRotate( rRef, nAngle, sin( a ), cos( a ) );
}
}
namespace
{
tools::Rectangle lclMirrorRectangle(tools::Rectangle const & rRectangle, Point const & rRef1, Point const & rRef2)
{
tools::Rectangle aRectangle(rRectangle);
aRectangle.Move(-rRef1.X(),-rRef1.Y());
tools::Rectangle R(aRectangle);
tools::Long dx=rRef2.X()-rRef1.X();
tools::Long dy=rRef2.Y()-rRef1.Y();
if (dx==0) { // vertical axis
aRectangle.SetLeft(-R.Right() );
aRectangle.SetRight(-R.Left() );
} else if (dy==0) { // horizontal axis
aRectangle.SetTop(-R.Bottom() );
aRectangle.SetBottom(-R.Top() );
} else if (dx==dy) { // 45deg axis
aRectangle.SetLeft(R.Top() );
aRectangle.SetRight(R.Bottom() );
aRectangle.SetTop(R.Left() );
aRectangle.SetBottom(R.Right() );
} else if (dx==-dy) { // 45deg axis
aRectangle.SetLeft(-R.Bottom() );
aRectangle.SetRight(-R.Top() );
aRectangle.SetTop(-R.Right() );
aRectangle.SetBottom(-R.Left() );
}
aRectangle.Move(rRef1.X(),rRef1.Y());
aRectangle.Normalize(); // just in case
return aRectangle;
}
} // end anonymous namespace
void SdrObject::NbcMirror(const Point& rRef1, const Point& rRef2)
{
SetGlueReallyAbsolute(true );
tools::Rectangle aRectangle = getOutRectangle();
aRectangle = lclMirrorRectangle(aRectangle, rRef1, rRef2);
setOutRectangle(aRectangle);
SetBoundAndSnapRectsDirty();
NbcMirrorGluePoints(rRef1,rRef2);
SetGlueReallyAbsolute(false );
}
void SdrObject::NbcShear(const Point& rRef, Degree100 /*nAngle*/, double tn, bool bVShear)
{
SetGlueReallyAbsolute(true );
NbcShearGluePoints(rRef,tn,bVShear);
SetGlueReallyAbsolute(false );
}
void SdrObject::Move(const Size& rSize)
{
if (rSize.Width() == 0 && rSize.Height() == 0)
return ;
tools::Rectangle aBoundRect0;
if (m_pUserCall != nullptr)
aBoundRect0 = GetLastBoundRect();
NbcMove(rSize);
if (isAnnotationObject())
{
css::geometry::RealPoint2D aNewPosition(
GetLogicRect().Left() / 100.0,
GetLogicRect().Top() / 100.0);
getAnnotationData()->mxAnnotation->SetPosition(aNewPosition);
}
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::MoveOnly, aBoundRect0);
}
void SdrObject::NbcCrop(const basegfx::B2DPoint& /*aRef*/, double /*fxFact*/, double /*fyFact*/)
{
// Default: does nothing. Real behaviour in SwVirtFlyDrawObj and SdrDragCrop::EndSdrDrag.
// Where SwVirtFlyDrawObj is the only real user of it to do something local
}
void SdrObject::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative)
{
if (xFact.GetNumerator() == xFact.GetDenominator() && yFact.GetNumerator() == yFact.GetDenominator())
return ;
if (bUnsetRelative)
{
mpImpl->mnRelativeWidth.reset();
mpImpl->meRelativeWidthRelation = text::RelOrientation::PAGE_FRAME;
mpImpl->meRelativeHeightRelation = text::RelOrientation::PAGE_FRAME;
mpImpl->mnRelativeHeight.reset();
}
tools::Rectangle aBoundRect0;
if (m_pUserCall != nullptr)
aBoundRect0 = GetLastBoundRect();
NbcResize(rRef, xFact, yFact);
if (isAnnotationObject())
{
auto & rRect = GetCurrentBoundRect();
css::geometry::RealSize2D aNewSize(rRect.GetWidth() / 100.0, rRect.GetHeight() / 100.0);
getAnnotationData()->mxAnnotation->SetSize(aNewSize);
}
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize, aBoundRect0);
}
void SdrObject::Crop(const basegfx::B2DPoint& rRef, double fxFact, double fyFact)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcCrop(rRef, fxFact, fyFact);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
void SdrObject::Rotate(const Point& rRef, Degree100 nAngle, double sn, double cs)
{
if (nAngle) {
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcRotate(rRef,nAngle,sn,cs);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
}
void SdrObject::Mirror(const Point& rRef1, const Point& rRef2)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcMirror(rRef1,rRef2);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
void SdrObject::Shear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear)
{
if (nAngle) {
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcShear(rRef,nAngle,tn,bVShear);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
}
void SdrObject::NbcSetRelativePos(const Point& rPnt)
{
Point aRelPos0(GetSnapRect().TopLeft()-m_aAnchor);
Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
NbcMove(aSiz); // This also calls SetRectsDirty()
}
void SdrObject::SetRelativePos(const Point& rPnt)
{
if (rPnt!=GetRelativePos()) {
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcSetRelativePos(rPnt);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0);
}
}
Point SdrObject::GetRelativePos() const
{
return GetSnapRect().TopLeft()-m_aAnchor;
}
void SdrObject::ImpSetAnchorPos(const Point& rPnt)
{
m_aAnchor = rPnt;
}
void SdrObject::NbcSetAnchorPos(const Point& rPnt)
{
Size aSiz(rPnt.X()-m_aAnchor.X(),rPnt.Y()-m_aAnchor.Y());
m_aAnchor=rPnt;
NbcMove(aSiz); // This also calls SetRectsDirty()
}
void SdrObject::SetAnchorPos(const Point& rPnt)
{
if (rPnt!=m_aAnchor) {
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcSetAnchorPos(rPnt);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0);
}
}
const Point& SdrObject::GetAnchorPos() const
{
return m_aAnchor;
}
void SdrObject::RecalcSnapRect()
{
}
const tools::Rectangle& SdrObject::GetSnapRect() const
{
return getOutRectangle();
}
void SdrObject::NbcSetSnapRect(const tools::Rectangle& rRect)
{
setOutRectangle(rRect);
}
const tools::Rectangle& SdrObject::GetLogicRect() const
{
return GetSnapRect();
}
void SdrObject::NbcSetLogicRect(const tools::Rectangle& rRect, bool /*bAdaptTextMinSize*/)
{
NbcSetSnapRect(rRect);
}
void SdrObject::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool /* bShrinkOnly = false */ )
{
SetLogicRect( rMaxRect );
}
void SdrObject::SetSnapRect(const tools::Rectangle& rRect)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcSetSnapRect(rRect);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
void SdrObject::SetLogicRect(const tools::Rectangle& rRect)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcSetLogicRect(rRect);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
Degree100 SdrObject::GetRotateAngle() const
{
return 0_deg100;
}
Degree100 SdrObject::GetShearAngle(bool /*bVertical*/) const
{
return 0_deg100;
}
sal_uInt32 SdrObject::GetSnapPointCount() const
{
return GetPointCount();
}
Point SdrObject::GetSnapPoint(sal_uInt32 i) const
{
return GetPoint(i);
}
bool SdrObject::IsPolyObj() const
{
return false ;
}
sal_uInt32 SdrObject::GetPointCount() const
{
return 0;
}
Point SdrObject::GetPoint(sal_uInt32 /*i*/) const
{
return Point();
}
void SdrObject::SetPoint(const Point& rPnt, sal_uInt32 i)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcSetPoint(rPnt, i);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
void SdrObject::NbcSetPoint(const Point& /*rPnt*/, sal_uInt32 /*i*/)
{
}
bool SdrObject::HasTextEdit() const
{
return false ;
}
bool SdrObject::Equals(const SdrObject& rOtherObj) const
{
return (m_aAnchor.X() == rOtherObj.m_aAnchor.X() && m_aAnchor.Y() == rOtherObj.m_aAnchor.Y() &&
m_nOrdNum == rOtherObj.m_nOrdNum && mnNavigationPosition == rOtherObj.mnNavigationPosition &&
mbSupportTextIndentingOnLineWidthChange == rOtherObj.mbSupportTextIndentingOnLineWidthChange &&
mbLineIsOutsideGeometry == rOtherObj.mbLineIsOutsideGeometry && m_bMarkProt == rOtherObj.m_bMarkProt &&
m_bIs3DObj == rOtherObj.m_bIs3DObj && m_bIsEdge == rOtherObj.m_bIsEdge && m_bClosedObj == rOtherObj.m_bClosedObj &&
m_bNotVisibleAsMaster == rOtherObj.m_bNotVisibleAsMaster && m_bEmptyPresObj == rOtherObj.m_bEmptyPresObj &&
mbVisible == rOtherObj.mbVisible && m_bNoPrint == rOtherObj.m_bNoPrint && m_bSizProt == rOtherObj.m_bSizProt &&
m_bMovProt == rOtherObj.m_bMovProt && m_bVirtObj == rOtherObj.m_bVirtObj &&
mnLayerID == rOtherObj.mnLayerID && GetMergedItemSet().Equals(rOtherObj.GetMergedItemSet(), false ) );
}
void SdrObject::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SdrObject" ));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr" ), "%p" , this );
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol" ), "%s" , BAD_CAST(typeid (*this ).name()));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("name" ), "%s" , BAD_CAST(GetName().toUtf8().getStr()));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("title" ), "%s" , BAD_CAST(GetTitle().toUtf8().getStr()));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("description" ), "%s" , BAD_CAST(GetDescription().toUtf8().getStr()));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("nOrdNum" ), "%" SAL_PRIuUINT32, GetOrdNumDirect());
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("aOutRect" ), BAD_CAST(getOutRectangle().toString().getStr()));
if (m_pGrabBagItem)
{
m_pGrabBagItem->dumpAsXml(pWriter);
}
if (mpProperties)
{
mpProperties->dumpAsXml(pWriter);
}
if (const OutlinerParaObject* pOutliner = GetOutlinerParaObject())
pOutliner->dumpAsXml(pWriter);
(void )xmlTextWriterEndElement(pWriter);
}
void SdrObject::SetOutlinerParaObject(std::optional<OutlinerParaObject> pTextObject)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcSetOutlinerParaObject(std::move(pTextObject));
SetChanged();
BroadcastObjectChange();
if (GetCurrentBoundRect()!=aBoundRect0) {
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
if (!getSdrModelFromSdrObject().IsUndoEnabled())
return ;
// Don't do this during import.
if (SdrObject* pTopGroupObj = getParentSdrObjectFromSdrObject())
{
while (SdrObject* pParent = pTopGroupObj->getParentSdrObjectFromSdrObject())
pTopGroupObj = pParent;
// A shape was modified, which is in a group shape. Empty the group shape's grab-bag,
// which potentially contains the old text of the shapes in case of diagrams.
pTopGroupObj->SetGrabBagItem(uno::Any(uno::Sequence<beans::PropertyValue>()));
}
}
void SdrObject::NbcSetOutlinerParaObject(std::optional<OutlinerParaObject> /*pTextObject*/, bool /*bAdjustTextFrameWidthAndHeight = true*/)
{
}
OutlinerParaObject* SdrObject::GetOutlinerParaObject() const
{
return nullptr;
}
void SdrObject::NbcReformatText()
{
}
void SdrObject::BurnInStyleSheetAttributes()
{
GetProperties().ForceStyleToHardAttributes();
}
bool SdrObject::HasMacro() const
{
return false ;
}
SdrObject* SdrObject::CheckMacroHit(const SdrObjMacroHitRec& rRec) const
{
if (rRec.pPageView)
{
return SdrObjectPrimitiveHit(*this , rRec.aPos, {static_cast <double >(rRec.nTol), static_cast <double >(rRec.nTol)}, *rRec.pPageView, rRec.pVisiLayer, false );
}
return nullptr;
}
PointerStyle SdrObject::GetMacroPointer(const SdrObjMacroHitRec&) const
{
return PointerStyle::RefHand;
}
void SdrObject::PaintMacro(OutputDevice& rOut, const tools::Rectangle& , const SdrObjMacroHitRec& ) const
{
const RasterOp eRop(rOut.GetRasterOp());
const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly());
rOut.SetLineColor(COL_BLACK);
rOut.SetFillColor();
rOut.SetRasterOp(RasterOp::Invert);
for (auto const & rPolygon : aPolyPolygon)
{
rOut.DrawPolyLine(rPolygon);
}
rOut.SetRasterOp(eRop);
}
bool SdrObject::DoMacro(const SdrObjMacroHitRec&)
{
return false ;
}
bool SdrObject::IsMacroHit(const SdrObjMacroHitRec& rRec) const
{
return CheckMacroHit(rRec) != nullptr;
}
std::unique_ptr<SdrObjGeoData> SdrObject::NewGeoData() const
{
return std::make_unique<SdrObjGeoData>();
}
void SdrObject::SaveGeoData(SdrObjGeoData& rGeo) const
{
rGeo.aBoundRect =GetCurrentBoundRect();
rGeo.aAnchor =m_aAnchor ;
rGeo.bMovProt =m_bMovProt ;
rGeo.bSizProt =m_bSizProt ;
rGeo.bNoPrint =m_bNoPrint ;
rGeo.mbVisible =mbVisible ;
rGeo.bClosedObj =m_bClosedObj ;
rGeo.mnLayerID = mnLayerID;
// user-defined gluepoints
if (m_pPlusData!=nullptr && m_pPlusData->pGluePoints!=nullptr) {
rGeo.moGluePoints = *m_pPlusData->pGluePoints;
} else {
rGeo.moGluePoints.reset();
}
}
void SdrObject::RestoreGeoData(const SdrObjGeoData& rGeo)
{
SetBoundAndSnapRectsDirty();
setOutRectangle(rGeo.aBoundRect);
m_aAnchor =rGeo.aAnchor ;
m_bMovProt =rGeo.bMovProt ;
m_bSizProt =rGeo.bSizProt ;
m_bNoPrint =rGeo.bNoPrint ;
mbVisible =rGeo.mbVisible ;
m_bClosedObj =rGeo.bClosedObj ;
mnLayerID = rGeo.mnLayerID;
// user-defined gluepoints
if (rGeo.moGluePoints) {
ImpForcePlusData();
if (m_pPlusData->pGluePoints!=nullptr) {
*m_pPlusData->pGluePoints=*rGeo.moGluePoints;
} else {
m_pPlusData->pGluePoints.reset(new SdrGluePointList(*rGeo.moGluePoints));
}
} else {
if (m_pPlusData!=nullptr && m_pPlusData->pGluePoints!=nullptr) {
m_pPlusData->pGluePoints.reset();
}
}
}
std::unique_ptr<SdrObjGeoData> SdrObject::GetGeoData() const
{
std::unique_ptr<SdrObjGeoData> pGeo = NewGeoData();
SaveGeoData(*pGeo);
return pGeo;
}
void SdrObject::SetGeoData(const SdrObjGeoData& rGeo)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
RestoreGeoData(rGeo);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
// ItemSet access
const SfxItemSet& SdrObject::GetObjectItemSet() const
{
return GetProperties().GetObjectItemSet();
}
const SfxItemSet& SdrObject::GetMergedItemSet() const
{
return GetProperties().GetMergedItemSet();
}
void SdrObject::SetObjectItem(const SfxPoolItem& rItem)
{
GetProperties().SetObjectItem(rItem);
}
void SdrObject::SetMergedItem(const SfxPoolItem& rItem)
{
GetProperties().SetMergedItem(rItem);
}
void SdrObject::ClearMergedItem(const sal_uInt16 nWhich)
{
GetProperties().ClearMergedItem(nWhich);
}
void SdrObject::SetObjectItemSet(const SfxItemSet& rSet)
{
GetProperties().SetObjectItemSet(rSet);
}
void SdrObject::SetMergedItemSet(const SfxItemSet& rSet, bool bClearAllItems, bool bAdjustTextFrameWidthAndHeight)
{
GetProperties().SetMergedItemSet(rSet, bClearAllItems, bAdjustTextFrameWidthAndHeight);
}
const SfxPoolItem& SdrObject::GetObjectItem(const sal_uInt16 nWhich) const
{
return GetObjectItemSet().Get(nWhich);
}
const SfxPoolItem& SdrObject::GetMergedItem(const sal_uInt16 nWhich) const
{
return GetMergedItemSet().Get(nWhich);
}
void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet& rSet, bool bClearAllItems)
{
GetProperties().SetMergedItemSetAndBroadcast(rSet, bClearAllItems);
}
void SdrObject::ApplyNotPersistAttr(const SfxItemSet& rAttr)
{
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
NbcApplyNotPersistAttr(rAttr);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
}
void SdrObject::NbcApplyNotPersistAttr(const SfxItemSet& rAttr)
{
const tools::Rectangle& rSnap=GetSnapRect();
const tools::Rectangle& rLogic=GetLogicRect();
Point aRef1(rSnap.Center());
if (const SdrTransformRef1XItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF1X))
{
aRef1.setX(pPoolItem->GetValue() );
}
if (const SdrTransformRef1YItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF1Y))
{
aRef1.setY(pPoolItem->GetValue() );
}
tools::Rectangle aNewSnap(rSnap);
if (const SdrMoveXItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_MOVEX))
{
tools::Long n = pPoolItem->GetValue();
aNewSnap.Move(n,0);
}
if (const SdrMoveYItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_MOVEY))
{
tools::Long n = pPoolItem->GetValue();
aNewSnap.Move(0,n);
}
if (const SdrOnePositionXItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONEPOSITIONX))
{
tools::Long n = pPoolItem->GetValue();
aNewSnap.Move(n-aNewSnap.Left(),0);
}
if (const SdrOnePositionYItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONEPOSITIONY))
{
tools::Long n = pPoolItem->GetValue();
aNewSnap.Move(0,n-aNewSnap.Top());
}
if (const SdrOneSizeWidthItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONESIZEWIDTH))
{
tools::Long n = pPoolItem->GetValue();
aNewSnap.SetRight(aNewSnap.Left()+n );
}
if (const SdrOneSizeHeightItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONESIZEHEIGHT))
{
tools::Long n = pPoolItem->GetValue();
aNewSnap.SetBottom(aNewSnap.Top()+n );
}
if (aNewSnap!=rSnap) {
if (aNewSnap.GetSize()==rSnap.GetSize()) {
NbcMove(Size(aNewSnap.Left()-rSnap.Left(),aNewSnap.Top()-rSnap.Top()));
} else {
NbcSetSnapRect(aNewSnap);
}
}
if (const SdrShearAngleItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_SHEARANGLE))
{
Degree100 n = pPoolItem->GetValue();
n-=GetShearAngle();
if (n) {
double nTan = tan(toRadians(n));
NbcShear(aRef1,n,nTan,false );
}
}
if (const SdrAngleItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ROTATEANGLE))
{
Degree100 n = pPoolItem->GetValue();
n-=GetRotateAngle();
if (n) {
NbcRotate(aRef1,n);
}
}
if (const SdrRotateOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ROTATEONE))
{
Degree100 n = pPoolItem->GetValue();
NbcRotate(aRef1,n);
}
if (const SdrHorzShearOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_HORZSHEARONE))
{
Degree100 n = pPoolItem->GetValue();
double nTan = tan(toRadians(n));
NbcShear(aRef1,n,nTan,false );
}
if (const SdrVertShearOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_VERTSHEARONE))
{
Degree100 n = pPoolItem->GetValue();
double nTan = tan(toRadians(n));
NbcShear(aRef1,n,nTan,true );
}
if (const SdrYesNoItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJMOVEPROTECT))
{
bool b = pPoolItem->GetValue();
SetMoveProtect(b);
}
if (const SdrYesNoItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJSIZEPROTECT))
{
bool b = pPoolItem->GetValue();
SetResizeProtect(b);
}
/* move protect always sets size protect */
if ( IsMoveProtect() )
SetResizeProtect( true );
if (const SdrObjPrintableItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJPRINTABLE))
{
bool b = pPoolItem->GetValue();
SetPrintable(b);
}
if (const SdrObjVisibleItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJVISIBLE))
{
bool b = pPoolItem->GetValue();
SetVisible(b);
}
SdrLayerID nLayer=SDRLAYER_NOTFOUND;
if (const SdrLayerIdItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERID))
{
nLayer = pPoolItem->GetValue();
}
if (const SdrLayerNameItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERNAME))
{
OUString aLayerName = pPoolItem->GetValue();
const SdrLayerAdmin& rLayAd(nullptr != getSdrPageFromSdrObject()
? getSdrPageFromSdrObject()->GetLayerAdmin()
: getSdrModelFromSdrObject().GetLayerAdmin());
const SdrLayer* pLayer = rLayAd.GetLayer(aLayerName);
if (nullptr != pLayer)
{
nLayer=pLayer->GetID();
}
}
if (nLayer!=SDRLAYER_NOTFOUND) {
NbcSetLayer(nLayer);
}
if (const SfxStringItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJECTNAME))
{
OUString aName = pPoolItem->GetValue();
SetName(aName);
}
tools::Rectangle aNewLogic(rLogic);
if (const SdrLogicSizeWidthItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LOGICSIZEWIDTH))
{
tools::Long n = pPoolItem->GetValue();
aNewLogic.SetRight(aNewLogic.Left()+n );
}
if (const SdrLogicSizeHeightItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LOGICSIZEHEIGHT))
{
tools::Long n = pPoolItem->GetValue();
aNewLogic.SetBottom(aNewLogic.Top()+n );
}
if (aNewLogic!=rLogic) {
NbcSetLogicRect(aNewLogic);
}
Fraction aResizeX(1,1);
Fraction aResizeY(1,1);
if (const SdrResizeXOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_RESIZEXONE))
{
aResizeX *= pPoolItem->GetValue();
}
if (const SdrResizeYOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_RESIZEYONE))
{
aResizeY *= pPoolItem->GetValue();
}
if (aResizeX!=Fraction(1,1) || aResizeY!=Fraction(1,1)) {
NbcResize(aRef1,aResizeX,aResizeY);
}
}
void SdrObject::TakeNotPersistAttr(SfxItemSet& rAttr) const
{
const tools::Rectangle& rSnap=GetSnapRect();
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=95 H=99 G=96
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland