3470 lines
104 KiB
C++
3470 lines
104 KiB
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 <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();
|
|
const tools::Rectangle& rLogic=GetLogicRect();
|
|
rAttr.Put(SdrYesNoItem(SDRATTR_OBJMOVEPROTECT, IsMoveProtect()));
|
|
rAttr.Put(SdrYesNoItem(SDRATTR_OBJSIZEPROTECT, IsResizeProtect()));
|
|
rAttr.Put(SdrObjPrintableItem(IsPrintable()));
|
|
rAttr.Put(SdrObjVisibleItem(IsVisible()));
|
|
rAttr.Put(SdrAngleItem(SDRATTR_ROTATEANGLE, GetRotateAngle()));
|
|
rAttr.Put(SdrShearAngleItem(GetShearAngle()));
|
|
rAttr.Put(SdrOneSizeWidthItem(rSnap.GetWidth()-1));
|
|
rAttr.Put(SdrOneSizeHeightItem(rSnap.GetHeight()-1));
|
|
rAttr.Put(SdrOnePositionXItem(rSnap.Left()));
|
|
rAttr.Put(SdrOnePositionYItem(rSnap.Top()));
|
|
if (rLogic.GetWidth()!=rSnap.GetWidth()) {
|
|
rAttr.Put(SdrLogicSizeWidthItem(rLogic.GetWidth()-1));
|
|
}
|
|
if (rLogic.GetHeight()!=rSnap.GetHeight()) {
|
|
rAttr.Put(SdrLogicSizeHeightItem(rLogic.GetHeight()-1));
|
|
}
|
|
OUString aName(GetName());
|
|
|
|
if (!aName.isEmpty())
|
|
{
|
|
rAttr.Put(SfxStringItem(SDRATTR_OBJECTNAME, aName));
|
|
}
|
|
|
|
rAttr.Put(SdrLayerIdItem(GetLayer()));
|
|
const SdrLayerAdmin& rLayAd(nullptr != getSdrPageFromSdrObject()
|
|
? getSdrPageFromSdrObject()->GetLayerAdmin()
|
|
: getSdrModelFromSdrObject().GetLayerAdmin());
|
|
const SdrLayer* pLayer = rLayAd.GetLayerPerID(GetLayer());
|
|
if(nullptr != pLayer)
|
|
{
|
|
rAttr.Put(SdrLayerNameItem(pLayer->GetName()));
|
|
}
|
|
Point aRef1(rSnap.Center());
|
|
Point aRef2(aRef1); aRef2.AdjustY( 1 );
|
|
rAttr.Put(SdrTransformRef1XItem(aRef1.X()));
|
|
rAttr.Put(SdrTransformRef1YItem(aRef1.Y()));
|
|
rAttr.Put(SdrTransformRef2XItem(aRef2.X()));
|
|
rAttr.Put(SdrTransformRef2YItem(aRef2.Y()));
|
|
}
|
|
|
|
SfxStyleSheet* SdrObject::GetStyleSheet() const
|
|
{
|
|
return GetProperties().GetStyleSheet();
|
|
}
|
|
|
|
void SdrObject::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr)
|
|
{
|
|
tools::Rectangle aBoundRect0;
|
|
|
|
if(m_pUserCall)
|
|
aBoundRect0 = GetLastBoundRect();
|
|
|
|
InternalSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, true);
|
|
SetChanged();
|
|
BroadcastObjectChange();
|
|
SendUserCall(SdrUserCallType::ChangeAttr, aBoundRect0);
|
|
}
|
|
|
|
void SdrObject::NbcSetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr, bool bAdjustTextFrameWidthAndHeight)
|
|
{
|
|
InternalSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, false, bAdjustTextFrameWidthAndHeight);
|
|
}
|
|
|
|
void SdrObject::InternalSetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr, bool bBroadcast, bool bAdjustTextFrameWidthAndHeight)
|
|
{
|
|
GetProperties().SetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, bBroadcast, bAdjustTextFrameWidthAndHeight);
|
|
}
|
|
|
|
// Broadcasting while setting attributes is managed by the AttrObj.
|
|
|
|
|
|
SdrGluePoint SdrObject::GetVertexGluePoint(sal_uInt16 nPosNum) const
|
|
{
|
|
// #i41936# Use SnapRect for default GluePoints
|
|
const tools::Rectangle aR(GetSnapRect());
|
|
Point aPt;
|
|
|
|
switch(nPosNum)
|
|
{
|
|
case 0 : aPt = aR.TopCenter(); break;
|
|
case 1 : aPt = aR.RightCenter(); break;
|
|
case 2 : aPt = aR.BottomCenter(); break;
|
|
case 3 : aPt = aR.LeftCenter(); break;
|
|
}
|
|
|
|
aPt -= aR.Center();
|
|
SdrGluePoint aGP(aPt);
|
|
aGP.SetPercent(false);
|
|
|
|
return aGP;
|
|
}
|
|
|
|
SdrGluePoint SdrObject::GetCornerGluePoint(sal_uInt16 nPosNum) const
|
|
{
|
|
tools::Rectangle aR(GetCurrentBoundRect());
|
|
Point aPt;
|
|
switch (nPosNum) {
|
|
case 0 : aPt=aR.TopLeft(); break;
|
|
case 1 : aPt=aR.TopRight(); break;
|
|
case 2 : aPt=aR.BottomRight(); break;
|
|
case 3 : aPt=aR.BottomLeft(); break;
|
|
}
|
|
aPt-=GetSnapRect().Center();
|
|
SdrGluePoint aGP(aPt);
|
|
aGP.SetPercent(false);
|
|
return aGP;
|
|
}
|
|
|
|
const SdrGluePointList* SdrObject::GetGluePointList() const
|
|
{
|
|
if (m_pPlusData!=nullptr) return m_pPlusData->pGluePoints.get();
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
SdrGluePointList* SdrObject::ForceGluePointList()
|
|
{
|
|
ImpForcePlusData();
|
|
if (m_pPlusData->pGluePoints==nullptr) {
|
|
m_pPlusData->pGluePoints.reset(new SdrGluePointList);
|
|
}
|
|
return m_pPlusData->pGluePoints.get();
|
|
}
|
|
|
|
void SdrObject::SetGlueReallyAbsolute(bool bOn)
|
|
{
|
|
// First a const call to see whether there are any gluepoints.
|
|
// Force const call!
|
|
if (GetGluePointList()!=nullptr) {
|
|
SdrGluePointList* pGPL=ForceGluePointList();
|
|
pGPL->SetReallyAbsolute(bOn,*this);
|
|
}
|
|
}
|
|
|
|
void SdrObject::NbcRotateGluePoints(const Point& rRef, Degree100 nAngle, double sn, double cs)
|
|
{
|
|
// First a const call to see whether there are any gluepoints.
|
|
// Force const call!
|
|
if (GetGluePointList()!=nullptr) {
|
|
SdrGluePointList* pGPL=ForceGluePointList();
|
|
pGPL->Rotate(rRef,nAngle,sn,cs,this);
|
|
}
|
|
}
|
|
|
|
void SdrObject::NbcMirrorGluePoints(const Point& rRef1, const Point& rRef2)
|
|
{
|
|
// First a const call to see whether there are any gluepoints.
|
|
// Force const call!
|
|
if (GetGluePointList()!=nullptr) {
|
|
SdrGluePointList* pGPL=ForceGluePointList();
|
|
pGPL->Mirror(rRef1,rRef2,this);
|
|
}
|
|
}
|
|
|
|
void SdrObject::NbcShearGluePoints(const Point& rRef, double tn, bool bVShear)
|
|
{
|
|
// First a const call to see whether there are any gluepoints.
|
|
// Force const call!
|
|
if (GetGluePointList()!=nullptr) {
|
|
SdrGluePointList* pGPL=ForceGluePointList();
|
|
pGPL->Shear(rRef,tn,bVShear,this);
|
|
}
|
|
}
|
|
|
|
void SdrObject::ConnectToNode(bool /*bTail1*/, SdrObject* /*pObj*/)
|
|
{
|
|
}
|
|
|
|
void SdrObject::DisconnectFromNode(bool /*bTail1*/)
|
|
{
|
|
}
|
|
|
|
SdrObject* SdrObject::GetConnectedNode(bool /*bTail1*/) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
static void extractLineContourFromPrimitive2DSequence(
|
|
const drawinglayer::primitive2d::Primitive2DContainer& rxSequence,
|
|
basegfx::B2DPolygonVector& rExtractedHairlines,
|
|
basegfx::B2DPolyPolygonVector& rExtractedLineFills)
|
|
{
|
|
rExtractedHairlines.clear();
|
|
rExtractedLineFills.clear();
|
|
|
|
if(rxSequence.empty())
|
|
return;
|
|
|
|
// use neutral ViewInformation
|
|
const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
|
|
|
|
// create extractor, process and get result
|
|
drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D);
|
|
aExtractor.process(rxSequence);
|
|
|
|
// copy line results
|
|
rExtractedHairlines = aExtractor.getExtractedHairlines();
|
|
|
|
// copy fill rsults
|
|
rExtractedLineFills = aExtractor.getExtractedLineFills();
|
|
}
|
|
|
|
|
|
rtl::Reference<SdrObject> SdrObject::ImpConvertToContourObj(bool bForceLineDash)
|
|
{
|
|
rtl::Reference<SdrObject> pRetval;
|
|
|
|
if(LineGeometryUsageIsNecessary())
|
|
{
|
|
basegfx::B2DPolyPolygon aMergedLineFillPolyPolygon;
|
|
basegfx::B2DPolyPolygon aMergedHairlinePolyPolygon;
|
|
drawinglayer::primitive2d::Primitive2DContainer xSequence;
|
|
GetViewContact().getViewIndependentPrimitive2DContainer(xSequence);
|
|
|
|
if(!xSequence.empty())
|
|
{
|
|
basegfx::B2DPolygonVector aExtractedHairlines;
|
|
basegfx::B2DPolyPolygonVector aExtractedLineFills;
|
|
|
|
extractLineContourFromPrimitive2DSequence(xSequence, aExtractedHairlines, aExtractedLineFills);
|
|
|
|
// for SdrObject creation, just copy all to a single Hairline-PolyPolygon
|
|
for(const basegfx::B2DPolygon & rExtractedHairline : aExtractedHairlines)
|
|
{
|
|
aMergedHairlinePolyPolygon.append(rExtractedHairline);
|
|
}
|
|
|
|
// check for fill rsults
|
|
if (!aExtractedLineFills.empty() && !comphelper::IsFuzzing())
|
|
{
|
|
// merge to a single tools::PolyPolygon (OR)
|
|
aMergedLineFillPolyPolygon = basegfx::utils::mergeToSinglePolyPolygon(std::move(aExtractedLineFills));
|
|
}
|
|
}
|
|
|
|
if(aMergedLineFillPolyPolygon.count() || (bForceLineDash && aMergedHairlinePolyPolygon.count()))
|
|
{
|
|
SfxItemSet aSet(GetMergedItemSet());
|
|
drawing::FillStyle eOldFillStyle = aSet.Get(XATTR_FILLSTYLE).GetValue();
|
|
rtl::Reference<SdrPathObj> aLinePolygonPart;
|
|
rtl::Reference<SdrPathObj> aLineHairlinePart;
|
|
bool bBuildGroup(false);
|
|
|
|
if(aMergedLineFillPolyPolygon.count())
|
|
{
|
|
// create SdrObject for filled line geometry
|
|
aLinePolygonPart = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathFill,
|
|
std::move(aMergedLineFillPolyPolygon));
|
|
|
|
// correct item properties
|
|
aSet.Put(XLineWidthItem(0));
|
|
aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
|
|
Color aColorLine = aSet.Get(XATTR_LINECOLOR).GetColorValue();
|
|
sal_uInt16 nTransLine = aSet.Get(XATTR_LINETRANSPARENCE).GetValue();
|
|
aSet.Put(XFillColorItem(OUString(), aColorLine));
|
|
aSet.Put(XFillStyleItem(drawing::FillStyle_SOLID));
|
|
aSet.Put(XFillTransparenceItem(nTransLine));
|
|
|
|
aLinePolygonPart->SetMergedItemSet(aSet);
|
|
}
|
|
|
|
if(aMergedHairlinePolyPolygon.count())
|
|
{
|
|
// create SdrObject for hairline geometry
|
|
// OBJ_PATHLINE is necessary here, not OBJ_PATHFILL. This is intended
|
|
// to get a non-filled object. If the poly is closed, the PathObj takes care for
|
|
// the correct closed state.
|
|
aLineHairlinePart = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathLine,
|
|
std::move(aMergedHairlinePolyPolygon));
|
|
|
|
aSet.Put(XLineWidthItem(0));
|
|
aSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
|
|
aSet.Put(XLineStyleItem(drawing::LineStyle_SOLID));
|
|
|
|
// it is also necessary to switch off line start and ends here
|
|
aSet.Put(XLineStartWidthItem(0));
|
|
aSet.Put(XLineEndWidthItem(0));
|
|
|
|
aLineHairlinePart->SetMergedItemSet(aSet);
|
|
|
|
if(aLinePolygonPart)
|
|
{
|
|
bBuildGroup = true;
|
|
}
|
|
}
|
|
|
|
// check if original geometry should be added (e.g. filled and closed)
|
|
bool bAddOriginalGeometry(false);
|
|
SdrPathObj* pPath = dynamic_cast<SdrPathObj*>(this);
|
|
|
|
if(pPath && pPath->IsClosed())
|
|
{
|
|
if(eOldFillStyle != drawing::FillStyle_NONE)
|
|
{
|
|
bAddOriginalGeometry = true;
|
|
}
|
|
}
|
|
|
|
// do we need a group?
|
|
if(bBuildGroup || bAddOriginalGeometry)
|
|
{
|
|
rtl::Reference<SdrObject> xGroup = new SdrObjGroup(getSdrModelFromSdrObject());
|
|
|
|
if(bAddOriginalGeometry)
|
|
{
|
|
// Add a clone of the original geometry.
|
|
aSet.ClearItem();
|
|
aSet.Put(GetMergedItemSet());
|
|
aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
|
|
aSet.Put(XLineWidthItem(0));
|
|
|
|
rtl::Reference<SdrObject> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
|
|
pClone->SetMergedItemSet(aSet);
|
|
|
|
xGroup->GetSubList()->NbcInsertObject(pClone.get());
|
|
}
|
|
|
|
if(aLinePolygonPart)
|
|
{
|
|
xGroup->GetSubList()->NbcInsertObject(aLinePolygonPart.get());
|
|
}
|
|
|
|
if(aLineHairlinePart)
|
|
{
|
|
xGroup->GetSubList()->NbcInsertObject(aLineHairlinePart.get());
|
|
}
|
|
|
|
pRetval = std::move(xGroup);
|
|
}
|
|
else
|
|
{
|
|
if(aLinePolygonPart)
|
|
{
|
|
pRetval = aLinePolygonPart;
|
|
}
|
|
else if(aLineHairlinePart)
|
|
{
|
|
pRetval = aLineHairlinePart;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!pRetval)
|
|
{
|
|
// due to current method usage, create and return a clone when nothing has changed
|
|
pRetval = CloneSdrObject(getSdrModelFromSdrObject());
|
|
}
|
|
|
|
return pRetval;
|
|
}
|
|
|
|
|
|
void SdrObject::SetMarkProtect(bool bProt)
|
|
{
|
|
m_bMarkProt = bProt;
|
|
}
|
|
|
|
|
|
void SdrObject::SetEmptyPresObj(bool bEpt)
|
|
{
|
|
m_bEmptyPresObj = bEpt;
|
|
}
|
|
|
|
|
|
void SdrObject::SetNotVisibleAsMaster(bool bFlg)
|
|
{
|
|
m_bNotVisibleAsMaster=bFlg;
|
|
}
|
|
|
|
|
|
// convert this path object to contour object, even when it is a group
|
|
rtl::Reference<SdrObject> SdrObject::ConvertToContourObj(SdrObject* pRet1, bool bForceLineDash) const
|
|
{
|
|
rtl::Reference<SdrObject> pRet = pRet1;
|
|
if(dynamic_cast<const SdrObjGroup*>( pRet.get()) != nullptr)
|
|
{
|
|
SdrObjList* pObjList2 = pRet->GetSubList();
|
|
rtl::Reference<SdrObject> pGroup = new SdrObjGroup(getSdrModelFromSdrObject());
|
|
|
|
for (const rtl::Reference<SdrObject>& pIterObj : *pObjList2)
|
|
pGroup->GetSubList()->NbcInsertObject(ConvertToContourObj(pIterObj.get(), bForceLineDash).get());
|
|
|
|
pRet = std::move(pGroup);
|
|
}
|
|
else
|
|
{
|
|
if (SdrPathObj *pPathObj = dynamic_cast<SdrPathObj*>(pRet.get()))
|
|
{
|
|
// bezier geometry got created, even for straight edges since the given
|
|
// object is a result of DoConvertToPolyObj. For conversion to contour
|
|
// this is not really needed and can be reduced again AFAP
|
|
pPathObj->SetPathPoly(basegfx::utils::simplifyCurveSegments(pPathObj->GetPathPoly()));
|
|
}
|
|
|
|
pRet = pRet->ImpConvertToContourObj(bForceLineDash);
|
|
}
|
|
|
|
// #i73441# preserve LayerID
|
|
if(pRet && pRet->GetLayer() != GetLayer())
|
|
{
|
|
pRet->SetLayer(GetLayer());
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
|
|
rtl::Reference<SdrObject> SdrObject::ConvertToPolyObj(bool bBezier, bool bLineToArea) const
|
|
{
|
|
rtl::Reference<SdrObject> pRet = DoConvertToPolyObj(bBezier, true);
|
|
|
|
if(pRet && bLineToArea)
|
|
{
|
|
pRet = ConvertToContourObj(pRet.get());
|
|
}
|
|
|
|
// #i73441# preserve LayerID
|
|
if(pRet && pRet->GetLayer() != GetLayer())
|
|
{
|
|
pRet->SetLayer(GetLayer());
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
|
|
rtl::Reference<SdrObject> SdrObject::DoConvertToPolyObj(bool /*bBezier*/, bool /*bAddText*/) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
void SdrObject::InsertedStateChange()
|
|
{
|
|
const bool bIsInserted(nullptr != getParentSdrObjListFromSdrObject());
|
|
const tools::Rectangle aBoundRect0(GetLastBoundRect());
|
|
|
|
if(bIsInserted)
|
|
{
|
|
SendUserCall(SdrUserCallType::Inserted, aBoundRect0);
|
|
}
|
|
else
|
|
{
|
|
SendUserCall(SdrUserCallType::Removed, aBoundRect0);
|
|
}
|
|
|
|
if(nullptr != m_pPlusData && nullptr != m_pPlusData->pBroadcast)
|
|
{
|
|
SdrHint aHint(bIsInserted ? SdrHintKind::ObjectInserted : SdrHintKind::ObjectRemoved, *this);
|
|
m_pPlusData->pBroadcast->Broadcast(aHint);
|
|
}
|
|
}
|
|
|
|
void SdrObject::SetMoveProtect(bool bProt)
|
|
{
|
|
if(IsMoveProtect() != bProt)
|
|
{
|
|
// #i77187# secured and simplified
|
|
m_bMovProt = bProt;
|
|
SetChanged();
|
|
BroadcastObjectChange();
|
|
}
|
|
}
|
|
|
|
void SdrObject::SetResizeProtect(bool bProt)
|
|
{
|
|
if(IsResizeProtect() != bProt)
|
|
{
|
|
// #i77187# secured and simplified
|
|
m_bSizProt = bProt;
|
|
SetChanged();
|
|
BroadcastObjectChange();
|
|
}
|
|
}
|
|
|
|
bool SdrObject::IsPrintable() const
|
|
{
|
|
return !m_bNoPrint;
|
|
}
|
|
|
|
void SdrObject::SetPrintable(bool bPrn)
|
|
{
|
|
if( bPrn == m_bNoPrint )
|
|
{
|
|
m_bNoPrint=!bPrn;
|
|
SetChanged();
|
|
if (IsInserted())
|
|
{
|
|
SdrHint aHint(SdrHintKind::ObjectChange, *this);
|
|
getSdrModelFromSdrObject().Broadcast(aHint);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SdrObject::IsVisible() const
|
|
{
|
|
return mbVisible;
|
|
}
|
|
|
|
void SdrObject::SetVisible(bool bVisible)
|
|
{
|
|
if( bVisible != mbVisible )
|
|
{
|
|
mbVisible = bVisible;
|
|
SetChanged();
|
|
if (IsInserted())
|
|
{
|
|
SdrHint aHint(SdrHintKind::ObjectChange, *this);
|
|
getSdrModelFromSdrObject().Broadcast(aHint);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
sal_uInt16 SdrObject::GetUserDataCount() const
|
|
{
|
|
if (m_pPlusData==nullptr || m_pPlusData->pUserDataList==nullptr) return 0;
|
|
return m_pPlusData->pUserDataList->GetUserDataCount();
|
|
}
|
|
|
|
SdrObjUserData* SdrObject::GetUserData(sal_uInt16 nNum) const
|
|
{
|
|
if (m_pPlusData==nullptr || m_pPlusData->pUserDataList==nullptr) return nullptr;
|
|
return &m_pPlusData->pUserDataList->GetUserData(nNum);
|
|
}
|
|
|
|
void SdrObject::AppendUserData(std::unique_ptr<SdrObjUserData> pData)
|
|
{
|
|
if (!pData)
|
|
{
|
|
OSL_FAIL("SdrObject::AppendUserData(): pData is NULL pointer.");
|
|
return;
|
|
}
|
|
|
|
ImpForcePlusData();
|
|
if (!m_pPlusData->pUserDataList)
|
|
m_pPlusData->pUserDataList.reset( new SdrObjUserDataList );
|
|
|
|
m_pPlusData->pUserDataList->AppendUserData(std::move(pData));
|
|
}
|
|
|
|
void SdrObject::DeleteUserData(sal_uInt16 nNum)
|
|
{
|
|
sal_uInt16 nCount=GetUserDataCount();
|
|
if (nNum<nCount) {
|
|
m_pPlusData->pUserDataList->DeleteUserData(nNum);
|
|
if (nCount==1) {
|
|
m_pPlusData->pUserDataList.reset();
|
|
}
|
|
} else {
|
|
OSL_FAIL("SdrObject::DeleteUserData(): Invalid Index.");
|
|
}
|
|
}
|
|
|
|
void SdrObject::SetUserCall(SdrObjUserCall* pUser)
|
|
{
|
|
m_pUserCall = pUser;
|
|
}
|
|
|
|
|
|
void SdrObject::SendUserCall(SdrUserCallType eUserCall, const tools::Rectangle& rBoundRect) const
|
|
{
|
|
SdrObject* pGroup(getParentSdrObjectFromSdrObject());
|
|
|
|
if ( m_pUserCall )
|
|
{
|
|
m_pUserCall->Changed( *this, eUserCall, rBoundRect );
|
|
}
|
|
|
|
if(nullptr != pGroup && pGroup->GetUserCall())
|
|
{
|
|
// broadcast to group
|
|
SdrUserCallType eChildUserType = SdrUserCallType::ChildChangeAttr;
|
|
|
|
switch( eUserCall )
|
|
{
|
|
case SdrUserCallType::MoveOnly:
|
|
eChildUserType = SdrUserCallType::ChildMoveOnly;
|
|
break;
|
|
|
|
case SdrUserCallType::Resize:
|
|
eChildUserType = SdrUserCallType::ChildResize;
|
|
break;
|
|
|
|
case SdrUserCallType::ChangeAttr:
|
|
eChildUserType = SdrUserCallType::ChildChangeAttr;
|
|
break;
|
|
|
|
case SdrUserCallType::Delete:
|
|
eChildUserType = SdrUserCallType::ChildDelete;
|
|
break;
|
|
|
|
case SdrUserCallType::Inserted:
|
|
eChildUserType = SdrUserCallType::ChildInserted;
|
|
break;
|
|
|
|
case SdrUserCallType::Removed:
|
|
eChildUserType = SdrUserCallType::ChildRemoved;
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
pGroup->GetUserCall()->Changed( *this, eChildUserType, rBoundRect );
|
|
}
|
|
|
|
// notify our UNO shape listeners
|
|
switch ( eUserCall )
|
|
{
|
|
case SdrUserCallType::Resize:
|
|
notifyShapePropertyChange( u"Size"_ustr );
|
|
[[fallthrough]]; // RESIZE might also imply a change of the position
|
|
case SdrUserCallType::MoveOnly:
|
|
notifyShapePropertyChange( u"Position"_ustr );
|
|
break;
|
|
default:
|
|
// not interested in
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SdrObject::setUnoShape( const uno::Reference< drawing::XShape >& _rxUnoShape )
|
|
{
|
|
const uno::Reference< uno::XInterface> xOldUnoShape( maWeakUnoShape );
|
|
// the UNO shape would be gutted by the following code; return early
|
|
if ( _rxUnoShape == xOldUnoShape )
|
|
{
|
|
if ( !xOldUnoShape.is() )
|
|
{
|
|
// make sure there is no stale impl. pointer if the UNO
|
|
// shape was destroyed meanwhile (remember we only hold weak
|
|
// reference to it!)
|
|
mpSvxShape = nullptr;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( xOldUnoShape.is() )
|
|
{
|
|
// Remove yourself from the current UNO shape. Its destructor
|
|
// will reset our UNO shape otherwise.
|
|
mpSvxShape->InvalidateSdrObject();
|
|
}
|
|
|
|
maWeakUnoShape = _rxUnoShape;
|
|
mpSvxShape = comphelper::getFromUnoTunnel<SvxShape>( _rxUnoShape );
|
|
}
|
|
|
|
/** only for internal use! */
|
|
SvxShape* SdrObject::getSvxShape()
|
|
{
|
|
DBG_TESTSOLARMUTEX();
|
|
// retrieving the impl pointer and subsequently using it is not thread-safe, of course, so it needs to be
|
|
// guarded by the SolarMutex
|
|
|
|
uno::Reference< uno::XInterface > xShape( maWeakUnoShape );
|
|
//#113608#, make sure mpSvxShape is always synchronized with maWeakUnoShape
|
|
if ( mpSvxShape && !xShape )
|
|
mpSvxShape = nullptr;
|
|
|
|
return mpSvxShape;
|
|
}
|
|
|
|
css::uno::Reference< css::drawing::XShape > SdrObject::getUnoShape()
|
|
{
|
|
// try weak reference first
|
|
uno::Reference< css::drawing::XShape > xShape = maWeakUnoShape;
|
|
if (xShape)
|
|
return xShape;
|
|
|
|
// try to access SdrPage from this SdrObject. This will only exist if the SdrObject is
|
|
// inserted in a SdrObjList (page/group/3dScene)
|
|
SdrPage* pPageCandidate(getSdrPageFromSdrObject());
|
|
|
|
// tdf#12152, tdf#120728
|
|
//
|
|
// With the paradigm change to only get a SdrPage for a SdrObject when the SdrObject
|
|
// is *inserted*, the functionality for creating 1:1 associated UNO API implementation
|
|
// SvxShapes was partially broken: The used ::CreateShape relies on the SvxPage being
|
|
// derived and the CreateShape method overloaded, implementing additional SdrInventor
|
|
// types as needed.
|
|
//
|
|
// The fallback to use SvxDrawPage::CreateShapeByTypeAndInventor is a trap: It's only
|
|
// a static fallback that handles the SdrInventor types SdrInventor::E3d and
|
|
// SdrInventor::Default. Due to that, e.g. the ReportDesigner broke in various conditions.
|
|
//
|
|
// That again has to do with the ReportDesigner being implemented using the UNO API
|
|
// aspects of SdrObjects early during their construction, not just after these are
|
|
// inserted to a SdrPage - but that is not illegal or wrong, the SdrObject exists already.
|
|
//
|
|
// As a current solution, use the (now always available) SdrModel and any of the
|
|
// existing SdrPages. The only important thing is to get a SdrPage where ::CreateShape is
|
|
// overloaded and implemented as needed.
|
|
//
|
|
// Note for the future:
|
|
// In a more ideal world there would be only one factory method for creating SdrObjects (not
|
|
// ::CreateShape and ::CreateShapeByTypeAndInventor). This also would not be placed at
|
|
// SdrPage/SvxPage at all, but at the Model where it belongs - where else would you expect
|
|
// objects for the current Model to be constructed? To have this at the Page only would make
|
|
// sense if different shapes would need to be constructed for different Pages in the same Model
|
|
// - this is never the case.
|
|
// At that Model extended functionality for that factory (or overloads and implementations)
|
|
// should be placed. But to be realistic, migrating the factories to Model now is too much
|
|
// work - maybe over time when melting SdrObject/SvxObject one day...
|
|
//
|
|
// More Note (added by noel grandin)
|
|
// Except that sd/ is being naughty and doing all kinds of magic during CreateShape that
|
|
// requires knowing which page the object is being created for. Fixing that would require
|
|
// moving a bunch of nasty logic from object creation time, to the point in time when
|
|
// it is actually added to a page.
|
|
if(nullptr == pPageCandidate)
|
|
{
|
|
// If not inserted, alternatively access a SdrPage using the SdrModel. There is
|
|
// no reason not to create and return a UNO API XShape when the SdrObject is not
|
|
// inserted - it may be in construction. Main paradigm is that it exists.
|
|
if(0 != getSdrModelFromSdrObject().GetPageCount())
|
|
{
|
|
// Take 1st SdrPage. That may be e.g. a special page (in SD), but the
|
|
// to-be-used method ::CreateShape will be correctly overloaded in
|
|
// all cases
|
|
pPageCandidate = getSdrModelFromSdrObject().GetPage(0);
|
|
}
|
|
}
|
|
|
|
if(nullptr != pPageCandidate)
|
|
{
|
|
uno::Reference< uno::XInterface > xPage(pPageCandidate->getUnoPage());
|
|
if( xPage.is() )
|
|
{
|
|
SvxDrawPage* pDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>(xPage);
|
|
if( pDrawPage )
|
|
{
|
|
// create one
|
|
xShape = pDrawPage->CreateShape( this );
|
|
assert(xShape);
|
|
setUnoShape( xShape );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Fallback to static base functionality. CAUTION: This will only support
|
|
// the most basic stuff like SdrInventor::E3d and SdrInventor::Default. All
|
|
// the other SdrInventor enum entries are from overloads and are *not accessible*
|
|
// using this fallback (!) - what a bad trap
|
|
rtl::Reference<SvxShape> xNewShape = SvxDrawPage::CreateShapeByTypeAndInventor( GetObjIdentifier(), GetObjInventor(), this );
|
|
mpSvxShape = xNewShape.get();
|
|
maWeakUnoShape = xShape = mpSvxShape;
|
|
}
|
|
|
|
return xShape;
|
|
}
|
|
|
|
void SdrObject::notifyShapePropertyChange( const OUString& rPropName ) const
|
|
{
|
|
DBG_TESTSOLARMUTEX();
|
|
|
|
SvxShape* pSvxShape = const_cast< SdrObject* >( this )->getSvxShape();
|
|
if ( pSvxShape )
|
|
return pSvxShape->notifyPropertyChange( rPropName );
|
|
}
|
|
|
|
// transformation interface for StarOfficeAPI. This implements support for
|
|
// homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
|
|
// moment it contains a shearX, rotation and translation, but for setting all linear
|
|
// transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
|
|
|
|
|
|
// gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
|
|
// with the base geometry and returns TRUE. Otherwise it returns FALSE.
|
|
bool SdrObject::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
|
|
{
|
|
// any kind of SdrObject, just use SnapRect
|
|
tools::Rectangle aRectangle(GetSnapRect());
|
|
|
|
// convert to transformation values
|
|
basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
|
|
basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
|
|
|
|
// position maybe relative to anchorpos, convert
|
|
if(getSdrModelFromSdrObject().IsWriter())
|
|
{
|
|
if(GetAnchorPos().X() || GetAnchorPos().Y())
|
|
{
|
|
aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
|
|
}
|
|
}
|
|
|
|
// build matrix
|
|
rMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(aScale, aTranslate);
|
|
|
|
return false;
|
|
}
|
|
|
|
// sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
|
|
// If it's an SdrPathObj it will use the provided geometry information. The Polygon has
|
|
// to use (0,0) as upper left and will be scaled to the given size in the matrix.
|
|
void SdrObject::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
|
|
{
|
|
// break up matrix
|
|
basegfx::B2DTuple aScale;
|
|
basegfx::B2DTuple aTranslate;
|
|
double fRotate, fShearX;
|
|
rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
|
|
// #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
|
|
// in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
|
|
if(aScale.getX() < 0.0 && aScale.getY() < 0.0)
|
|
{
|
|
aScale.setX(fabs(aScale.getX()));
|
|
aScale.setY(fabs(aScale.getY()));
|
|
}
|
|
|
|
// if anchor is used, make position relative to it
|
|
if(getSdrModelFromSdrObject().IsWriter())
|
|
{
|
|
if(GetAnchorPos().X() || GetAnchorPos().Y())
|
|
{
|
|
aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
|
|
}
|
|
}
|
|
|
|
// build BaseRect
|
|
Point aPoint(basegfx::fround<tools::Long>(aTranslate.getX()),
|
|
basegfx::fround<tools::Long>(aTranslate.getY()));
|
|
tools::Rectangle aBaseRect(aPoint, Size(basegfx::fround<tools::Long>(aScale.getX()),
|
|
basegfx::fround<tools::Long>(aScale.getY())));
|
|
|
|
// set BaseRect
|
|
SetSnapRect(aBaseRect);
|
|
}
|
|
|
|
// Give info if object is in destruction
|
|
bool SdrObject::IsInDestruction() const
|
|
{
|
|
return getSdrModelFromSdrObject().IsInDestruction();
|
|
}
|
|
|
|
// return if fill is != drawing::FillStyle_NONE
|
|
bool SdrObject::HasFillStyle() const
|
|
{
|
|
return GetObjectItem(XATTR_FILLSTYLE).GetValue() != drawing::FillStyle_NONE;
|
|
}
|
|
|
|
bool SdrObject::HasLineStyle() const
|
|
{
|
|
return GetObjectItem(XATTR_LINESTYLE).GetValue() != drawing::LineStyle_NONE;
|
|
}
|
|
|
|
|
|
// #i52224#
|
|
// on import of OLE object from MS documents the BLIP size might be retrieved,
|
|
// the following four methods are used to control it;
|
|
// usually this data makes no sense after the import is finished, since the object
|
|
// might be resized
|
|
|
|
|
|
void SdrObject::SetBLIPSizeRectangle( const tools::Rectangle& aRect )
|
|
{
|
|
maBLIPSizeRectangle = aRect;
|
|
}
|
|
|
|
void SdrObject::SetContextWritingMode( const sal_Int16 /*_nContextWritingMode*/ )
|
|
{
|
|
// this base class does not support different writing modes, so ignore the call
|
|
}
|
|
|
|
void SdrObject::SetDoNotInsertIntoPageAutomatically(const bool bSet)
|
|
{
|
|
mbDoNotInsertIntoPageAutomatically = bSet;
|
|
}
|
|
|
|
|
|
// #i121917#
|
|
bool SdrObject::HasText() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool SdrObject::IsTextBox() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void SdrObject::MakeNameUnique()
|
|
{
|
|
if (GetName().isEmpty())
|
|
{
|
|
OUString aName;
|
|
if (const E3dScene* pE3dObj = DynCastE3dScene(this))
|
|
{
|
|
SdrObjList* pObjList = pE3dObj->GetSubList();
|
|
if (pObjList)
|
|
{
|
|
SdrObject* pObj0 = pObjList->GetObj(0);
|
|
if (pObj0)
|
|
aName = pObj0->TakeObjNameSingul();
|
|
}
|
|
}
|
|
else
|
|
aName = TakeObjNameSingul();
|
|
SetName(aName + " 1");
|
|
}
|
|
|
|
std::unordered_set<OUString> aNameSet;
|
|
MakeNameUnique(aNameSet);
|
|
}
|
|
|
|
void SdrObject::MakeNameUnique(std::unordered_set<OUString>& rNameSet)
|
|
{
|
|
if (GetName().isEmpty())
|
|
return;
|
|
|
|
if (rNameSet.empty())
|
|
{
|
|
SdrPage* pPage;
|
|
SdrObject* pObj;
|
|
for (sal_uInt16 nPage(0); nPage < mrSdrModelFromSdrObject.GetPageCount(); ++nPage)
|
|
{
|
|
pPage = mrSdrModelFromSdrObject.GetPage(nPage);
|
|
SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
|
|
while (aIter.IsMore())
|
|
{
|
|
pObj = aIter.Next();
|
|
if (pObj != this)
|
|
rNameSet.insert(pObj->GetName());
|
|
}
|
|
}
|
|
}
|
|
|
|
OUString sName(GetName().trim());
|
|
OUString sRootName(sName);
|
|
|
|
if (!sName.isEmpty() && rtl::isAsciiDigit(sName[sName.getLength() - 1]))
|
|
{
|
|
sal_Int32 nPos(sName.getLength() - 1);
|
|
while (nPos > 0 && rtl::isAsciiDigit(sName[--nPos]));
|
|
sRootName = o3tl::trim(sName.subView(0, nPos + 1));
|
|
}
|
|
|
|
for (sal_uInt32 n = 1; rNameSet.find(sName) != rNameSet.end(); n++)
|
|
sName = sRootName + " " + OUString::number(n);
|
|
rNameSet.insert(sName);
|
|
|
|
SetName(sName);
|
|
}
|
|
|
|
void SdrObject::ForceMetricToItemPoolMetric(basegfx::B2DPolyPolygon& rPolyPolygon) const noexcept
|
|
{
|
|
MapUnit eMapUnit(getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
|
|
if(eMapUnit == MapUnit::Map100thMM)
|
|
return;
|
|
|
|
if (const auto eTo = MapToO3tlLength(eMapUnit); eTo != o3tl::Length::invalid)
|
|
{
|
|
const double fConvert(o3tl::convert(1.0, o3tl::Length::mm100, eTo));
|
|
rPolyPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(fConvert, fConvert));
|
|
}
|
|
else
|
|
{
|
|
OSL_FAIL("Missing unit translation to PoolMetric!");
|
|
}
|
|
}
|
|
|
|
const tools::Rectangle& SdrObject::getOutRectangle() const
|
|
{
|
|
return m_aOutRect;
|
|
}
|
|
|
|
void SdrObject::setOutRectangleConst(tools::Rectangle const& rRectangle) const
|
|
{
|
|
m_aOutRect = rRectangle;
|
|
}
|
|
|
|
void SdrObject::setOutRectangle(tools::Rectangle const& rRectangle)
|
|
{
|
|
m_aOutRect = rRectangle;
|
|
}
|
|
|
|
void SdrObject::resetOutRectangle()
|
|
{
|
|
m_aOutRect = tools::Rectangle();
|
|
}
|
|
|
|
void SdrObject::moveOutRectangle(sal_Int32 nXDelta, sal_Int32 nYDelta)
|
|
{
|
|
m_aOutRect.Move(nXDelta, nYDelta);
|
|
}
|
|
|
|
E3dScene* DynCastE3dScene(SdrObject* pObj)
|
|
{
|
|
if( pObj && pObj->GetObjInventor() == SdrInventor::E3d && pObj->GetObjIdentifier() == SdrObjKind::E3D_Scene )
|
|
return static_cast<E3dScene*>(pObj);
|
|
return nullptr;
|
|
}
|
|
|
|
E3dObject* DynCastE3dObject(SdrObject* pObj)
|
|
{
|
|
if( pObj && pObj->GetObjInventor() == SdrInventor::E3d )
|
|
return static_cast<E3dObject*>(pObj);
|
|
return nullptr;
|
|
}
|
|
|
|
SdrTextObj* DynCastSdrTextObj(SdrObject* pObj)
|
|
{
|
|
// SdrTextObj has a lot of subclasses, with lots of SdrObjKind identifiers, so use a virtual method
|
|
// to be safer.
|
|
if( pObj && pObj->IsSdrTextObj() )
|
|
return static_cast<SdrTextObj*>(pObj);
|
|
return nullptr;
|
|
}
|
|
|
|
SdrOle2Obj* DynCastSdrOle2Obj(SdrObject* pObj)
|
|
{
|
|
// SdrTextObj has subclasses, with lots of SdrObjKind identifiers, so use a virtual method
|
|
// to be safer.
|
|
if( pObj && pObj->IsSdrOle2Obj() )
|
|
return static_cast<SdrOle2Obj*>(pObj);
|
|
return nullptr;
|
|
}
|
|
|
|
rtl::Reference<SdrObject> SdrObjFactory::CreateObjectFromFactory(SdrModel& rSdrModel, SdrInventor nInventor, SdrObjKind nObjIdentifier)
|
|
{
|
|
SdrObjCreatorParams aParams { nInventor, nObjIdentifier, rSdrModel };
|
|
for (const auto & i : ImpGetUserMakeObjHdl()) {
|
|
rtl::Reference<SdrObject> pObj = i.Call(aParams);
|
|
if (pObj) {
|
|
return pObj;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
|
|
// SdrObject subclass, which represents an empty object of a
|
|
// certain type (kind).
|
|
template <SdrObjKind OBJECT_KIND, SdrInventor OBJECT_INVENTOR>
|
|
class EmptyObject final : public SdrObject
|
|
{
|
|
private:
|
|
virtual ~EmptyObject() override
|
|
{}
|
|
|
|
public:
|
|
EmptyObject(SdrModel& rSdrModel)
|
|
: SdrObject(rSdrModel)
|
|
{
|
|
}
|
|
|
|
EmptyObject(SdrModel& rSdrModel, EmptyObject const& rSource)
|
|
: SdrObject(rSdrModel, rSource)
|
|
{
|
|
}
|
|
|
|
rtl::Reference<SdrObject> CloneSdrObject(SdrModel& rTargetModel) const override
|
|
{
|
|
return new EmptyObject(rTargetModel, *this);
|
|
}
|
|
|
|
virtual std::unique_ptr<sdr::properties::BaseProperties> CreateObjectSpecificProperties() override
|
|
{
|
|
return std::make_unique<sdr::properties::EmptyProperties>(*this);
|
|
}
|
|
|
|
SdrInventor GetObjInventor() const override
|
|
{
|
|
return OBJECT_INVENTOR;
|
|
}
|
|
|
|
SdrObjKind GetObjIdentifier() const override
|
|
{
|
|
return OBJECT_KIND;
|
|
}
|
|
|
|
void NbcRotate(const Point& /*rRef*/, Degree100 /*nAngle*/, double /*sinAngle*/, double /*cosAngle*/) override
|
|
{
|
|
assert(false); // should not be called for this kind of objects
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
rtl::Reference<SdrObject> SdrObjFactory::MakeNewObject(
|
|
SdrModel& rSdrModel,
|
|
SdrInventor nInventor,
|
|
SdrObjKind nIdentifier,
|
|
const tools::Rectangle* pSnapRect)
|
|
{
|
|
rtl::Reference<SdrObject> pObj;
|
|
bool bSetSnapRect(nullptr != pSnapRect);
|
|
|
|
if (nInventor == SdrInventor::Default)
|
|
{
|
|
switch (nIdentifier)
|
|
{
|
|
case SdrObjKind::Measure:
|
|
{
|
|
if(nullptr != pSnapRect)
|
|
{
|
|
pObj = new SdrMeasureObj(
|
|
rSdrModel,
|
|
pSnapRect->TopLeft(),
|
|
pSnapRect->BottomRight());
|
|
}
|
|
else
|
|
{
|
|
pObj = new SdrMeasureObj(rSdrModel);
|
|
}
|
|
}
|
|
break;
|
|
case SdrObjKind::Line:
|
|
{
|
|
if(nullptr != pSnapRect)
|
|
{
|
|
basegfx::B2DPolygon aPoly;
|
|
|
|
aPoly.append(
|
|
basegfx::B2DPoint(
|
|
pSnapRect->Left(),
|
|
pSnapRect->Top()));
|
|
aPoly.append(
|
|
basegfx::B2DPoint(
|
|
pSnapRect->Right(),
|
|
pSnapRect->Bottom()));
|
|
pObj = new SdrPathObj(
|
|
rSdrModel,
|
|
SdrObjKind::Line,
|
|
basegfx::B2DPolyPolygon(aPoly));
|
|
}
|
|
else
|
|
{
|
|
pObj = new SdrPathObj(
|
|
rSdrModel,
|
|
SdrObjKind::Line);
|
|
}
|
|
}
|
|
break;
|
|
case SdrObjKind::Text:
|
|
case SdrObjKind::TitleText:
|
|
case SdrObjKind::OutlineText:
|
|
{
|
|
if(nullptr != pSnapRect)
|
|
{
|
|
pObj = new SdrRectObj(
|
|
rSdrModel,
|
|
nIdentifier,
|
|
*pSnapRect);
|
|
bSetSnapRect = false;
|
|
}
|
|
else
|
|
{
|
|
pObj = new SdrRectObj(
|
|
rSdrModel,
|
|
nIdentifier);
|
|
}
|
|
}
|
|
break;
|
|
case SdrObjKind::CircleOrEllipse:
|
|
case SdrObjKind::CircleSection:
|
|
case SdrObjKind::CircleArc:
|
|
case SdrObjKind::CircleCut:
|
|
{
|
|
SdrCircKind eCircKind = ToSdrCircKind(nIdentifier);
|
|
if(nullptr != pSnapRect)
|
|
{
|
|
pObj = new SdrCircObj(rSdrModel, eCircKind, *pSnapRect);
|
|
bSetSnapRect = false;
|
|
}
|
|
else
|
|
{
|
|
pObj = new SdrCircObj(rSdrModel, eCircKind);
|
|
}
|
|
}
|
|
break;
|
|
case SdrObjKind::NONE: pObj = nullptr; break;
|
|
case SdrObjKind::Group : pObj=new SdrObjGroup(rSdrModel); break;
|
|
case SdrObjKind::Polygon : pObj=new SdrPathObj(rSdrModel, SdrObjKind::Polygon ); break;
|
|
case SdrObjKind::PolyLine : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PolyLine ); break;
|
|
case SdrObjKind::PathLine : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PathLine ); break;
|
|
case SdrObjKind::PathFill : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PathFill ); break;
|
|
case SdrObjKind::FreehandLine : pObj=new SdrPathObj(rSdrModel, SdrObjKind::FreehandLine ); break;
|
|
case SdrObjKind::FreehandFill : pObj=new SdrPathObj(rSdrModel, SdrObjKind::FreehandFill ); break;
|
|
case SdrObjKind::PathPoly : pObj=new SdrPathObj(rSdrModel, SdrObjKind::Polygon ); break;
|
|
case SdrObjKind::PathPolyLine : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PolyLine ); break;
|
|
case SdrObjKind::Edge : pObj=new SdrEdgeObj(rSdrModel); break;
|
|
case SdrObjKind::Rectangle : pObj=new SdrRectObj(rSdrModel); break;
|
|
case SdrObjKind::Graphic : pObj=new SdrGrafObj(rSdrModel); break;
|
|
case SdrObjKind::OLE2 : pObj=new SdrOle2Obj(rSdrModel); break;
|
|
case SdrObjKind::OLEPluginFrame : pObj=new SdrOle2Obj(rSdrModel, true); break;
|
|
case SdrObjKind::Caption : pObj=new SdrCaptionObj(rSdrModel); break;
|
|
case SdrObjKind::Page : pObj=new SdrPageObj(rSdrModel); break;
|
|
case SdrObjKind::UNO : pObj=new SdrUnoObj(rSdrModel, OUString()); break;
|
|
case SdrObjKind::CustomShape: pObj=new SdrObjCustomShape(rSdrModel); break;
|
|
#if HAVE_FEATURE_AVMEDIA
|
|
case SdrObjKind::Media : pObj=new SdrMediaObj(rSdrModel); break;
|
|
#endif
|
|
case SdrObjKind::Table : pObj=new sdr::table::SdrTableObj(rSdrModel); break;
|
|
case SdrObjKind::NewFrame: // used for frame creation in writer
|
|
pObj = new EmptyObject<SdrObjKind::NewFrame, SdrInventor::Default>(rSdrModel);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pObj)
|
|
{
|
|
pObj = CreateObjectFromFactory(rSdrModel, nInventor, nIdentifier);
|
|
}
|
|
|
|
if (!pObj)
|
|
{
|
|
// Well, if no one wants it...
|
|
return nullptr;
|
|
}
|
|
|
|
if(bSetSnapRect && nullptr != pSnapRect)
|
|
{
|
|
pObj->NbcSetSnapRect(*pSnapRect);
|
|
}
|
|
|
|
return pObj;
|
|
}
|
|
|
|
void SdrObjFactory::InsertMakeObjectHdl(Link<SdrObjCreatorParams, rtl::Reference<SdrObject>> const & rLink)
|
|
{
|
|
std::vector<Link<SdrObjCreatorParams, rtl::Reference<SdrObject>>>& rLL=ImpGetUserMakeObjHdl();
|
|
auto it = std::find(rLL.begin(), rLL.end(), rLink);
|
|
if (it != rLL.end()) {
|
|
OSL_FAIL("SdrObjFactory::InsertMakeObjectHdl(): Link already in place.");
|
|
} else {
|
|
rLL.push_back(rLink);
|
|
}
|
|
}
|
|
|
|
void SdrObjFactory::RemoveMakeObjectHdl(Link<SdrObjCreatorParams, rtl::Reference<SdrObject>> const & rLink)
|
|
{
|
|
std::vector<Link<SdrObjCreatorParams, rtl::Reference<SdrObject>>>& rLL=ImpGetUserMakeObjHdl();
|
|
auto it = std::find(rLL.begin(), rLL.end(), rLink);
|
|
if (it != rLL.end())
|
|
rLL.erase(it);
|
|
}
|
|
|
|
namespace svx
|
|
{
|
|
ISdrObjectFilter::~ISdrObjectFilter()
|
|
{
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|