1840 lines
48 KiB
C++
1840 lines
48 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 <cassert>
|
|
|
|
#include <svx/svdpage.hxx>
|
|
|
|
// HACK
|
|
#include <sot/storage.hxx>
|
|
#include <comphelper/classids.hxx>
|
|
#include <svx/svdview.hxx>
|
|
#include <string.h>
|
|
#include <vcl/svapp.hxx>
|
|
|
|
#include <tools/diagnose_ex.h>
|
|
#include <tools/helpers.hxx>
|
|
|
|
#include <svx/svdetc.hxx>
|
|
#include <svx/svdobj.hxx>
|
|
#include <svx/svdogrp.hxx>
|
|
#include <svx/svdograf.hxx>
|
|
#include <svx/svdoedge.hxx>
|
|
#include <svx/svdoole2.hxx>
|
|
#include "svx/svditer.hxx"
|
|
#include <svx/svdmodel.hxx>
|
|
#include <svx/svdlayer.hxx>
|
|
#include <svx/svdotext.hxx>
|
|
#include <svx/svdpagv.hxx>
|
|
#include <svx/svdundo.hxx>
|
|
#include <svx/fmglob.hxx>
|
|
#include <svx/polysc3d.hxx>
|
|
|
|
#include <svx/fmdpage.hxx>
|
|
|
|
#include <sfx2/objsh.hxx>
|
|
#include <sdr/contact/viewcontactofsdrpage.hxx>
|
|
#include <svx/sdr/contact/viewobjectcontact.hxx>
|
|
#include <svx/sdr/contact/displayinfo.hxx>
|
|
#include <algorithm>
|
|
#include <svl/smplhint.hxx>
|
|
#include <rtl/strbuf.hxx>
|
|
#include <libxml/xmlwriter.h>
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
class SdrObjList::WeakSdrObjectContainerType
|
|
: public ::std::vector<SdrObjectWeakRef>
|
|
{
|
|
public:
|
|
explicit WeakSdrObjectContainerType (const sal_Int32 nInitialSize)
|
|
: ::std::vector<SdrObjectWeakRef>(nInitialSize) {};
|
|
};
|
|
|
|
|
|
|
|
static const sal_Int32 InitialObjectContainerCapacity (64);
|
|
|
|
TYPEINIT0(SdrObjList);
|
|
|
|
SdrObjList::SdrObjList(SdrModel* pNewModel, SdrPage* pNewPage, SdrObjList* pNewUpList):
|
|
maList(),
|
|
mxNavigationOrder(),
|
|
mbIsNavigationOrderDirty(false)
|
|
{
|
|
maList.reserve(InitialObjectContainerCapacity);
|
|
pModel=pNewModel;
|
|
pPage=pNewPage;
|
|
pUpList=pNewUpList;
|
|
bObjOrdNumsDirty=false;
|
|
bRectsDirty=false;
|
|
pOwnerObj=NULL;
|
|
eListKind=SDROBJLIST_UNKNOWN;
|
|
}
|
|
|
|
SdrObjList::SdrObjList():
|
|
maList(),
|
|
mxNavigationOrder(),
|
|
mbIsNavigationOrderDirty(false)
|
|
{
|
|
maList.reserve(InitialObjectContainerCapacity);
|
|
pModel=NULL;
|
|
pPage=NULL;
|
|
pUpList=NULL;
|
|
bObjOrdNumsDirty=false;
|
|
bRectsDirty=false;
|
|
pOwnerObj=NULL;
|
|
eListKind=SDROBJLIST_UNKNOWN;
|
|
}
|
|
|
|
SdrObjList::~SdrObjList()
|
|
{
|
|
|
|
// To avoid that the Clear() method will broadcast changes when in destruction
|
|
// which would call virtual methos (not allowed in destructor), the model is set
|
|
// to NULL here.
|
|
pModel = 0L;
|
|
|
|
Clear(); // delete contents of container
|
|
}
|
|
|
|
SdrObjList* SdrObjList::Clone() const
|
|
{
|
|
SdrObjList* const pObjList = new SdrObjList();
|
|
pObjList->lateInit(*this);
|
|
return pObjList;
|
|
}
|
|
|
|
void SdrObjList::lateInit(const SdrObjList& rSrcList)
|
|
{
|
|
// this function is only supposed to be called once, right after construction
|
|
assert(maList.empty());
|
|
|
|
eListKind=rSrcList.eListKind;
|
|
CopyObjects(rSrcList);
|
|
}
|
|
|
|
void SdrObjList::CopyObjects(const SdrObjList& rSrcList)
|
|
{
|
|
Clear();
|
|
bObjOrdNumsDirty=false;
|
|
bRectsDirty =false;
|
|
size_t nCloneErrCnt = 0;
|
|
const size_t nCount = rSrcList.GetObjCount();
|
|
SdrInsertReason aReason(SDRREASON_COPY);
|
|
for (size_t no=0; no<nCount; ++no) {
|
|
SdrObject* pSO=rSrcList.GetObj(no);
|
|
|
|
SdrObject* pDO = pSO->Clone();
|
|
|
|
if (pDO!=NULL) {
|
|
pDO->SetModel(pModel);
|
|
pDO->SetPage(pPage);
|
|
NbcInsertObject(pDO, SAL_MAX_SIZE, &aReason);
|
|
} else {
|
|
nCloneErrCnt++;
|
|
}
|
|
}
|
|
|
|
// and now for the Connectors
|
|
// The new objects would be shown in the rSrcList
|
|
// and then the object connections are made.
|
|
// Similar implementation are setup as the following:
|
|
// void SdrObjList::CopyObjects(const SdrObjList& rSrcList)
|
|
// SdrModel* SdrExchangeView::GetMarkedObjModel() const
|
|
// BOOL SdrExchangeView::Paste(const SdrModel& rMod,...)
|
|
// void SdrEditView::CopyMarked()
|
|
if (nCloneErrCnt==0) {
|
|
for (size_t no=0; no<nCount; ++no) {
|
|
const SdrObject* pSrcOb=rSrcList.GetObj(no);
|
|
const SdrEdgeObj* pSrcEdge=PTR_CAST(SdrEdgeObj,pSrcOb);
|
|
if (pSrcEdge!=NULL) {
|
|
SdrObject* pSrcNode1=pSrcEdge->GetConnectedNode(true);
|
|
SdrObject* pSrcNode2=pSrcEdge->GetConnectedNode(false);
|
|
if (pSrcNode1!=NULL && pSrcNode1->GetObjList()!=pSrcEdge->GetObjList()) pSrcNode1=NULL; // can't do this
|
|
if (pSrcNode2!=NULL && pSrcNode2->GetObjList()!=pSrcEdge->GetObjList()) pSrcNode2=NULL; // across all lists (yet)
|
|
if (pSrcNode1!=NULL || pSrcNode2!=NULL) {
|
|
SdrObject* pEdgeObjTmp=GetObj(no);
|
|
SdrEdgeObj* pDstEdge=PTR_CAST(SdrEdgeObj,pEdgeObjTmp);
|
|
if (pDstEdge!=NULL) {
|
|
if (pSrcNode1!=NULL) {
|
|
sal_uIntPtr nDstNode1=pSrcNode1->GetOrdNum();
|
|
SdrObject* pDstNode1=GetObj(nDstNode1);
|
|
if (pDstNode1!=NULL) { // else we get an error!
|
|
pDstEdge->ConnectToNode(true,pDstNode1);
|
|
} else {
|
|
OSL_FAIL("SdrObjList::operator=(): pDstNode1==NULL!");
|
|
}
|
|
}
|
|
if (pSrcNode2!=NULL) {
|
|
sal_uIntPtr nDstNode2=pSrcNode2->GetOrdNum();
|
|
SdrObject* pDstNode2=GetObj(nDstNode2);
|
|
if (pDstNode2!=NULL) { // else the node was probably not selected
|
|
pDstEdge->ConnectToNode(false,pDstNode2);
|
|
} else {
|
|
OSL_FAIL("SdrObjList::operator=(): pDstNode2==NULL!");
|
|
}
|
|
}
|
|
} else {
|
|
OSL_FAIL("SdrObjList::operator=(): pDstEdge==NULL!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
#ifdef DBG_UTIL
|
|
OStringBuffer aStr("SdrObjList::operator=(): Error when cloning ");
|
|
|
|
if(nCloneErrCnt == 1)
|
|
{
|
|
aStr.append("a drawing object.");
|
|
}
|
|
else
|
|
{
|
|
aStr.append(static_cast<sal_Int32>(nCloneErrCnt));
|
|
aStr.append(" drawing objects.");
|
|
}
|
|
|
|
aStr.append(" Not copying connectors.");
|
|
|
|
OSL_FAIL(aStr.getStr());
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void SdrObjList::Clear()
|
|
{
|
|
bool bObjectsRemoved(false);
|
|
|
|
while( ! maList.empty())
|
|
{
|
|
// remove last object from list
|
|
SdrObject* pObj = maList.back();
|
|
RemoveObjectFromContainer(maList.size()-1);
|
|
|
|
// flushViewObjectContacts() is done since SdrObject::Free is not guaranteed
|
|
// to delete the object and thus refresh visualisations
|
|
pObj->GetViewContact().flushViewObjectContacts(true);
|
|
|
|
bObjectsRemoved = true;
|
|
|
|
// sent remove hint (after removal, see RemoveObject())
|
|
if(pModel)
|
|
{
|
|
SdrHint aHint(*pObj);
|
|
aHint.SetKind(HINT_OBJREMOVED);
|
|
aHint.SetPage(pPage);
|
|
pModel->Broadcast(aHint);
|
|
}
|
|
|
|
// delete the object itself
|
|
SdrObject::Free( pObj );
|
|
}
|
|
|
|
if(pModel && bObjectsRemoved)
|
|
{
|
|
pModel->SetChanged();
|
|
}
|
|
}
|
|
|
|
SdrPage* SdrObjList::GetPage() const
|
|
{
|
|
return pPage;
|
|
}
|
|
|
|
void SdrObjList::SetPage(SdrPage* pNewPage)
|
|
{
|
|
if (pPage!=pNewPage) {
|
|
pPage=pNewPage;
|
|
const size_t nCount = GetObjCount();
|
|
for (size_t no=0; no<nCount; ++no) {
|
|
SdrObject* pObj=GetObj(no);
|
|
pObj->SetPage(pPage);
|
|
}
|
|
}
|
|
}
|
|
|
|
SdrModel* SdrObjList::GetModel() const
|
|
{
|
|
return pModel;
|
|
}
|
|
|
|
void SdrObjList::SetModel(SdrModel* pNewModel)
|
|
{
|
|
if (pModel!=pNewModel) {
|
|
pModel=pNewModel;
|
|
const size_t nCount = GetObjCount();
|
|
for (size_t i=0; i<nCount; ++i) {
|
|
SdrObject* pObj=GetObj(i);
|
|
pObj->SetModel(pModel);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrObjList::RecalcObjOrdNums()
|
|
{
|
|
const size_t nCount = GetObjCount();
|
|
for (size_t no=0; no<nCount; ++no) {
|
|
SdrObject* pObj=GetObj(no);
|
|
pObj->SetOrdNum(no);
|
|
}
|
|
bObjOrdNumsDirty=false;
|
|
}
|
|
|
|
void SdrObjList::RecalcRects()
|
|
{
|
|
aOutRect=Rectangle();
|
|
aSnapRect=aOutRect;
|
|
const size_t nCount = GetObjCount();
|
|
for (size_t i=0; i<nCount; ++i) {
|
|
SdrObject* pObj=GetObj(i);
|
|
if (i==0) {
|
|
aOutRect=pObj->GetCurrentBoundRect();
|
|
aSnapRect=pObj->GetSnapRect();
|
|
} else {
|
|
aOutRect.Union(pObj->GetCurrentBoundRect());
|
|
aSnapRect.Union(pObj->GetSnapRect());
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrObjList::SetRectsDirty()
|
|
{
|
|
bRectsDirty=true;
|
|
if (pUpList!=NULL) pUpList->SetRectsDirty();
|
|
}
|
|
|
|
void SdrObjList::impChildInserted(SdrObject& rChild)
|
|
{
|
|
sdr::contact::ViewContact* pParent = rChild.GetViewContact().GetParentContact();
|
|
|
|
if(pParent)
|
|
{
|
|
pParent->ActionChildInserted(rChild.GetViewContact());
|
|
}
|
|
}
|
|
|
|
void SdrObjList::NbcInsertObject(SdrObject* pObj, size_t nPos, const SdrInsertReason* /*pReason*/)
|
|
{
|
|
DBG_ASSERT(pObj!=NULL,"SdrObjList::NbcInsertObject(NULL)");
|
|
if (pObj!=NULL) {
|
|
DBG_ASSERT(!pObj->IsInserted(),"ZObjekt already has the status Inserted.");
|
|
const size_t nCount = GetObjCount();
|
|
if (nPos>nCount) nPos=nCount;
|
|
InsertObjectIntoContainer(*pObj,nPos);
|
|
|
|
if (nPos<nCount) bObjOrdNumsDirty=true;
|
|
pObj->SetOrdNum(nPos);
|
|
pObj->SetObjList(this);
|
|
pObj->SetPage(pPage);
|
|
|
|
// Inform the parent about change to allow invalidations at
|
|
// evtl. existing parent visualisations
|
|
impChildInserted(*pObj);
|
|
|
|
if (!bRectsDirty) {
|
|
aOutRect.Union(pObj->GetCurrentBoundRect());
|
|
aSnapRect.Union(pObj->GetSnapRect());
|
|
}
|
|
pObj->SetInserted(true); // calls the UserCall (among others)
|
|
}
|
|
}
|
|
|
|
void SdrObjList::InsertObject(SdrObject* pObj, size_t nPos, const SdrInsertReason* pReason)
|
|
{
|
|
DBG_ASSERT(pObj!=NULL,"SdrObjList::InsertObject(NULL)");
|
|
|
|
if(pObj)
|
|
{
|
|
// if anchor is used, reset it before grouping
|
|
if(GetOwnerObj())
|
|
{
|
|
const Point& rAnchorPos = pObj->GetAnchorPos();
|
|
if(rAnchorPos.X() || rAnchorPos.Y())
|
|
pObj->NbcSetAnchorPos(Point());
|
|
}
|
|
|
|
// do insert to new group
|
|
NbcInsertObject(pObj, nPos, pReason);
|
|
|
|
// In case the object is inserted into a group and doesn't overlap with
|
|
// the group's other members, it needs an own repaint.
|
|
if(pOwnerObj)
|
|
{
|
|
// only repaint here
|
|
pOwnerObj->ActionChanged();
|
|
}
|
|
|
|
if(pModel)
|
|
{
|
|
// TODO: We need a different broadcast here!
|
|
// Repaint from object number ... (heads-up: GroupObj)
|
|
if(pObj->GetPage())
|
|
{
|
|
SdrHint aHint(*pObj);
|
|
|
|
aHint.SetKind(HINT_OBJINSERTED);
|
|
pModel->Broadcast(aHint);
|
|
}
|
|
|
|
pModel->SetChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
SdrObject* SdrObjList::NbcRemoveObject(size_t nObjNum)
|
|
{
|
|
if (nObjNum >= maList.size())
|
|
{
|
|
OSL_ASSERT(nObjNum<maList.size());
|
|
return NULL;
|
|
}
|
|
|
|
const size_t nCount = GetObjCount();
|
|
SdrObject* pObj=maList[nObjNum];
|
|
RemoveObjectFromContainer(nObjNum);
|
|
|
|
DBG_ASSERT(pObj!=NULL,"Could not find object to remove.");
|
|
if (pObj!=NULL) {
|
|
// flushViewObjectContacts() clears the VOC's and those invalidate
|
|
pObj->GetViewContact().flushViewObjectContacts(true);
|
|
|
|
DBG_ASSERT(pObj->IsInserted(),"ZObjekt does not have the status Inserted.");
|
|
pObj->SetInserted(false); // Ruft u.a. den UserCall
|
|
pObj->SetObjList(NULL);
|
|
pObj->SetPage(NULL);
|
|
if (!bObjOrdNumsDirty) { // optimizing for the case that the last object has to be removed
|
|
if (nObjNum+1!=nCount) {
|
|
bObjOrdNumsDirty=true;
|
|
}
|
|
}
|
|
SetRectsDirty();
|
|
}
|
|
return pObj;
|
|
}
|
|
|
|
SdrObject* SdrObjList::RemoveObject(size_t nObjNum)
|
|
{
|
|
if (nObjNum >= maList.size())
|
|
{
|
|
OSL_ASSERT(nObjNum<maList.size());
|
|
return NULL;
|
|
}
|
|
|
|
const size_t nCount = GetObjCount();
|
|
SdrObject* pObj=maList[nObjNum];
|
|
RemoveObjectFromContainer(nObjNum);
|
|
|
|
DBG_ASSERT(pObj!=NULL,"Object to remove not found.");
|
|
if(pObj)
|
|
{
|
|
// flushViewObjectContacts() clears the VOC's and those invalidate
|
|
pObj->GetViewContact().flushViewObjectContacts(true);
|
|
|
|
DBG_ASSERT(pObj->IsInserted(),"ZObjekt does not have the status Inserted.");
|
|
if (pModel!=NULL) {
|
|
// TODO: We need a different broadcast here.
|
|
if (pObj->GetPage()!=NULL) {
|
|
SdrHint aHint(*pObj);
|
|
aHint.SetKind(HINT_OBJREMOVED);
|
|
pModel->Broadcast(aHint);
|
|
}
|
|
pModel->SetChanged();
|
|
}
|
|
pObj->SetInserted(false); // calls, among other things, the UserCall
|
|
pObj->SetObjList(NULL);
|
|
pObj->SetPage(NULL);
|
|
if (!bObjOrdNumsDirty) { // optimization for the case that the last object is removed
|
|
if (nObjNum+1!=nCount) {
|
|
bObjOrdNumsDirty=true;
|
|
}
|
|
}
|
|
SetRectsDirty();
|
|
|
|
if(pOwnerObj && !GetObjCount())
|
|
{
|
|
// empty group created; it needs to be repainted since it's
|
|
// visualization changes
|
|
pOwnerObj->ActionChanged();
|
|
}
|
|
}
|
|
return pObj;
|
|
}
|
|
|
|
SdrObject* SdrObjList::NbcReplaceObject(SdrObject* pNewObj, size_t nObjNum)
|
|
{
|
|
if (nObjNum >= maList.size() || pNewObj == NULL)
|
|
{
|
|
OSL_ASSERT(nObjNum<maList.size());
|
|
OSL_ASSERT(pNewObj!=NULL);
|
|
return NULL;
|
|
}
|
|
|
|
SdrObject* pObj=maList[nObjNum];
|
|
DBG_ASSERT(pObj!=NULL,"SdrObjList::ReplaceObject: Could not find object to remove.");
|
|
if (pObj!=NULL) {
|
|
DBG_ASSERT(pObj->IsInserted(),"SdrObjList::ReplaceObject: ZObjekt does not have status Inserted.");
|
|
pObj->SetInserted(false);
|
|
pObj->SetObjList(NULL);
|
|
pObj->SetPage(NULL);
|
|
ReplaceObjectInContainer(*pNewObj,nObjNum);
|
|
|
|
// flushViewObjectContacts() clears the VOC's and those invalidate
|
|
pObj->GetViewContact().flushViewObjectContacts(true);
|
|
|
|
pNewObj->SetOrdNum(nObjNum);
|
|
pNewObj->SetObjList(this);
|
|
pNewObj->SetPage(pPage);
|
|
|
|
// Inform the parent about change to allow invalidations at
|
|
// evtl. existing parent visualisations
|
|
impChildInserted(*pNewObj);
|
|
|
|
pNewObj->SetInserted(true);
|
|
SetRectsDirty();
|
|
}
|
|
return pObj;
|
|
}
|
|
|
|
SdrObject* SdrObjList::ReplaceObject(SdrObject* pNewObj, size_t nObjNum)
|
|
{
|
|
if (nObjNum >= maList.size())
|
|
{
|
|
OSL_ASSERT(nObjNum<maList.size());
|
|
return NULL;
|
|
}
|
|
if (pNewObj == NULL)
|
|
{
|
|
OSL_ASSERT(pNewObj!=NULL);
|
|
return NULL;
|
|
}
|
|
|
|
SdrObject* pObj=maList[nObjNum];
|
|
DBG_ASSERT(pObj!=NULL,"SdrObjList::ReplaceObject: Could not find object to remove.");
|
|
if (pObj!=NULL) {
|
|
DBG_ASSERT(pObj->IsInserted(),"SdrObjList::ReplaceObject: ZObjekt does not have status Inserted.");
|
|
if (pModel!=NULL) {
|
|
// TODO: We need a different broadcast here.
|
|
if (pObj->GetPage()!=NULL) {
|
|
SdrHint aHint(*pObj);
|
|
aHint.SetKind(HINT_OBJREMOVED);
|
|
pModel->Broadcast(aHint);
|
|
}
|
|
}
|
|
pObj->SetInserted(false);
|
|
pObj->SetObjList(NULL);
|
|
pObj->SetPage(NULL);
|
|
ReplaceObjectInContainer(*pNewObj,nObjNum);
|
|
|
|
// flushViewObjectContacts() clears the VOC's and those invalidate
|
|
pObj->GetViewContact().flushViewObjectContacts(true);
|
|
|
|
pNewObj->SetOrdNum(nObjNum);
|
|
pNewObj->SetObjList(this);
|
|
pNewObj->SetPage(pPage);
|
|
|
|
// Inform the parent about change to allow invalidations at
|
|
// evtl. existing parent visualisations
|
|
impChildInserted(*pNewObj);
|
|
|
|
pNewObj->SetInserted(true);
|
|
if (pModel!=NULL) {
|
|
// TODO: We need a different broadcast here.
|
|
if (pNewObj->GetPage()!=NULL) {
|
|
SdrHint aHint(*pNewObj);
|
|
aHint.SetKind(HINT_OBJINSERTED);
|
|
pModel->Broadcast(aHint);
|
|
}
|
|
pModel->SetChanged();
|
|
}
|
|
SetRectsDirty();
|
|
}
|
|
return pObj;
|
|
}
|
|
|
|
SdrObject* SdrObjList::SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum)
|
|
{
|
|
if (nOldObjNum >= maList.size() || nNewObjNum >= maList.size())
|
|
{
|
|
OSL_ASSERT(nOldObjNum<maList.size());
|
|
OSL_ASSERT(nNewObjNum<maList.size());
|
|
return NULL;
|
|
}
|
|
|
|
SdrObject* pObj=maList[nOldObjNum];
|
|
if (nOldObjNum==nNewObjNum) return pObj;
|
|
DBG_ASSERT(pObj!=NULL,"SdrObjList::SetObjectOrdNum: Object not found.");
|
|
if (pObj!=NULL) {
|
|
DBG_ASSERT(pObj->IsInserted(),"SdrObjList::SetObjectOrdNum: ZObjekt does not have status Inserted.");
|
|
RemoveObjectFromContainer(nOldObjNum);
|
|
InsertObjectIntoContainer(*pObj,nNewObjNum);
|
|
|
|
// No need to delete visualisation data since same object
|
|
// gets inserted again. Also a single ActionChanged is enough
|
|
pObj->ActionChanged();
|
|
|
|
pObj->SetOrdNum(nNewObjNum);
|
|
bObjOrdNumsDirty=true;
|
|
if (pModel!=NULL)
|
|
{
|
|
// TODO: We need a different broadcast here.
|
|
if (pObj->GetPage()!=NULL) pModel->Broadcast(SdrHint(*pObj));
|
|
pModel->SetChanged();
|
|
}
|
|
}
|
|
return pObj;
|
|
}
|
|
|
|
const Rectangle& SdrObjList::GetAllObjSnapRect() const
|
|
{
|
|
if (bRectsDirty) {
|
|
const_cast<SdrObjList*>(this)->RecalcRects();
|
|
const_cast<SdrObjList*>(this)->bRectsDirty=false;
|
|
}
|
|
return aSnapRect;
|
|
}
|
|
|
|
const Rectangle& SdrObjList::GetAllObjBoundRect() const
|
|
{
|
|
// #i106183# for deep group hierarchies like in chart2, the invalidates
|
|
// through the hierarchy are not correct; use a 2nd hint for the needed
|
|
// recalculation. Future versions will have no bool flag at all, but
|
|
// just aOutRect in empty state to represent an invalid state, thus
|
|
// it's a step in the right direction.
|
|
if (bRectsDirty || aOutRect.IsEmpty())
|
|
{
|
|
const_cast<SdrObjList*>(this)->RecalcRects();
|
|
const_cast<SdrObjList*>(this)->bRectsDirty=false;
|
|
}
|
|
return aOutRect;
|
|
}
|
|
|
|
void SdrObjList::NbcReformatAllTextObjects()
|
|
{
|
|
size_t nCount=GetObjCount();
|
|
size_t nNum=0;
|
|
|
|
while (nNum<nCount)
|
|
{
|
|
SdrObject* pObj = GetObj(nNum);
|
|
|
|
pObj->NbcReformatText();
|
|
nCount=GetObjCount(); // ReformatText may delete an object
|
|
nNum++;
|
|
}
|
|
|
|
}
|
|
|
|
void SdrObjList::ReformatAllTextObjects()
|
|
{
|
|
NbcReformatAllTextObjects();
|
|
}
|
|
|
|
/** steps over all available objects and reformats all
|
|
edge objects that are connected to other objects so that
|
|
they may reposition themselves.
|
|
*/
|
|
void SdrObjList::ReformatAllEdgeObjects()
|
|
{
|
|
// #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
|
|
SdrObjListIter aIter(*this, IM_DEEPNOGROUPS);
|
|
|
|
while(aIter.IsMore())
|
|
{
|
|
SdrEdgeObj* pSdrEdgeObj = dynamic_cast< SdrEdgeObj* >(aIter.Next());
|
|
|
|
if(pSdrEdgeObj)
|
|
{
|
|
pSdrEdgeObj->Reformat();
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrObjList::BurnInStyleSheetAttributes()
|
|
{
|
|
for(size_t a = 0; a < GetObjCount(); ++a)
|
|
{
|
|
GetObj(a)->BurnInStyleSheetAttributes();
|
|
}
|
|
}
|
|
|
|
size_t SdrObjList::GetObjCount() const
|
|
{
|
|
return maList.size();
|
|
}
|
|
|
|
|
|
|
|
|
|
SdrObject* SdrObjList::GetObj(size_t nNum) const
|
|
{
|
|
if (nNum >= maList.size())
|
|
{
|
|
OSL_ASSERT(nNum<maList.size());
|
|
return NULL;
|
|
}
|
|
else
|
|
return maList[nNum];
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SdrObjList::IsReadOnly() const
|
|
{
|
|
bool bRet = false;
|
|
if (pPage!=NULL && pPage!=this) bRet=pPage->IsReadOnly();
|
|
return bRet;
|
|
}
|
|
|
|
size_t SdrObjList::CountAllObjects() const
|
|
{
|
|
const size_t nCount=GetObjCount();
|
|
size_t nCnt=nCount;
|
|
for (size_t nNum=0; nNum<nCount; nNum++) {
|
|
SdrObjList* pSubOL=GetObj(nNum)->GetSubList();
|
|
if (pSubOL!=NULL) {
|
|
nCnt+=pSubOL->CountAllObjects();
|
|
}
|
|
}
|
|
return nCnt;
|
|
}
|
|
|
|
void SdrObjList::FlattenGroups()
|
|
{
|
|
const size_t nObj = GetObjCount();
|
|
for( size_t i = nObj; i>0; )
|
|
UnGroupObj(--i);
|
|
}
|
|
|
|
void SdrObjList::UnGroupObj( size_t nObjNum )
|
|
{
|
|
// if the given object is no group, this method is a noop
|
|
SdrObject* pUngroupObj = GetObj( nObjNum );
|
|
if( pUngroupObj )
|
|
{
|
|
SdrObjList* pSrcLst = pUngroupObj->GetSubList();
|
|
if( pUngroupObj->ISA( SdrObjGroup ) && pSrcLst )
|
|
{
|
|
SdrObjGroup* pUngroupGroup = static_cast< SdrObjGroup* > (pUngroupObj);
|
|
|
|
// ungroup recursively (has to be head recursion,
|
|
// otherwise our indices will get trashed when doing it in
|
|
// the loop)
|
|
pSrcLst->FlattenGroups();
|
|
|
|
// the position at which we insert the members of rUngroupGroup
|
|
size_t nInsertPos( pUngroupGroup->GetOrdNum() );
|
|
|
|
const size_t nCount = pSrcLst->GetObjCount();
|
|
for( size_t i=0; i<nCount; ++i )
|
|
{
|
|
SdrObject* pObj = pSrcLst->RemoveObject(0);
|
|
SdrInsertReason aReason(SDRREASON_VIEWCALL, pUngroupGroup);
|
|
InsertObject(pObj, nInsertPos, &aReason);
|
|
++nInsertPos;
|
|
}
|
|
|
|
RemoveObject(nInsertPos);
|
|
}
|
|
}
|
|
#ifdef DBG_UTIL
|
|
else
|
|
OSL_FAIL("SdrObjList::UnGroupObj: object index invalid");
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SdrObjList::HasObjectNavigationOrder() const
|
|
{
|
|
return mxNavigationOrder.get() != NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdrObjList::SetObjectNavigationPosition (
|
|
SdrObject& rObject,
|
|
const sal_uInt32 nNewPosition)
|
|
{
|
|
// When the navigation order container has not yet been created then
|
|
// create one now. It is initialized with the z-order taken from
|
|
// maList.
|
|
if (mxNavigationOrder.get() == NULL)
|
|
{
|
|
mxNavigationOrder.reset(new WeakSdrObjectContainerType(maList.size()));
|
|
::std::copy(
|
|
maList.begin(),
|
|
maList.end(),
|
|
mxNavigationOrder->begin());
|
|
}
|
|
OSL_ASSERT(mxNavigationOrder.get()!=NULL);
|
|
OSL_ASSERT( mxNavigationOrder->size() == maList.size());
|
|
|
|
SdrObjectWeakRef aReference (&rObject);
|
|
|
|
// Look up the object whose navigation position is to be changed.
|
|
WeakSdrObjectContainerType::iterator iObject (::std::find(
|
|
mxNavigationOrder->begin(),
|
|
mxNavigationOrder->end(),
|
|
aReference));
|
|
if (iObject == mxNavigationOrder->end())
|
|
{
|
|
// The given object is not a member of the navigation order.
|
|
return;
|
|
}
|
|
|
|
// Move the object to its new position.
|
|
const sal_uInt32 nOldPosition = ::std::distance(mxNavigationOrder->begin(), iObject);
|
|
if (nOldPosition != nNewPosition)
|
|
{
|
|
mxNavigationOrder->erase(iObject);
|
|
sal_uInt32 nInsertPosition (nNewPosition);
|
|
// Adapt insertion position for the just erased object.
|
|
if (nNewPosition >= nOldPosition)
|
|
nInsertPosition -= 1;
|
|
if (nInsertPosition >= mxNavigationOrder->size())
|
|
mxNavigationOrder->push_back(aReference);
|
|
else
|
|
mxNavigationOrder->insert(mxNavigationOrder->begin()+nInsertPosition, aReference);
|
|
|
|
mbIsNavigationOrderDirty = true;
|
|
|
|
// The navigation order is written out to file so mark the model as modified.
|
|
if (pModel != NULL)
|
|
pModel->SetChanged();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
SdrObject* SdrObjList::GetObjectForNavigationPosition (const sal_uInt32 nNavigationPosition) const
|
|
{
|
|
if (HasObjectNavigationOrder())
|
|
{
|
|
// There is a user defined navigation order. Make sure the object
|
|
// index is correct and look up the object in mxNavigationOrder.
|
|
if (nNavigationPosition >= mxNavigationOrder->size())
|
|
{
|
|
OSL_ASSERT(nNavigationPosition < mxNavigationOrder->size());
|
|
}
|
|
else
|
|
return (*mxNavigationOrder)[nNavigationPosition].get();
|
|
}
|
|
else
|
|
{
|
|
// There is no user defined navigation order. Use the z-order
|
|
// instead.
|
|
if (nNavigationPosition >= maList.size())
|
|
{
|
|
OSL_ASSERT(nNavigationPosition < maList.size());
|
|
}
|
|
else
|
|
return maList[nNavigationPosition];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdrObjList::ClearObjectNavigationOrder()
|
|
{
|
|
mxNavigationOrder.reset();
|
|
mbIsNavigationOrderDirty = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SdrObjList::RecalcNavigationPositions()
|
|
{
|
|
if (mbIsNavigationOrderDirty)
|
|
{
|
|
if (mxNavigationOrder.get() != NULL)
|
|
{
|
|
mbIsNavigationOrderDirty = false;
|
|
|
|
WeakSdrObjectContainerType::iterator iObject;
|
|
WeakSdrObjectContainerType::const_iterator iEnd (mxNavigationOrder->end());
|
|
sal_uInt32 nIndex (0);
|
|
for (iObject=mxNavigationOrder->begin(); iObject!=iEnd; ++iObject,++nIndex)
|
|
(*iObject)->SetNavigationPosition(nIndex);
|
|
}
|
|
}
|
|
|
|
return mxNavigationOrder.get() != NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdrObjList::SetNavigationOrder (const uno::Reference<container::XIndexAccess>& rxOrder)
|
|
{
|
|
if (rxOrder.is())
|
|
{
|
|
const sal_Int32 nCount = rxOrder->getCount();
|
|
if ((sal_uInt32)nCount != maList.size())
|
|
return;
|
|
|
|
if (mxNavigationOrder.get() == NULL)
|
|
mxNavigationOrder.reset(new WeakSdrObjectContainerType(nCount));
|
|
|
|
for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
|
|
{
|
|
uno::Reference<uno::XInterface> xShape (rxOrder->getByIndex(nIndex), uno::UNO_QUERY);
|
|
SdrObject* pObject = SdrObject::getSdrObjectFromXShape(xShape);
|
|
if (pObject == NULL)
|
|
break;
|
|
(*mxNavigationOrder)[nIndex] = pObject;
|
|
}
|
|
|
|
mbIsNavigationOrderDirty = true;
|
|
}
|
|
else
|
|
ClearObjectNavigationOrder();
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdrObjList::InsertObjectIntoContainer (
|
|
SdrObject& rObject,
|
|
const sal_uInt32 nInsertPosition)
|
|
{
|
|
OSL_ASSERT(nInsertPosition<=maList.size());
|
|
|
|
// Update the navigation positions.
|
|
if (HasObjectNavigationOrder())
|
|
{
|
|
// The new object does not have a user defined position so append it
|
|
// to the list.
|
|
rObject.SetNavigationPosition(mxNavigationOrder->size());
|
|
mxNavigationOrder->push_back(&rObject);
|
|
}
|
|
|
|
// Insert object into object list. Because the insert() method requires
|
|
// a valid iterator as insertion position, we have to use push_back() to
|
|
// insert at the end of the list.
|
|
if (nInsertPosition >= maList.size())
|
|
maList.push_back(&rObject);
|
|
else
|
|
maList.insert(maList.begin()+nInsertPosition, &rObject);
|
|
bObjOrdNumsDirty=true;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdrObjList::ReplaceObjectInContainer (
|
|
SdrObject& rNewObject,
|
|
const sal_uInt32 nObjectPosition)
|
|
{
|
|
if (nObjectPosition >= maList.size())
|
|
{
|
|
OSL_ASSERT(nObjectPosition<maList.size());
|
|
return;
|
|
}
|
|
|
|
// Update the navigation positions.
|
|
if (HasObjectNavigationOrder())
|
|
{
|
|
// A user defined position of the object that is to be replaced is
|
|
// not transferred to the new object so erase the former and append
|
|
// the later object from/to the navigation order.
|
|
OSL_ASSERT(nObjectPosition < maList.size());
|
|
SdrObjectWeakRef aReference (maList[nObjectPosition]);
|
|
WeakSdrObjectContainerType::iterator iObject (::std::find(
|
|
mxNavigationOrder->begin(),
|
|
mxNavigationOrder->end(),
|
|
aReference));
|
|
if (iObject != mxNavigationOrder->end())
|
|
mxNavigationOrder->erase(iObject);
|
|
|
|
mxNavigationOrder->push_back(&rNewObject);
|
|
|
|
mbIsNavigationOrderDirty = true;
|
|
}
|
|
|
|
maList[nObjectPosition] = &rNewObject;
|
|
bObjOrdNumsDirty=true;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SdrObjList::RemoveObjectFromContainer (
|
|
const sal_uInt32 nObjectPosition)
|
|
{
|
|
if (nObjectPosition >= maList.size())
|
|
{
|
|
OSL_ASSERT(nObjectPosition<maList.size());
|
|
return;
|
|
}
|
|
|
|
// Update the navigation positions.
|
|
if (HasObjectNavigationOrder())
|
|
{
|
|
SdrObjectWeakRef aReference (maList[nObjectPosition]);
|
|
WeakSdrObjectContainerType::iterator iObject (::std::find(
|
|
mxNavigationOrder->begin(),
|
|
mxNavigationOrder->end(),
|
|
aReference));
|
|
if (iObject != mxNavigationOrder->end())
|
|
mxNavigationOrder->erase(iObject);
|
|
mbIsNavigationOrderDirty = true;
|
|
}
|
|
|
|
maList.erase(maList.begin()+nObjectPosition);
|
|
bObjOrdNumsDirty=true;
|
|
}
|
|
|
|
void SdrObjList::dumpAsXml(xmlTextWriterPtr pWriter) const
|
|
{
|
|
xmlTextWriterStartElement(pWriter, BAD_CAST("sdrObjList"));
|
|
xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
|
|
xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
|
|
|
|
size_t nObjCount = GetObjCount();
|
|
for (size_t i = 0; i < nObjCount; ++i)
|
|
{
|
|
if (const SdrObject* pObject = GetObj(i))
|
|
pObject->dumpAsXml(pWriter);
|
|
}
|
|
|
|
xmlTextWriterEndElement(pWriter);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SdrPageGridFrameList::Clear()
|
|
{
|
|
sal_uInt16 nCount=GetCount();
|
|
for (sal_uInt16 i=0; i<nCount; i++) {
|
|
delete GetObject(i);
|
|
}
|
|
aList.clear();
|
|
}
|
|
|
|
|
|
// PageUser section
|
|
|
|
void SdrPage::AddPageUser(sdr::PageUser& rNewUser)
|
|
{
|
|
maPageUsers.push_back(&rNewUser);
|
|
}
|
|
|
|
void SdrPage::RemovePageUser(sdr::PageUser& rOldUser)
|
|
{
|
|
const sdr::PageUserVector::iterator aFindResult = ::std::find(maPageUsers.begin(), maPageUsers.end(), &rOldUser);
|
|
if(aFindResult != maPageUsers.end())
|
|
{
|
|
maPageUsers.erase(aFindResult);
|
|
}
|
|
}
|
|
|
|
|
|
// DrawContact section
|
|
|
|
sdr::contact::ViewContact* SdrPage::CreateObjectSpecificViewContact()
|
|
{
|
|
return new sdr::contact::ViewContactOfSdrPage(*this);
|
|
}
|
|
|
|
sdr::contact::ViewContact& SdrPage::GetViewContact() const
|
|
{
|
|
if(!mpViewContact)
|
|
{
|
|
const_cast< SdrPage* >(this)->mpViewContact =
|
|
const_cast< SdrPage* >(this)->CreateObjectSpecificViewContact();
|
|
}
|
|
|
|
return *mpViewContact;
|
|
}
|
|
|
|
|
|
|
|
void SdrPageProperties::ImpRemoveStyleSheet()
|
|
{
|
|
if(mpStyleSheet)
|
|
{
|
|
EndListening(*mpStyleSheet);
|
|
mpProperties->SetParent(0);
|
|
mpStyleSheet = 0;
|
|
}
|
|
}
|
|
|
|
void SdrPageProperties::ImpAddStyleSheet(SfxStyleSheet& rNewStyleSheet)
|
|
{
|
|
if(mpStyleSheet != &rNewStyleSheet)
|
|
{
|
|
ImpRemoveStyleSheet();
|
|
mpStyleSheet = &rNewStyleSheet;
|
|
StartListening(rNewStyleSheet);
|
|
mpProperties->SetParent(&rNewStyleSheet.GetItemSet());
|
|
}
|
|
}
|
|
|
|
void ImpPageChange(SdrPage& rSdrPage)
|
|
{
|
|
rSdrPage.ActionChanged();
|
|
|
|
if(rSdrPage.GetModel())
|
|
{
|
|
rSdrPage.GetModel()->SetChanged(true);
|
|
SdrHint aHint(HINT_PAGEORDERCHG);
|
|
aHint.SetPage(&rSdrPage);
|
|
rSdrPage.GetModel()->Broadcast(aHint);
|
|
}
|
|
}
|
|
|
|
SdrPageProperties::SdrPageProperties(SdrPage& rSdrPage)
|
|
: SfxListener(),
|
|
mpSdrPage(&rSdrPage),
|
|
mpStyleSheet(0),
|
|
mpProperties(new SfxItemSet(mpSdrPage->GetModel()->GetItemPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST))
|
|
{
|
|
if(!rSdrPage.IsMasterPage())
|
|
{
|
|
mpProperties->Put(XFillStyleItem(drawing::FillStyle_NONE));
|
|
}
|
|
}
|
|
|
|
SdrPageProperties::~SdrPageProperties()
|
|
{
|
|
ImpRemoveStyleSheet();
|
|
delete mpProperties;
|
|
}
|
|
|
|
void SdrPageProperties::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
|
|
{
|
|
const SfxSimpleHint* pSimpleHint = dynamic_cast< const SfxSimpleHint* >(&rHint);
|
|
|
|
if(pSimpleHint)
|
|
{
|
|
switch(pSimpleHint->GetId())
|
|
{
|
|
case SFX_HINT_DATACHANGED :
|
|
{
|
|
// notify change, broadcast
|
|
ImpPageChange(*mpSdrPage);
|
|
break;
|
|
}
|
|
case SFX_HINT_DYING :
|
|
{
|
|
// Style needs to be forgotten
|
|
ImpRemoveStyleSheet();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SdrPageProperties::isUsedByModel() const
|
|
{
|
|
assert(mpSdrPage);
|
|
return mpSdrPage->IsInserted();
|
|
}
|
|
|
|
|
|
void SdrPageProperties::PutItemSet(const SfxItemSet& rSet)
|
|
{
|
|
OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
|
|
mpProperties->Put(rSet);
|
|
ImpPageChange(*mpSdrPage);
|
|
}
|
|
|
|
void SdrPageProperties::PutItem(const SfxPoolItem& rItem)
|
|
{
|
|
OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
|
|
mpProperties->Put(rItem);
|
|
ImpPageChange(*mpSdrPage);
|
|
}
|
|
|
|
void SdrPageProperties::ClearItem(const sal_uInt16 nWhich)
|
|
{
|
|
mpProperties->ClearItem(nWhich);
|
|
ImpPageChange(*mpSdrPage);
|
|
}
|
|
|
|
void SdrPageProperties::SetStyleSheet(SfxStyleSheet* pStyleSheet)
|
|
{
|
|
if(pStyleSheet)
|
|
{
|
|
ImpAddStyleSheet(*pStyleSheet);
|
|
}
|
|
else
|
|
{
|
|
ImpRemoveStyleSheet();
|
|
}
|
|
|
|
ImpPageChange(*mpSdrPage);
|
|
}
|
|
|
|
|
|
|
|
|
|
TYPEINIT1(SdrPage,SdrObjList);
|
|
SdrPage::SdrPage(SdrModel& rNewModel, bool bMasterPage)
|
|
: SdrObjList(&rNewModel, this),
|
|
mpViewContact(0L),
|
|
nWdt(10L),
|
|
nHgt(10L),
|
|
nBordLft(0L),
|
|
nBordUpp(0L),
|
|
nBordRgt(0L),
|
|
nBordLwr(0L),
|
|
pLayerAdmin(new SdrLayerAdmin(&rNewModel.GetLayerAdmin())),
|
|
mpSdrPageProperties(0),
|
|
mpMasterPageDescriptor(0L),
|
|
nPageNum(0L),
|
|
mbMaster(bMasterPage),
|
|
mbInserted(false),
|
|
mbObjectsNotPersistent(false),
|
|
mbPageBorderOnlyLeftRight(false)
|
|
{
|
|
aPrefVisiLayers.SetAll();
|
|
eListKind = (bMasterPage) ? SDROBJLIST_MASTERPAGE : SDROBJLIST_DRAWPAGE;
|
|
|
|
mpSdrPageProperties = new SdrPageProperties(*this);
|
|
}
|
|
|
|
SdrPage::SdrPage(const SdrPage& rSrcPage)
|
|
: SdrObjList(rSrcPage.pModel, this),
|
|
tools::WeakBase< SdrPage >(),
|
|
mpViewContact(0L),
|
|
nWdt(rSrcPage.nWdt),
|
|
nHgt(rSrcPage.nHgt),
|
|
nBordLft(rSrcPage.nBordLft),
|
|
nBordUpp(rSrcPage.nBordUpp),
|
|
nBordRgt(rSrcPage.nBordRgt),
|
|
nBordLwr(rSrcPage.nBordLwr),
|
|
pLayerAdmin(new SdrLayerAdmin(rSrcPage.pModel->GetLayerAdmin())),
|
|
mpSdrPageProperties(0),
|
|
mpMasterPageDescriptor(0L),
|
|
nPageNum(rSrcPage.nPageNum),
|
|
mbMaster(rSrcPage.mbMaster),
|
|
mbInserted(false),
|
|
mbObjectsNotPersistent(rSrcPage.mbObjectsNotPersistent),
|
|
mbPageBorderOnlyLeftRight(rSrcPage.mbPageBorderOnlyLeftRight)
|
|
{
|
|
aPrefVisiLayers.SetAll();
|
|
}
|
|
|
|
SdrPage::~SdrPage()
|
|
{
|
|
if( mxUnoPage.is() ) try
|
|
{
|
|
uno::Reference< lang::XComponent > xPageComponent( mxUnoPage, uno::UNO_QUERY_THROW );
|
|
mxUnoPage.clear();
|
|
xPageComponent->dispose();
|
|
}
|
|
catch( const uno::Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
|
|
// tell all the registered PageUsers that the page is in destruction
|
|
// This causes some (all?) PageUsers to remove themselves from the list
|
|
// of page users. Therefore we have to use a copy of the list for the
|
|
// iteration.
|
|
sdr::PageUserVector aListCopy (maPageUsers.begin(), maPageUsers.end());
|
|
for(sdr::PageUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); ++aIterator)
|
|
{
|
|
sdr::PageUser* pPageUser = *aIterator;
|
|
DBG_ASSERT(pPageUser, "SdrPage::~SdrPage: corrupt PageUser list (!)");
|
|
pPageUser->PageInDestruction(*this);
|
|
}
|
|
|
|
// Clear the vector. This means that user do not need to call RemovePageUser()
|
|
// when they get called from PageInDestruction().
|
|
maPageUsers.clear();
|
|
|
|
delete pLayerAdmin;
|
|
|
|
TRG_ClearMasterPage();
|
|
|
|
if(mpViewContact)
|
|
{
|
|
delete mpViewContact;
|
|
mpViewContact = 0L;
|
|
}
|
|
|
|
{
|
|
delete mpSdrPageProperties;
|
|
mpSdrPageProperties = 0;
|
|
}
|
|
|
|
}
|
|
|
|
void SdrPage::lateInit(const SdrPage& rSrcPage, SdrModel* const pNewModel)
|
|
{
|
|
assert(!mpViewContact);
|
|
assert(!mpSdrPageProperties);
|
|
assert(!mxUnoPage.is());
|
|
|
|
if (pNewModel && (pNewModel != pModel))
|
|
{
|
|
pModel = pNewModel;
|
|
impl_setModelForLayerAdmin(pNewModel);
|
|
}
|
|
|
|
// copy all the local parameters to make this instance
|
|
// a valid copy of source page before copying and inserting
|
|
// the contained objects
|
|
mbMaster = rSrcPage.mbMaster;
|
|
mbPageBorderOnlyLeftRight = rSrcPage.mbPageBorderOnlyLeftRight;
|
|
aPrefVisiLayers = rSrcPage.aPrefVisiLayers;
|
|
nWdt = rSrcPage.nWdt;
|
|
nHgt = rSrcPage.nHgt;
|
|
nBordLft = rSrcPage.nBordLft;
|
|
nBordUpp = rSrcPage.nBordUpp;
|
|
nBordRgt = rSrcPage.nBordRgt;
|
|
nBordLwr = rSrcPage.nBordLwr;
|
|
nPageNum = rSrcPage.nPageNum;
|
|
|
|
if(rSrcPage.TRG_HasMasterPage())
|
|
{
|
|
TRG_SetMasterPage(rSrcPage.TRG_GetMasterPage());
|
|
TRG_SetMasterPageVisibleLayers(rSrcPage.TRG_GetMasterPageVisibleLayers());
|
|
}
|
|
else
|
|
{
|
|
TRG_ClearMasterPage();
|
|
}
|
|
|
|
mbObjectsNotPersistent = rSrcPage.mbObjectsNotPersistent;
|
|
|
|
{
|
|
mpSdrPageProperties = new SdrPageProperties(*this);
|
|
|
|
if(!IsMasterPage())
|
|
{
|
|
mpSdrPageProperties->PutItemSet(rSrcPage.getSdrPageProperties().GetItemSet());
|
|
}
|
|
|
|
mpSdrPageProperties->SetStyleSheet(rSrcPage.getSdrPageProperties().GetStyleSheet());
|
|
}
|
|
|
|
// Now copy the contained objects
|
|
SdrObjList::lateInit(rSrcPage);
|
|
|
|
// be careful and correct eListKind, a member of SdrObjList which
|
|
// will be changed by the SdrObjList::lateInit before...
|
|
eListKind = (mbMaster) ? SDROBJLIST_MASTERPAGE : SDROBJLIST_DRAWPAGE;
|
|
}
|
|
|
|
SdrPage* SdrPage::Clone() const
|
|
{
|
|
return Clone(NULL);
|
|
}
|
|
|
|
SdrPage* SdrPage::Clone(SdrModel* pNewModel) const
|
|
{
|
|
if (pNewModel==NULL) pNewModel=pModel;
|
|
SdrPage* pPage2=new SdrPage(*pNewModel);
|
|
pPage2->lateInit(*this);
|
|
return pPage2;
|
|
}
|
|
|
|
void SdrPage::SetSize(const Size& aSiz)
|
|
{
|
|
bool bChanged(false);
|
|
|
|
if(aSiz.Width() != nWdt)
|
|
{
|
|
nWdt = aSiz.Width();
|
|
bChanged = true;
|
|
}
|
|
|
|
if(aSiz.Height() != nHgt)
|
|
{
|
|
nHgt = aSiz.Height();
|
|
bChanged = true;
|
|
}
|
|
|
|
if(bChanged)
|
|
{
|
|
SetChanged();
|
|
}
|
|
}
|
|
|
|
Size SdrPage::GetSize() const
|
|
{
|
|
return Size(nWdt,nHgt);
|
|
}
|
|
|
|
sal_Int32 SdrPage::GetWdt() const
|
|
{
|
|
return nWdt;
|
|
}
|
|
|
|
void SdrPage::SetOrientation(Orientation eOri)
|
|
{
|
|
// square: handle like portrait format
|
|
Size aSiz(GetSize());
|
|
if (aSiz.Width()!=aSiz.Height()) {
|
|
if ((eOri==ORIENTATION_PORTRAIT) == (aSiz.Width()>aSiz.Height())) {
|
|
SetSize(Size(aSiz.Height(),aSiz.Width()));
|
|
}
|
|
}
|
|
}
|
|
|
|
Orientation SdrPage::GetOrientation() const
|
|
{
|
|
// square: handle like portrait format
|
|
Orientation eRet=ORIENTATION_PORTRAIT;
|
|
Size aSiz(GetSize());
|
|
if (aSiz.Width()>aSiz.Height()) eRet=ORIENTATION_LANDSCAPE;
|
|
return eRet;
|
|
}
|
|
|
|
sal_Int32 SdrPage::GetHgt() const
|
|
{
|
|
return nHgt;
|
|
}
|
|
|
|
void SdrPage::SetBorder(sal_Int32 nLft, sal_Int32 nUpp, sal_Int32 nRgt, sal_Int32 nLwr)
|
|
{
|
|
bool bChanged(false);
|
|
|
|
if(nBordLft != nLft)
|
|
{
|
|
nBordLft = nLft;
|
|
bChanged = true;
|
|
}
|
|
|
|
if(nBordUpp != nUpp)
|
|
{
|
|
nBordUpp = nUpp;
|
|
bChanged = true;
|
|
}
|
|
|
|
if(nBordRgt != nRgt)
|
|
{
|
|
nBordRgt = nRgt;
|
|
bChanged = true;
|
|
}
|
|
|
|
if(nBordLwr != nLwr)
|
|
{
|
|
nBordLwr = nLwr;
|
|
bChanged = true;
|
|
}
|
|
|
|
if(bChanged)
|
|
{
|
|
SetChanged();
|
|
}
|
|
}
|
|
|
|
void SdrPage::SetLftBorder(sal_Int32 nBorder)
|
|
{
|
|
if(nBordLft != nBorder)
|
|
{
|
|
nBordLft = nBorder;
|
|
SetChanged();
|
|
}
|
|
}
|
|
|
|
void SdrPage::SetUppBorder(sal_Int32 nBorder)
|
|
{
|
|
if(nBordUpp != nBorder)
|
|
{
|
|
nBordUpp = nBorder;
|
|
SetChanged();
|
|
}
|
|
}
|
|
|
|
void SdrPage::SetRgtBorder(sal_Int32 nBorder)
|
|
{
|
|
if(nBordRgt != nBorder)
|
|
{
|
|
nBordRgt=nBorder;
|
|
SetChanged();
|
|
}
|
|
}
|
|
|
|
void SdrPage::SetLwrBorder(sal_Int32 nBorder)
|
|
{
|
|
if(nBordLwr != nBorder)
|
|
{
|
|
nBordLwr=nBorder;
|
|
SetChanged();
|
|
}
|
|
}
|
|
|
|
sal_Int32 SdrPage::GetLftBorder() const
|
|
{
|
|
return nBordLft;
|
|
}
|
|
|
|
sal_Int32 SdrPage::GetUppBorder() const
|
|
{
|
|
return nBordUpp;
|
|
}
|
|
|
|
sal_Int32 SdrPage::GetRgtBorder() const
|
|
{
|
|
return nBordRgt;
|
|
}
|
|
|
|
sal_Int32 SdrPage::GetLwrBorder() const
|
|
{
|
|
return nBordLwr;
|
|
}
|
|
|
|
void SdrPage::impl_setModelForLayerAdmin(SdrModel* const pNewModel)
|
|
{
|
|
if (pNewModel!=NULL) {
|
|
pLayerAdmin->SetParent(&pNewModel->GetLayerAdmin());
|
|
} else {
|
|
pLayerAdmin->SetParent(NULL);
|
|
}
|
|
pLayerAdmin->SetModel(pNewModel);
|
|
}
|
|
|
|
void SdrPage::SetModel(SdrModel* pNewModel)
|
|
{
|
|
SdrModel* pOldModel=pModel;
|
|
SdrObjList::SetModel(pNewModel);
|
|
|
|
if (pNewModel!=pOldModel)
|
|
{
|
|
impl_setModelForLayerAdmin( pNewModel );
|
|
|
|
// create new SdrPageProperties with new model (due to SfxItemSet there)
|
|
// and copy ItemSet and StyleSheet
|
|
SdrPageProperties *pNew = new SdrPageProperties(*this);
|
|
|
|
if(!IsMasterPage())
|
|
{
|
|
pNew->PutItemSet(getSdrPageProperties().GetItemSet());
|
|
}
|
|
|
|
pNew->SetStyleSheet(getSdrPageProperties().GetStyleSheet());
|
|
|
|
delete mpSdrPageProperties;
|
|
mpSdrPageProperties = pNew;
|
|
}
|
|
|
|
// update listeners at possible API wrapper object
|
|
if( pOldModel != pNewModel )
|
|
{
|
|
if( mxUnoPage.is() )
|
|
{
|
|
SvxDrawPage* pPage2 = SvxDrawPage::getImplementation( mxUnoPage );
|
|
if( pPage2 )
|
|
pPage2->ChangeModel( pNewModel );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// #i68775# React on PageNum changes (from Model in most cases)
|
|
void SdrPage::SetPageNum(sal_uInt16 nNew)
|
|
{
|
|
if(nNew != nPageNum)
|
|
{
|
|
// change
|
|
nPageNum = nNew;
|
|
|
|
// notify visualisations, also notifies e.g. buffered MasterPages
|
|
ActionChanged();
|
|
}
|
|
}
|
|
|
|
sal_uInt16 SdrPage::GetPageNum() const
|
|
{
|
|
if (!mbInserted)
|
|
return 0;
|
|
|
|
if (mbMaster) {
|
|
if (pModel && pModel->IsMPgNumsDirty())
|
|
pModel->RecalcPageNums(true);
|
|
} else {
|
|
if (pModel && pModel->IsPagNumsDirty())
|
|
pModel->RecalcPageNums(false);
|
|
}
|
|
return nPageNum;
|
|
}
|
|
|
|
void SdrPage::SetChanged()
|
|
{
|
|
// For test purposes, use the new ViewContact for change
|
|
// notification now.
|
|
ActionChanged();
|
|
|
|
if( pModel )
|
|
{
|
|
pModel->SetChanged();
|
|
}
|
|
}
|
|
|
|
|
|
// MasterPage interface
|
|
|
|
void SdrPage::TRG_SetMasterPage(SdrPage& rNew)
|
|
{
|
|
if(mpMasterPageDescriptor && &(mpMasterPageDescriptor->GetUsedPage()) == &rNew)
|
|
return;
|
|
|
|
if(mpMasterPageDescriptor)
|
|
TRG_ClearMasterPage();
|
|
|
|
mpMasterPageDescriptor = new sdr::MasterPageDescriptor(*this, rNew);
|
|
GetViewContact().ActionChanged();
|
|
}
|
|
|
|
void SdrPage::TRG_ClearMasterPage()
|
|
{
|
|
if(mpMasterPageDescriptor)
|
|
{
|
|
SetChanged();
|
|
|
|
// the flushViewObjectContacts() will do needed invalidates by deleting the involved VOCs
|
|
mpMasterPageDescriptor->GetUsedPage().GetViewContact().flushViewObjectContacts(true);
|
|
|
|
delete mpMasterPageDescriptor;
|
|
mpMasterPageDescriptor = 0L;
|
|
}
|
|
}
|
|
|
|
SdrPage& SdrPage::TRG_GetMasterPage() const
|
|
{
|
|
DBG_ASSERT(mpMasterPageDescriptor != 0L, "TRG_GetMasterPage(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
|
|
return mpMasterPageDescriptor->GetUsedPage();
|
|
}
|
|
|
|
const SetOfByte& SdrPage::TRG_GetMasterPageVisibleLayers() const
|
|
{
|
|
DBG_ASSERT(mpMasterPageDescriptor != 0L, "TRG_GetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
|
|
return mpMasterPageDescriptor->GetVisibleLayers();
|
|
}
|
|
|
|
void SdrPage::TRG_SetMasterPageVisibleLayers(const SetOfByte& rNew)
|
|
{
|
|
DBG_ASSERT(mpMasterPageDescriptor != 0L, "TRG_SetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
|
|
mpMasterPageDescriptor->SetVisibleLayers(rNew);
|
|
}
|
|
|
|
sdr::contact::ViewContact& SdrPage::TRG_GetMasterPageDescriptorViewContact() const
|
|
{
|
|
DBG_ASSERT(mpMasterPageDescriptor != 0L, "TRG_GetMasterPageDescriptorViewContact(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
|
|
return mpMasterPageDescriptor->GetViewContact();
|
|
}
|
|
|
|
// used from SdrModel::RemoveMasterPage
|
|
void SdrPage::TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage)
|
|
{
|
|
if(TRG_HasMasterPage())
|
|
{
|
|
if(&TRG_GetMasterPage() == &rRemovedPage)
|
|
{
|
|
TRG_ClearMasterPage();
|
|
}
|
|
}
|
|
}
|
|
|
|
const SdrPageGridFrameList* SdrPage::GetGridFrameList(const SdrPageView* /*pPV*/, const Rectangle* /*pRect*/) const
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
OUString SdrPage::GetLayoutName() const
|
|
{
|
|
return OUString();
|
|
}
|
|
|
|
void SdrPage::SetInserted( bool bIns )
|
|
{
|
|
if( (bool) mbInserted != bIns )
|
|
{
|
|
mbInserted = bIns;
|
|
|
|
// #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
|
|
SdrObjListIter aIter(*this, IM_DEEPNOGROUPS);
|
|
|
|
while ( aIter.IsMore() )
|
|
{
|
|
SdrObject* pObj = aIter.Next();
|
|
if ( pObj->ISA(SdrOle2Obj) )
|
|
{
|
|
if( mbInserted )
|
|
static_cast<SdrOle2Obj*>(pObj)->Connect();
|
|
else
|
|
static_cast<SdrOle2Obj*>(pObj)->Disconnect();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrPage::SetUnoPage(uno::Reference<drawing::XDrawPage> const& xNewPage)
|
|
{
|
|
mxUnoPage = xNewPage;
|
|
}
|
|
|
|
uno::Reference< uno::XInterface > SdrPage::getUnoPage()
|
|
{
|
|
if( !mxUnoPage.is() )
|
|
{
|
|
// create one
|
|
mxUnoPage = createUnoPage();
|
|
}
|
|
|
|
return mxUnoPage;
|
|
}
|
|
|
|
uno::Reference< uno::XInterface > SdrPage::createUnoPage()
|
|
{
|
|
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xInt =
|
|
static_cast<cppu::OWeakObject*>( new SvxFmDrawPage( this ) );
|
|
return xInt;
|
|
}
|
|
|
|
SfxStyleSheet* SdrPage::GetTextStyleSheetForObject( SdrObject* pObj ) const
|
|
{
|
|
return pObj->GetStyleSheet();
|
|
}
|
|
|
|
/** returns an averaged background color of this page */
|
|
// #i75566# GetBackgroundColor -> GetPageBackgroundColor and bScreenDisplay hint value
|
|
Color SdrPage::GetPageBackgroundColor( SdrPageView* pView, bool bScreenDisplay ) const
|
|
{
|
|
Color aColor;
|
|
|
|
if(bScreenDisplay && (!pView || pView->GetApplicationDocumentColor() == COL_AUTO))
|
|
{
|
|
svtools::ColorConfig aColorConfig;
|
|
aColor = aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor;
|
|
}
|
|
else
|
|
{
|
|
aColor = pView->GetApplicationDocumentColor();
|
|
}
|
|
|
|
const SfxItemSet* pBackgroundFill = &getSdrPageProperties().GetItemSet();
|
|
|
|
if(!IsMasterPage() && TRG_HasMasterPage())
|
|
{
|
|
if(drawing::FillStyle_NONE == static_cast<const XFillStyleItem&>(pBackgroundFill->Get(XATTR_FILLSTYLE)).GetValue())
|
|
{
|
|
pBackgroundFill = &TRG_GetMasterPage().getSdrPageProperties().GetItemSet();
|
|
}
|
|
}
|
|
|
|
GetDraftFillColor(*pBackgroundFill, aColor);
|
|
|
|
return aColor;
|
|
}
|
|
|
|
/** *deprecated, use GetBackgroundColor with SdrPageView */
|
|
Color SdrPage::GetPageBackgroundColor() const
|
|
// #i75566# GetBackgroundColor -> GetPageBackgroundColor
|
|
{
|
|
return GetPageBackgroundColor( NULL, true );
|
|
}
|
|
|
|
/** this method returns true if the object from the ViewObjectContact should
|
|
be visible on this page while rendering.
|
|
bEdit selects if visibility test is for an editing view or a final render,
|
|
like printing.
|
|
*/
|
|
bool SdrPage::checkVisibility(
|
|
const sdr::contact::ViewObjectContact& /*rOriginal*/,
|
|
const sdr::contact::DisplayInfo& /*rDisplayInfo*/,
|
|
bool /*bEdit*/)
|
|
{
|
|
// this will be handled in the application if needed
|
|
return true;
|
|
}
|
|
|
|
// DrawContact support: Methods for handling Page changes
|
|
void SdrPage::ActionChanged() const
|
|
{
|
|
// Do necessary ViewContact actions
|
|
GetViewContact().ActionChanged();
|
|
|
|
// #i48535# also handle MasterPage change
|
|
if(TRG_HasMasterPage())
|
|
{
|
|
TRG_GetMasterPageDescriptorViewContact().ActionChanged();
|
|
}
|
|
}
|
|
|
|
// sdr::Comment interface
|
|
|
|
const SdrPageProperties* SdrPage::getCorrectSdrPageProperties() const
|
|
{
|
|
if(mpMasterPageDescriptor)
|
|
{
|
|
return mpMasterPageDescriptor->getCorrectSdrPageProperties();
|
|
}
|
|
else
|
|
{
|
|
return &getSdrPageProperties();
|
|
}
|
|
}
|
|
|
|
|
|
// use new redirector instead of pPaintProc
|
|
|
|
StandardCheckVisisbilityRedirector::StandardCheckVisisbilityRedirector()
|
|
: ViewObjectContactRedirector()
|
|
{
|
|
}
|
|
|
|
StandardCheckVisisbilityRedirector::~StandardCheckVisisbilityRedirector()
|
|
{
|
|
}
|
|
|
|
drawinglayer::primitive2d::Primitive2DSequence StandardCheckVisisbilityRedirector::createRedirectedPrimitive2DSequence(
|
|
const sdr::contact::ViewObjectContact& rOriginal,
|
|
const sdr::contact::DisplayInfo& rDisplayInfo)
|
|
{
|
|
SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject();
|
|
|
|
if(pObject)
|
|
{
|
|
if(pObject->GetPage())
|
|
{
|
|
if(pObject->GetPage()->checkVisibility(rOriginal, rDisplayInfo, false))
|
|
{
|
|
return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo);
|
|
}
|
|
}
|
|
|
|
return drawinglayer::primitive2d::Primitive2DSequence();
|
|
}
|
|
else
|
|
{
|
|
// not an object, maybe a page
|
|
return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo);
|
|
}
|
|
}
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|