blob: cbb5da1646dd8c8c428aee68391e6c5129e3b0be [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <svx/svdedtv.hxx>
#include <editeng/outliner.hxx>
#include <svx/svdundo.hxx>
#include <svx/svdogrp.hxx> // fuer's Gruppieren
#include <svx/svdovirt.hxx> // fuer VirtualObject-Bundling (Writer)
#include <svx/svdopath.hxx> // fuer CombineObjects
#include <svx/svdpage.hxx>
#include <svx/svdpagv.hxx>
#include "svx/svditer.hxx"
#include <svx/svdograf.hxx> // fuer Possibilities
#include <svx/svdoole2.hxx> // und Mtf-Import
#include "svx/svdstr.hrc" // Namen aus der Resource
#include "svx/svdglob.hxx" // StringCache
#include "svdfmtf.hxx"
#include <svx/svdetc.hxx>
#include <sfx2/basedlgs.hxx>
#include <vcl/msgbox.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/eeitem.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <svx/svxdlg.hxx> //CHINA001
#include <svx/dialogs.hrc> //CHINA001
// #i37011#
#include <svx/svdoashp.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// @@@@@ @@@@@ @@ @@@@@@ @@ @@ @@ @@@@@ @@ @@
// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@
// @@@@ @@ @@ @@ @@ @@@@@ @@ @@@@ @@@@@@@
// @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@
// @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@
// @@@@@ @@@@@ @@ @@ @ @@ @@@@@ @@ @@
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void SdrEditView::ImpBundleVirtObjOfMarkList()
{
// ... fehlende Implementation
}
SdrObject* SdrEditView::GetMaxToTopObj(SdrObject* /*pObj*/) const
{
return NULL;
}
SdrObject* SdrEditView::GetMaxToBtmObj(SdrObject* /*pObj*/) const
{
return NULL;
}
void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, sal_uIntPtr /*nOldPos*/, sal_uIntPtr /*nNewPos*/)
{
}
void SdrEditView::MovMarkedToTop()
{
sal_uIntPtr nAnz=GetMarkedObjectCount();
if (nAnz!=0)
{
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo(ImpGetResStr(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOTOP);
SortMarkedObjects();
sal_uIntPtr nm;
for (nm=0; nm<nAnz; nm++)
{ // Ordnums muessen alle stimmen!
GetMarkedObjectByIndex(nm)->GetOrdNum();
}
sal_Bool bChg=sal_False;
SdrObjList* pOL0=NULL;
sal_uIntPtr nNewPos=0;
for (nm=nAnz; nm>0;)
{
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj=pM->GetMarkedSdrObj();
SdrObjList* pOL=pObj->GetObjList();
if (pOL!=pOL0)
{
nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
pOL0=pOL;
}
sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
const Rectangle& rBR=pObj->GetCurrentBoundRect();
sal_uIntPtr nCmpPos=nNowPos+1;
SdrObject* pMaxObj=GetMaxToTopObj(pObj);
if (pMaxObj!=NULL)
{
sal_uIntPtr nMaxPos=pMaxObj->GetOrdNum();
if (nMaxPos!=0)
nMaxPos--;
if (nNewPos>nMaxPos)
nNewPos=nMaxPos; // diesen nicht ueberholen.
if (nNewPos<nNowPos)
nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
}
sal_Bool bEnd=sal_False;
while (nCmpPos<nNewPos && !bEnd)
{
SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
if (pCmpObj==NULL)
{
DBG_ERROR("MovMarkedToTop(): Vergleichsobjekt nicht gefunden");
bEnd=sal_True;
}
else if (pCmpObj==pMaxObj)
{
nNewPos=nCmpPos;
nNewPos--;
bEnd=sal_True;
}
else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
{
nNewPos=nCmpPos;
bEnd=sal_True;
}
else
{
nCmpPos++;
}
}
if (nNowPos!=nNewPos)
{
bChg=sal_True;
pOL->SetObjectOrdNum(nNowPos,nNewPos);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
ObjOrderChanged(pObj,nNowPos,nNewPos);
}
nNewPos--;
}
if( bUndo )
EndUndo();
if (bChg)
MarkListHasChanged();
}
}
void SdrEditView::MovMarkedToBtm()
{
sal_uIntPtr nAnz=GetMarkedObjectCount();
if (nAnz!=0)
{
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo(ImpGetResStr(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOBTM);
SortMarkedObjects();
sal_uIntPtr nm;
for (nm=0; nm<nAnz; nm++)
{ // Ordnums muessen alle stimmen!
GetMarkedObjectByIndex(nm)->GetOrdNum();
}
sal_Bool bChg=sal_False;
SdrObjList* pOL0=NULL;
sal_uIntPtr nNewPos=0;
for (nm=0; nm<nAnz; nm++)
{
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj=pM->GetMarkedSdrObj();
SdrObjList* pOL=pObj->GetObjList();
if (pOL!=pOL0)
{
nNewPos=0;
pOL0=pOL;
}
sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
const Rectangle& rBR=pObj->GetCurrentBoundRect();
sal_uIntPtr nCmpPos=nNowPos; if (nCmpPos>0) nCmpPos--;
SdrObject* pMaxObj=GetMaxToBtmObj(pObj);
if (pMaxObj!=NULL)
{
sal_uIntPtr nMinPos=pMaxObj->GetOrdNum()+1;
if (nNewPos<nMinPos)
nNewPos=nMinPos; // diesen nicht ueberholen.
if (nNewPos>nNowPos)
nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
}
sal_Bool bEnd=sal_False;
// nNewPos ist an dieser Stelle noch die maximale Position,
// an der das Obj hinruecken darf, ohne seinen Vorgaenger
// (Mehrfachselektion) zu ueberholen.
while (nCmpPos>nNewPos && !bEnd)
{
SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
if (pCmpObj==NULL)
{
DBG_ERROR("MovMarkedToBtm(): Vergleichsobjekt nicht gefunden");
bEnd=sal_True;
}
else if (pCmpObj==pMaxObj)
{
nNewPos=nCmpPos;
nNewPos++;
bEnd=sal_True;
}
else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
{
nNewPos=nCmpPos;
bEnd=sal_True;
}
else
{
nCmpPos--;
}
}
if (nNowPos!=nNewPos)
{
bChg=sal_True;
pOL->SetObjectOrdNum(nNowPos,nNewPos);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
ObjOrderChanged(pObj,nNowPos,nNewPos);
}
nNewPos++;
}
if(bUndo)
EndUndo();
if(bChg)
MarkListHasChanged();
}
}
void SdrEditView::PutMarkedToTop()
{
PutMarkedInFrontOfObj(NULL);
}
void SdrEditView::PutMarkedInFrontOfObj(const SdrObject* pRefObj)
{
sal_uIntPtr nAnz=GetMarkedObjectCount();
if (nAnz!=0)
{
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo(ImpGetResStr(STR_EditPutToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOTOP);
SortMarkedObjects();
if (pRefObj!=NULL)
{
// Damit "Vor das Objekt" auch funktioniert wenn die
// markierten Objekte bereits vor dem Objekt stehen
sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
SdrMark aRefMark;
if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
{
aRefMark=*GetSdrMarkByIndex(nRefMark);
GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
}
PutMarkedToBtm();
if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
{
GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
SortMarkedObjects();
}
}
sal_uIntPtr nm;
for (nm=0; nm<nAnz; nm++)
{ // Ordnums muessen alle stimmen!
GetMarkedObjectByIndex(nm)->GetOrdNum();
}
sal_Bool bChg=sal_False;
SdrObjList* pOL0=NULL;
sal_uIntPtr nNewPos=0;
for (nm=nAnz; nm>0;)
{
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj=pM->GetMarkedSdrObj();
if (pObj!=pRefObj)
{
SdrObjList* pOL=pObj->GetObjList();
if (pOL!=pOL0)
{
nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
pOL0=pOL;
}
sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
SdrObject* pMaxObj=GetMaxToTopObj(pObj);
if (pMaxObj!=NULL)
{
sal_uIntPtr nMaxOrd=pMaxObj->GetOrdNum(); // geht leider nicht anders
if (nMaxOrd>0)
nMaxOrd--;
if (nNewPos>nMaxOrd)
nNewPos=nMaxOrd; // nicht ueberholen.
if (nNewPos<nNowPos)
nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
}
if (pRefObj!=NULL)
{
if (pRefObj->GetObjList()==pObj->GetObjList())
{
sal_uIntPtr nMaxOrd=pRefObj->GetOrdNum(); // geht leider nicht anders
if (nNewPos>nMaxOrd)
nNewPos=nMaxOrd; // nicht ueberholen.
if (nNewPos<nNowPos)
nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
}
else
{
nNewPos=nNowPos; // andere PageView, also nicht veraendern
}
}
if (nNowPos!=nNewPos)
{
bChg=sal_True;
pOL->SetObjectOrdNum(nNowPos,nNewPos);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
ObjOrderChanged(pObj,nNowPos,nNewPos);
}
nNewPos--;
} // if (pObj!=pRefObj)
} // for-Schleife ueber alle Markierten Objekte
if( bUndo )
EndUndo();
if(bChg)
MarkListHasChanged();
}
}
void SdrEditView::PutMarkedToBtm()
{
PutMarkedBehindObj(NULL);
}
void SdrEditView::PutMarkedBehindObj(const SdrObject* pRefObj)
{
sal_uIntPtr nAnz=GetMarkedObjectCount();
if (nAnz!=0)
{
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo(ImpGetResStr(STR_EditPutToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOBTM);
SortMarkedObjects();
if (pRefObj!=NULL)
{
// Damit "Hinter das Objekt" auch funktioniert wenn die
// markierten Objekte bereits hinter dem Objekt stehen
sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
SdrMark aRefMark;
if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
{
aRefMark=*GetSdrMarkByIndex(nRefMark);
GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
}
PutMarkedToTop();
if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
{
GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
SortMarkedObjects();
}
}
sal_uIntPtr nm;
for (nm=0; nm<nAnz; nm++) { // Ordnums muessen alle stimmen!
GetMarkedObjectByIndex(nm)->GetOrdNum();
}
sal_Bool bChg=sal_False;
SdrObjList* pOL0=NULL;
sal_uIntPtr nNewPos=0;
for (nm=0; nm<nAnz; nm++) {
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj=pM->GetMarkedSdrObj();
if (pObj!=pRefObj) {
SdrObjList* pOL=pObj->GetObjList();
if (pOL!=pOL0) {
nNewPos=0;
pOL0=pOL;
}
sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
SdrObject* pMinObj=GetMaxToBtmObj(pObj);
if (pMinObj!=NULL) {
sal_uIntPtr nMinOrd=pMinObj->GetOrdNum()+1; // geht leider nicht anders
if (nNewPos<nMinOrd) nNewPos=nMinOrd; // nicht ueberholen.
if (nNewPos>nNowPos) nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
}
if (pRefObj!=NULL) {
if (pRefObj->GetObjList()==pObj->GetObjList()) {
sal_uIntPtr nMinOrd=pRefObj->GetOrdNum(); // geht leider nicht anders
if (nNewPos<nMinOrd) nNewPos=nMinOrd; // nicht ueberholen.
if (nNewPos>nNowPos) nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
} else {
nNewPos=nNowPos; // andere PageView, also nicht veraendern
}
}
if (nNowPos!=nNewPos) {
bChg=sal_True;
pOL->SetObjectOrdNum(nNowPos,nNewPos);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
ObjOrderChanged(pObj,nNowPos,nNewPos);
}
nNewPos++;
} // if (pObj!=pRefObj)
} // for-Schleife ueber alle markierten Objekte
if(bUndo)
EndUndo();
if(bChg)
MarkListHasChanged();
}
}
void SdrEditView::ReverseOrderOfMarked()
{
SortMarkedObjects();
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
if (nMarkAnz>0)
{
//sal_Bool bNeedBundle=sal_False;
sal_Bool bChg=sal_False;
bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo(ImpGetResStr(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_REVORDER);
sal_uIntPtr a=0;
do {
// Markierung ueber mehrere PageViews berueksichtigen
sal_uIntPtr b=a+1;
while (b<nMarkAnz && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) b++;
b--;
SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList();
sal_uIntPtr c=b;
if (a<c) { // Sicherstellen, dass die OrdNums nicht Dirty sind
GetMarkedObjectByIndex(a)->GetOrdNum();
}
while (a<c) {
SdrObject* pObj1=GetMarkedObjectByIndex(a);
SdrObject* pObj2=GetMarkedObjectByIndex(c);
sal_uIntPtr nOrd1=pObj1->GetOrdNumDirect();
sal_uIntPtr nOrd2=pObj2->GetOrdNumDirect();
if( bUndo )
{
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2));
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1));
}
pOL->SetObjectOrdNum(nOrd1,nOrd2);
// Obj 2 ist um eine Position nach vorn gerutscht, deshalb nun nOrd2-1
pOL->SetObjectOrdNum(nOrd2-1,nOrd1);
// Verwendung von Replace statt SetOrdNum wg. Performance (Neuberechnung der Ordnums)
a++; c--;
bChg=sal_True;
}
a=b+1;
} while (a<nMarkAnz);
if(bUndo)
EndUndo();
if(bChg)
MarkListHasChanged();
}
}
void SdrEditView::ImpCheckToTopBtmPossible()
{
sal_uIntPtr nAnz=GetMarkedObjectCount();
if (nAnz==0)
return;
if (nAnz==1)
{ // Sonderbehandlung fuer Einzelmarkierung
SdrObject* pObj=GetMarkedObjectByIndex(0);
SdrObjList* pOL=pObj->GetObjList();
sal_uIntPtr nMax=pOL->GetObjCount();
sal_uIntPtr nMin=0;
sal_uIntPtr nObjNum=pObj->GetOrdNum();
SdrObject* pRestrict=GetMaxToTopObj(pObj);
if (pRestrict!=NULL) {
sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
if (nRestrict<nMax) nMax=nRestrict;
}
pRestrict=GetMaxToBtmObj(pObj);
if (pRestrict!=NULL) {
sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
if (nRestrict>nMin) nMin=nRestrict;
}
bToTopPossible=nObjNum<sal_uIntPtr(nMax-1);
bToBtmPossible=nObjNum>nMin;
} else { // Mehrfachselektion
sal_uIntPtr nm=0;
SdrObjList* pOL0=NULL;
long nPos0=-1;
while (!bToBtmPossible && nm<nAnz) { // 'nach hinten' checken
SdrObject* pObj=GetMarkedObjectByIndex(nm);
SdrObjList* pOL=pObj->GetObjList();
if (pOL!=pOL0) {
nPos0=-1;
pOL0=pOL;
}
sal_uIntPtr nPos=pObj->GetOrdNum();
bToBtmPossible=nPos>sal_uIntPtr(nPos0+1);
nPos0=long(nPos);
nm++;
}
nm=nAnz;
pOL0=NULL;
nPos0=0x7FFFFFFF;
while (!bToTopPossible && nm>0) { // 'nach vorn' checken
nm--;
SdrObject* pObj=GetMarkedObjectByIndex(nm);
SdrObjList* pOL=pObj->GetObjList();
if (pOL!=pOL0) {
nPos0=pOL->GetObjCount();
pOL0=pOL;
}
sal_uIntPtr nPos=pObj->GetOrdNum();
bToTopPossible=nPos+1<sal_uIntPtr(nPos0);
nPos0=nPos;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// @@@@ @@@@ @@ @@ @@@@@ @@ @@ @@ @@@@@
// @@ @@ @@ @@ @@@ @@@ @@ @@ @@ @@@ @@ @@
// @@ @@ @@ @@@@@@@ @@ @@ @@ @@@@@@ @@
// @@ @@ @@ @@@@@@@ @@@@@ @@ @@@@@@ @@@@
// @@ @@ @@ @@ @ @@ @@ @@ @@ @@ @@@ @@
// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
// @@@@ @@@@ @@ @@ @@@@@ @@ @@ @@ @@@@@
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const
{
if (pSource!=NULL) {
SdrObjList* pOL=pSource->GetSubList();
if (pOL!=NULL && !pSource->Is3DObj()) { // erstes Nichtgruppenobjekt aus der Gruppe holen
SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
pSource=aIter.Next();
}
}
if(pSource && pDest)
{
SfxItemSet aSet(pMod->GetItemPool(),
SDRATTR_START, SDRATTR_NOTPERSIST_FIRST-1,
SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END,
EE_ITEMS_START, EE_ITEMS_END,
0, 0); // #52757#, #52762#
aSet.Put(pSource->GetMergedItemSet());
pDest->ClearMergedItem();
pDest->SetMergedItemSet(aSet);
pDest->NbcSetLayer(pSource->GetLayer());
pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), sal_True);
}
}
sal_Bool SdrEditView::ImpCanConvertForCombine1(const SdrObject* pObj) const
{
// #69711 : new condition IsLine() to be able to combine simple Lines
sal_Bool bIsLine(sal_False);
const SdrPathObj* pPath = PTR_CAST(SdrPathObj,pObj);
if(pPath)
{
bIsLine = pPath->IsLine();
}
SdrObjTransformInfoRec aInfo;
pObj->TakeObjInfo(aInfo);
return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine);
}
sal_Bool SdrEditView::ImpCanConvertForCombine(const SdrObject* pObj) const
{
SdrObjList* pOL = pObj->GetSubList();
if(pOL && !pObj->Is3DObj())
{
SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
while(aIter.IsMore())
{
SdrObject* pObj1 = aIter.Next();
// Es muessen alle Member einer Gruppe konvertierbar sein
if(!ImpCanConvertForCombine1(pObj1))
{
return sal_False;
}
}
}
else
{
if(!ImpCanConvertForCombine1(pObj))
{
return sal_False;
}
}
return sal_True;
}
basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon1(const SdrObject* pObj, sal_Bool bCombine) const
{
basegfx::B2DPolyPolygon aRetval;
SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
if(bCombine && pPath && !pObj->GetOutlinerParaObject())
{
aRetval = pPath->GetPathPoly();
}
else
{
SdrObject* pConvObj = pObj->ConvertToPolyObj(bCombine, sal_False);
if(pConvObj)
{
SdrObjList* pOL = pConvObj->GetSubList();
if(pOL)
{
SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
while(aIter.IsMore())
{
SdrObject* pObj1 = aIter.Next();
pPath = PTR_CAST(SdrPathObj, pObj1);
if(pPath)
{
aRetval.append(pPath->GetPathPoly());
}
}
}
else
{
pPath = PTR_CAST(SdrPathObj, pConvObj);
if(pPath)
{
aRetval = pPath->GetPathPoly();
}
}
SdrObject::Free( pConvObj );
}
}
return aRetval;
}
basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon(const SdrObject* pObj, sal_Bool bCombine) const
{
SdrObjList* pOL = pObj->GetSubList();
if(pOL && !pObj->Is3DObj())
{
basegfx::B2DPolyPolygon aRetval;
SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
while(aIter.IsMore())
{
SdrObject* pObj1 = aIter.Next();
aRetval.append(ImpGetPolyPolygon1(pObj1, bCombine));
}
return aRetval;
}
else
{
return ImpGetPolyPolygon1(pObj, bCombine);
}
}
basegfx::B2DPolygon SdrEditView::ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon& rPolyPolygon) const
{
const sal_uInt32 nPolyCount(rPolyPolygon.count());
if(0L == nPolyCount)
{
return basegfx::B2DPolygon();
}
else if(1L == nPolyCount)
{
return rPolyPolygon.getB2DPolygon(0L);
}
else
{
basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0L));
for(sal_uInt32 a(1L); a < nPolyCount; a++)
{
basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
if(aRetval.count())
{
if(aCandidate.count())
{
const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0L));
const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1L));
const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0L));
const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1L));
const double fRACA(basegfx::B2DVector(aCA - aRA).getLength());
const double fRACB(basegfx::B2DVector(aCB - aRA).getLength());
const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength());
const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength());
const double fSmallestRA(fRACA < fRACB ? fRACA : fRACB);
const double fSmallestRB(fRBCA < fRBCB ? fRBCA : fRBCB);
if(fSmallestRA < fSmallestRB)
{
// flip result
aRetval.flip();
}
const double fSmallestCA(fRACA < fRBCA ? fRACA : fRBCA);
const double fSmallestCB(fRACB < fRBCB ? fRACB : fRBCB);
if(fSmallestCB < fSmallestCA)
{
// flip candidate
aCandidate.flip();
}
// append candidate to retval
aRetval.append(aCandidate);
}
}
else
{
aRetval = aCandidate;
}
}
return aRetval;
}
}
// for distribution dialog function
struct ImpDistributeEntry
{
SdrObject* mpObj;
sal_Int32 mnPos;
sal_Int32 mnLength;
};
DECLARE_LIST(ImpDistributeEntryList, ImpDistributeEntry*)
void SdrEditView::DistributeMarkedObjects()
{
sal_uInt32 nMark(GetMarkedObjectCount());
if(nMark > 2)
{
SfxItemSet aNewAttr(pMod->GetItemPool());
//CHINA001 SvxDistributeDialog* pDlg = new SvxDistributeDialog(NULL, aNewAttr);
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
if(pFact)
{
AbstractSvxDistributeDialog *pDlg = pFact->CreateSvxDistributeDialog(NULL, aNewAttr);
DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001
sal_uInt16 nResult = pDlg->Execute();
if(nResult == RET_OK)
{
SvxDistributeHorizontal eHor = pDlg->GetDistributeHor();
SvxDistributeVertical eVer = pDlg->GetDistributeVer();
ImpDistributeEntryList aEntryList;
sal_uInt32 a, nInsPos, nFullLength;
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo();
if(eHor != SvxDistributeHorizontalNone)
{
// build sorted entry list
nFullLength = 0L;
for(a=0;a<nMark;a++)
{
SdrMark* pMark = GetSdrMarkByIndex(a);
ImpDistributeEntry* pNew = new ImpDistributeEntry;
pNew->mpObj = pMark->GetMarkedSdrObj();
nInsPos = 0;
switch(eHor)
{
case SvxDistributeHorizontalLeft:
{
pNew->mnPos = pNew->mpObj->GetSnapRect().Left();
break;
}
case SvxDistributeHorizontalCenter:
{
pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
break;
}
case SvxDistributeHorizontalDistance:
{
pNew->mnLength = pNew->mpObj->GetSnapRect().GetWidth() + 1;
nFullLength += pNew->mnLength;
pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
break;
}
case SvxDistributeHorizontalRight:
{
pNew->mnPos = pNew->mpObj->GetSnapRect().Right();
break;
}
default: break;
}
while(nInsPos < aEntryList.Count() && aEntryList.GetObject(nInsPos)->mnPos < pNew->mnPos)
nInsPos++;
aEntryList.Insert(pNew, nInsPos);
}
if(eHor == SvxDistributeHorizontalDistance)
{
// calc room in-between
sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1;
double fStepWidth = ((double)nWidth - (double)nFullLength) / (double)(aEntryList.Count() - 1);
double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
fStepStart += fStepWidth + (double)((aEntryList.GetObject(0)->mnLength + aEntryList.GetObject(1)->mnLength) / 2);
// move entries 1..n-1
for(a=1;a<aEntryList.Count()-1;a++)
{
ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
ImpDistributeEntry* pNext = aEntryList.GetObject(a+1);
sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
pCurr->mpObj->Move(Size(nDelta, 0));
fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
}
}
else
{
// calc distances
sal_Int32 nWidth = aEntryList.GetObject(aEntryList.Count() - 1)->mnPos - aEntryList.GetObject(0)->mnPos;
double fStepWidth = (double)nWidth / (double)(aEntryList.Count() - 1);
double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
fStepStart += fStepWidth;
// move entries 1..n-1
for(a=1;a<aEntryList.Count()-1;a++)
{
ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
pCurr->mpObj->Move(Size(nDelta, 0));
fStepStart += fStepWidth;
}
}
// clear list
while(aEntryList.Count())
delete aEntryList.Remove((sal_uIntPtr)0L);
}
if(eVer != SvxDistributeVerticalNone)
{
// build sorted entry list
nFullLength = 0L;
for(a=0;a<nMark;a++)
{
SdrMark* pMark = GetSdrMarkByIndex(a);
ImpDistributeEntry* pNew = new ImpDistributeEntry;
pNew->mpObj = pMark->GetMarkedSdrObj();
nInsPos = 0;
switch(eVer)
{
case SvxDistributeVerticalTop:
{
pNew->mnPos = pNew->mpObj->GetSnapRect().Top();
break;
}
case SvxDistributeVerticalCenter:
{
pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
break;
}
case SvxDistributeVerticalDistance:
{
pNew->mnLength = pNew->mpObj->GetSnapRect().GetHeight() + 1;
nFullLength += pNew->mnLength;
pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
break;
}
case SvxDistributeVerticalBottom:
{
pNew->mnPos = pNew->mpObj->GetSnapRect().Bottom();
break;
}
default: break;
}
while(nInsPos < aEntryList.Count() && aEntryList.GetObject(nInsPos)->mnPos < pNew->mnPos)
nInsPos++;
aEntryList.Insert(pNew, nInsPos);
}
if(eVer == SvxDistributeVerticalDistance)
{
// calc room in-between
sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1;
double fStepWidth = ((double)nHeight - (double)nFullLength) / (double)(aEntryList.Count() - 1);
double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
fStepStart += fStepWidth + (double)((aEntryList.GetObject(0)->mnLength + aEntryList.GetObject(1)->mnLength) / 2);
// move entries 1..n-1
for(a=1;a<aEntryList.Count()-1;a++)
{
ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
ImpDistributeEntry* pNext = aEntryList.GetObject(a+1);
sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
pCurr->mpObj->Move(Size(0, nDelta));
fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
}
}
else
{
// calc distances
sal_Int32 nHeight = aEntryList.GetObject(aEntryList.Count() - 1)->mnPos - aEntryList.GetObject(0)->mnPos;
double fStepWidth = (double)nHeight / (double)(aEntryList.Count() - 1);
double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
fStepStart += fStepWidth;
// move entries 1..n-1
for(a=1;a<aEntryList.Count()-1;a++)
{
ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
pCurr->mpObj->Move(Size(0, nDelta));
fStepStart += fStepWidth;
}
}
// clear list
while(aEntryList.Count())
delete aEntryList.Remove((sal_uIntPtr)0L);
}
// UNDO-Comment and end of UNDO
SetUndoComment(ImpGetResStr(STR_DistributeMarkedObjects));
if( bUndo )
EndUndo();
}
delete(pDlg);
}
}
}
void SdrEditView::MergeMarkedObjects(SdrMergeMode eMode)
{
// #i73441# check content
if(AreObjectsMarked())
{
SdrMarkList aRemove;
SortMarkedObjects();
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo();
sal_uInt32 nInsPos=0xFFFFFFFF;
const SdrObject* pAttrObj = NULL;
basegfx::B2DPolyPolygon aMergePolyPolygonA;
basegfx::B2DPolyPolygon aMergePolyPolygonB;
SdrObjList* pInsOL = NULL;
SdrPageView* pInsPV = NULL;
sal_Bool bFirstObjectComplete(sal_False);
// make sure selected objects are contour objects
// since now basegfx::tools::adaptiveSubdivide() is used, it is no longer
// necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old
// mechanisms. In a next step the polygon clipper will even be able to clip curves...
// ConvertMarkedToPolyObj(sal_True);
ConvertMarkedToPathObj(sal_True);
OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)");
for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
{
SdrMark* pM = GetSdrMarkByIndex(a);
SdrObject* pObj = pM->GetMarkedSdrObj();
if(ImpCanConvertForCombine(pObj))
{
if(!pAttrObj)
pAttrObj = pObj;
nInsPos = pObj->GetOrdNum() + 1;
pInsPV = pM->GetPageView();
pInsOL = pObj->GetObjList();
// #i76891# use single iter from SJ here whcih works on SdrObjects and takes
// groups into account by itself
SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
while(aIter.IsMore())
{
SdrObject* pCandidate = aIter.Next();
SdrPathObj* pPathObj = PTR_CAST(SdrPathObj, pCandidate);
if(pPathObj)
{
basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly());
// #i76891# unfortunately ConvertMarkedToPathObj has converted all
// involved polygon data to curve segments, even if not necessary.
// It is better to try to reduce to more simple polygons.
aTmpPoly = basegfx::tools::simplifyCurveSegments(aTmpPoly);
// for each part polygon as preparation, remove self-intersections
// correct orientations and get rid of evtl. neutral polygons.
aTmpPoly = basegfx::tools::prepareForPolygonOperation(aTmpPoly);
if(!bFirstObjectComplete)
{
// #i111987# Also need to collect ORed source shape when more than
// a single polygon is involved
if(aMergePolyPolygonA.count())
{
aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly);
}
else
{
aMergePolyPolygonA = aTmpPoly;
}
}
else
{
if(aMergePolyPolygonB.count())
{
// to topologically correctly collect the 2nd polygon
// group it is necessary to OR the parts (each is seen as
// XOR-FillRule polygon and they are drawn over each-other)
aMergePolyPolygonB = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly);
}
else
{
aMergePolyPolygonB = aTmpPoly;
}
}
}
}
// was there something added to the first poly?
if(!bFirstObjectComplete && aMergePolyPolygonA.count())
{
bFirstObjectComplete = sal_True;
}
// move object to temporary delete list
aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView()));
}
}
switch(eMode)
{
case SDR_MERGE_MERGE:
{
// merge all contained parts (OR)
static bool bTestXOR(false);
if(bTestXOR)
{
aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
}
else
{
aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
}
break;
}
case SDR_MERGE_SUBSTRACT:
{
// Substract B from A
aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
break;
}
case SDR_MERGE_INTERSECT:
{
// AND B and A
aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
break;
}
}
// #i73441# check insert list before taking actions
if(pInsOL)
{
SdrPathObj* pPath = new SdrPathObj(OBJ_PATHFILL, aMergePolyPolygonA);
ImpCopyAttributes(pAttrObj, pPath);
SdrInsertReason aReason(SDRREASON_VIEWCALL, pAttrObj);
pInsOL->InsertObject(pPath, nInsPos, &aReason);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
MarkObj(pPath, pInsPV, sal_False, sal_True);
}
aRemove.ForceSort();
switch(eMode)
{
case SDR_MERGE_MERGE:
{
SetUndoComment(
ImpGetResStr(STR_EditMergeMergePoly),
aRemove.GetMarkDescription());
break;
}
case SDR_MERGE_SUBSTRACT:
{
SetUndoComment(
ImpGetResStr(STR_EditMergeSubstractPoly),
aRemove.GetMarkDescription());
break;
}
case SDR_MERGE_INTERSECT:
{
SetUndoComment(
ImpGetResStr(STR_EditMergeIntersectPoly),
aRemove.GetMarkDescription());
break;
}
}
DeleteMarkedList(aRemove);
if( bUndo )
EndUndo();
}
}
void SdrEditView::CombineMarkedObjects(sal_Bool bNoPolyPoly)
{
// #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
// create a 2nd Undo-action and Undo-Comment.
bool bUndo = IsUndoEnabled();
// Undo-String will be set later
if( bUndo )
BegUndo(String(), String(), bNoPolyPoly ? SDRREPFUNC_OBJ_COMBINE_ONEPOLY : SDRREPFUNC_OBJ_COMBINE_POLYPOLY);
// #105899# First, guarantee that all objects are converted to polyobjects,
// especially for SdrGrafObj with bitmap filling this is necessary to not
// loose the bitmap filling.
// #i12392#
// ConvertMarkedToPolyObj was too strong here, it will loose quality and
// information when curve objects are combined. This can be replaced by
// using ConvertMarkedToPathObj without changing the previous fix.
// #i21250#
// Instead of simply passing sal_True as LineToArea, use bNoPolyPoly as info
// if this command is a 'Combine' or a 'Connect' command. On Connect it's sal_True.
// To not concert line segments with a set line width to polygons in that case,
// use this info. Do not convert LineToArea on Connect commands.
// ConvertMarkedToPathObj(!bNoPolyPoly);
// #114310#
// This is used for Combine and Connect. In no case it is necessary to force
// the content to curve, but it is also not good to force to polygons. Thus,
// curve is the less information loosing one. Remember: This place is not
// used for merge.
// LineToArea is never necessary, both commands are able to take over the
// set line style and to display it correctly. Thus, i will use a
// ConvertMarkedToPathObj with a sal_False in any case. Only drawback is that
// simple polygons will be changed to curves, but with no information loss.
ConvertMarkedToPathObj(sal_False /* bLineToArea */);
// continue as before
basegfx::B2DPolyPolygon aPolyPolygon;
SdrObjList* pAktOL = 0L;
SdrMarkList aRemoveMerker;
SortMarkedObjects();
sal_uInt32 nInsPos(0xFFFFFFFF);
SdrObjList* pInsOL = 0L;
SdrPageView* pInsPV = 0L;
const sal_uInt32 nAnz(GetMarkedObjectCount());
const SdrObject* pAttrObj = 0L;
for(sal_uInt32 a(nAnz); a > 0L; )
{
a--;
SdrMark* pM = GetSdrMarkByIndex(a);
SdrObject* pObj = pM->GetMarkedSdrObj();
SdrObjList* pThisOL = pObj->GetObjList();
if(pAktOL != pThisOL)
{
pAktOL = pThisOL;
}
if(ImpCanConvertForCombine(pObj))
{
// Obj merken fuer Attribute kopieren
pAttrObj = pObj;
// unfortunately ConvertMarkedToPathObj has converted all
// involved polygon data to curve segments, even if not necessary.
// It is better to try to reduce to more simple polygons.
basegfx::B2DPolyPolygon aTmpPoly(basegfx::tools::simplifyCurveSegments(ImpGetPolyPolygon(pObj, sal_True)));
aPolyPolygon.insert(0L, aTmpPoly);
if(!pInsOL)
{
nInsPos = pObj->GetOrdNum() + 1L;
pInsPV = pM->GetPageView();
pInsOL = pObj->GetObjList();
}
aRemoveMerker.InsertEntry(SdrMark(pObj, pM->GetPageView()));
}
}
if(bNoPolyPoly)
{
basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon));
aPolyPolygon.clear();
aPolyPolygon.append(aCombinedPolygon);
}
const sal_uInt32 nPolyCount(aPolyPolygon.count());
if(nPolyCount)
{
SdrObjKind eKind = OBJ_PATHFILL;
if(nPolyCount > 1L)
{
aPolyPolygon.setClosed(true);
}
else
{
// auf Polyline Checken
const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0L));
const sal_uInt32 nPointCount(aPolygon.count());
if(nPointCount <= 2L)
{
eKind = OBJ_PATHLINE;
}
else
{
if(!aPolygon.isClosed())
{
const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0L));
const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1L));
const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength());
const double fJoinTolerance(10.0);
if(fDistance < fJoinTolerance)
{
aPolyPolygon.setClosed(true);
}
else
{
eKind = OBJ_PATHLINE;
}
}
}
}
SdrPathObj* pPath = new SdrPathObj(eKind,aPolyPolygon);
// Attribute des untersten Objekts
ImpCopyAttributes(pAttrObj, pPath);
// #100408# If LineStyle of pAttrObj is XLINE_NONE force to XLINE_SOLID to make visible.
const XLineStyle eLineStyle = ((const XLineStyleItem&)pAttrObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
const XFillStyle eFillStyle = ((const XFillStyleItem&)pAttrObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
// #110635#
// Take fill style/closed state of pAttrObj in account when deciding to change the line style
sal_Bool bIsClosedPathObj(pAttrObj->ISA(SdrPathObj) && ((SdrPathObj*)pAttrObj)->IsClosed());
if(XLINE_NONE == eLineStyle && (XFILL_NONE == eFillStyle || !bIsClosedPathObj))
{
pPath->SetMergedItem(XLineStyleItem(XLINE_SOLID));
}
SdrInsertReason aReason(SDRREASON_VIEWCALL,pAttrObj);
pInsOL->InsertObject(pPath,nInsPos,&aReason);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
// #111111#
// Here was a severe error: Without UnmarkAllObj, the new object was marked
// additionally to the two ones which are deleted below. As long as those are
// in the UNDO there is no problem, but as soon as they get deleted, the
// MarkList will contain deleted objects -> GPF.
UnmarkAllObj(pInsPV);
MarkObj(pPath, pInsPV, sal_False, sal_True);
}
// UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen
aRemoveMerker.ForceSort(); // wichtig fuer Remove (s.u.)
if( bUndo )
SetUndoComment(ImpGetResStr(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveMerker.GetMarkDescription());
// die tatsaechlich verwendeten Objekten aus der Liste entfernen
DeleteMarkedList(aRemoveMerker);
if( bUndo )
EndUndo();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// @@@@@ @@ @@@@ @@ @@ @@@@ @@ @@ @@@@@@ @@ @@@@@
// @@ @@ @@ @@ @@ @@@ @@@ @@ @@ @@@ @@ @@ @@ @@
// @@ @@ @@ @@ @@@@@@@ @@ @@ @@@@@@ @@ @@ @@
// @@ @@ @@ @@@@ @@@@@@@ @@@@@@ @@@@@@ @@ @@ @@@@
// @@ @@ @@ @@ @@ @ @@ @@ @@ @@ @@@ @@ @@ @@
// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
// @@@@@ @@ @@@@ @@ @@ @@ @@ @@ @@ @@ @@@@@ @@@@@
//
////////////////////////////////////////////////////////////////////////////////////////////////////
sal_Bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, sal_Bool bMakeLines) const
{
sal_Bool bCan(sal_False);
const sal_uInt32 nPolygonCount(rPpolyPolygon.count());
if(nPolygonCount >= 2L)
{
// #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon
bCan = sal_True;
}
else if(bMakeLines && 1L == nPolygonCount)
{
// #i69172# ..or with at least 2 edges (curves or lines)
const basegfx::B2DPolygon aPolygon(rPpolyPolygon.getB2DPolygon(0L));
const sal_uInt32 nPointCount(aPolygon.count());
if(nPointCount > 2L)
{
bCan = sal_True;
}
}
return bCan;
}
sal_Bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, sal_Bool bMakeLines) const
{
sal_Bool bOtherObjs(sal_False); // sal_True=andere Objekte ausser PathObj's vorhanden
sal_Bool bMin1PolyPoly(sal_False); // sal_True=mind. 1 PolyPolygon mit mehr als ein Polygon vorhanden
SdrObjList* pOL = pObj->GetSubList();
if(pOL)
{
// Aha, Gruppenobjekt. Also alle Member ansehen.
// Alle muessen PathObjs sein !
SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
while(aIter.IsMore() && !bOtherObjs)
{
const SdrObject* pObj1 = aIter.Next();
const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj1);
if(pPath)
{
if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines))
{
bMin1PolyPoly = sal_True;
}
SdrObjTransformInfoRec aInfo;
pObj1->TakeObjInfo(aInfo);
if(!aInfo.bCanConvToPath)
{
// Passiert z.B. im Falle Fontwork (Joe, 28-11-95)
bOtherObjs = sal_True;
}
}
else
{
bOtherObjs = sal_True;
}
}
}
else
{
const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
// #i37011#
if(pPath)
{
if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines))
{
bMin1PolyPoly = sal_True;
}
SdrObjTransformInfoRec aInfo;
pObj->TakeObjInfo(aInfo);
// #69711 : new condition IsLine() to be able to break simple Lines
if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine())
{
// Passiert z.B. im Falle Fontwork (Joe, 28-11-95)
bOtherObjs = sal_True;
}
}
else if(pCustomShape)
{
if(bMakeLines)
{
// allow break command
bMin1PolyPoly = sal_True;
}
}
else
{
bOtherObjs = sal_True;
}
}
return bMin1PolyPoly && !bOtherObjs;
}
void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, sal_uIntPtr& rPos, SdrPageView* pPV, sal_Bool bMakeLines)
{
const SdrPathObj* pSrcPath = PTR_CAST(SdrPathObj, pObj);
const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
const bool bUndo = IsUndoEnabled();
if(pSrcPath)
{
// #i74631# redesigned due to XpolyPolygon removal and explicit constructors
SdrObject* pLast = 0; // fuer die Zuweisung des OutlinerParaObject
const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly());
const sal_uInt32 nPolyCount(rPolyPolygon.count());
for(sal_uInt32 a(0); a < nPolyCount; a++)
{
const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a));
const sal_uInt32 nPointCount(rCandidate.count());
if(!bMakeLines || nPointCount < 2)
{
SdrPathObj* pPath = new SdrPathObj((SdrObjKind)pSrcPath->GetObjIdentifier(), basegfx::B2DPolyPolygon(rCandidate));
ImpCopyAttributes(pSrcPath, pPath);
pLast = pPath;
SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
rOL.InsertObject(pPath, rPos, &aReason);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
MarkObj(pPath, pPV, sal_False, sal_True);
rPos++;
}
else
{
const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
for(sal_uInt32 b(0); b < nLoopCount; b++)
{
SdrObjKind eKind(OBJ_PLIN);
basegfx::B2DPolygon aNewPolygon;
const sal_uInt32 nNextIndex((b + 1) % nPointCount);
aNewPolygon.append(rCandidate.getB2DPoint(b));
if(rCandidate.areControlPointsUsed())
{
aNewPolygon.appendBezierSegment(
rCandidate.getNextControlPoint(b),
rCandidate.getPrevControlPoint(nNextIndex),
rCandidate.getB2DPoint(nNextIndex));
eKind = OBJ_PATHLINE;
}
else
{
aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex));
}
SdrPathObj* pPath = new SdrPathObj(eKind, basegfx::B2DPolyPolygon(aNewPolygon));
ImpCopyAttributes(pSrcPath, pPath);
pLast = pPath;
SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
rOL.InsertObject(pPath, rPos, &aReason);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
MarkObj(pPath, pPV, sal_False, sal_True);
rPos++;
}
}
}
if(pLast && pSrcPath->GetOutlinerParaObject())
{
pLast->SetOutlinerParaObject(new OutlinerParaObject(*pSrcPath->GetOutlinerParaObject()));
}
}
else if(pCustomShape)
{
if(bMakeLines)
{
// break up custom shape
const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape();
if(pReplacement)
{
SdrObject* pCandidate = pReplacement->Clone();
DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)");
pCandidate->SetModel(pCustomShape->GetModel());
if(((SdrShadowItem&)pCustomShape->GetMergedItem(SDRATTR_SHADOW)).GetValue())
{
if(pReplacement->ISA(SdrObjGroup))
{
pCandidate->SetMergedItem(SdrShadowItem(sal_True));
}
}
SdrInsertReason aReason(SDRREASON_VIEWCALL, pCustomShape);
rOL.InsertObject(pCandidate, rPos, &aReason);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true));
MarkObj(pCandidate, pPV, sal_False, sal_True);
if(pCustomShape->HasText() && !pCustomShape->IsTextPath())
{
// #i37011# also create a text object and add at rPos + 1
SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject(
pCustomShape->GetObjInventor(), OBJ_TEXT, 0L, pCustomShape->GetModel());
// Copy text content
OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject();
if(pParaObj)
{
pTextObj->NbcSetOutlinerParaObject(new OutlinerParaObject(*pParaObj));
}
// copy all attributes
SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet());
// clear fill and line style
aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));
// get the text bounds and set at text object
Rectangle aTextBounds = pCustomShape->GetSnapRect();
if(pCustomShape->GetTextBounds(aTextBounds))
{
pTextObj->SetSnapRect(aTextBounds);
}
// if rotated, copy GeoStat, too.
const GeoStat& rSourceGeo = pCustomShape->GetGeoStat();
if(rSourceGeo.nDrehWink)
{
pTextObj->NbcRotate(
pCustomShape->GetSnapRect().Center(), rSourceGeo.nDrehWink,
rSourceGeo.nSin, rSourceGeo.nCos);
}
// set modified ItemSet at text object
pTextObj->SetMergedItemSet(aTargetItemSet);
// insert object
rOL.InsertObject(pTextObj, rPos + 1, &aReason);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true));
MarkObj(pTextObj, pPV, sal_False, sal_True);
}
}
}
}
}
void SdrEditView::DismantleMarkedObjects(sal_Bool bMakeLines)
{
//sal_uInt32 nCnt(0);
// Temporaere Marklist
SdrMarkList aRemoveMerker;
SortMarkedObjects();
const bool bUndo = IsUndoEnabled();
if( bUndo )
{
// Der Comment wird spaeter zusammengebaut
BegUndo(String(), String(),
bMakeLines ? SDRREPFUNC_OBJ_DISMANTLE_LINES : SDRREPFUNC_OBJ_DISMANTLE_POLYS);
}
sal_uIntPtr nm;
sal_uIntPtr nAnz=GetMarkedObjectCount();
SdrObjList* pOL0=NULL;
for (nm=nAnz; nm>0;) {
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj=pM->GetMarkedSdrObj();
SdrPageView* pPV=pM->GetPageView();
SdrObjList* pOL=pObj->GetObjList();
if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // sicherstellen, dass OrdNums stimmen!
if (ImpCanDismantle(pObj,bMakeLines)) {
aRemoveMerker.InsertEntry(SdrMark(pObj,pM->GetPageView()));
sal_uIntPtr nPos0=pObj->GetOrdNumDirect();
sal_uIntPtr nPos=nPos0+1;
SdrObjList* pSubList=pObj->GetSubList();
if (pSubList!=NULL && !pObj->Is3DObj()) {
SdrObjListIter aIter(*pSubList,IM_DEEPNOGROUPS);
while (aIter.IsMore()) {
const SdrObject* pObj1=aIter.Next();
ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines);
}
} else {
ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines);
}
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,sal_True));
pOL->RemoveObject(nPos0);
if( !bUndo )
SdrObject::Free(pObj);
}
}
if( bUndo )
{
// UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen
SetUndoComment(ImpGetResStr(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveMerker.GetMarkDescription());
// die tatsaechlich verwendeten Objekten aus der Liste entfernen
EndUndo();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// #### #### ### # # ####
// # # # # # # # # #
// # ## #### # # # # ####
// # # # # # # # # #
// #### # # ### ### #
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void SdrEditView::GroupMarked(const SdrObject* pUserGrp)
{
if (AreObjectsMarked())
{
SortMarkedObjects();
const bool bUndo = IsUndoEnabled();
if( bUndo )
{
BegUndo(ImpGetResStr(STR_EditGroup),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_GROUP);
const sal_uIntPtr nAnz = GetMarkedObjectCount();
for(sal_uIntPtr nm = nAnz; nm>0; )
{
// UndoActions fuer alle betroffenen Objekte anlegen
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj = pM->GetMarkedSdrObj();
std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) );
AddUndoActions( vConnectorUndoActions );
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj ));
}
}
SdrMarkList aNewMark;
SdrPageView* pPV = GetSdrPageView();
if(pPV)
{
SdrObjList* pAktLst=pPV->GetObjList();
SdrObjList* pSrcLst=pAktLst;
SdrObjList* pSrcLst0=pSrcLst;
SdrPage* pPage=pPV->GetPage();
// sicherstellen, dass die OrdNums stimmen
if (pSrcLst->IsObjOrdNumsDirty())
pSrcLst->RecalcObjOrdNums();
SdrObject* pGrp=NULL;
SdrObject* pRefObj=NULL; // Referenz fuer InsertReason (-> rumankern im Writer)
SdrObject* pRefObj1=NULL; // Referenz fuer InsertReason (-> rumankern im Writer)
SdrObjList* pDstLst=NULL;
// Falls alle markierten Objekte aus Fremden Obj-Listen
// kommen, kommt das Gruppenobjekt an das Ende der Liste.
sal_uIntPtr nInsPos=pSrcLst->GetObjCount();
sal_Bool bNeedInsPos=sal_True;
for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;)
{
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
if (pM->GetPageView()==pPV)
{
if (pGrp==NULL)
{
if (pUserGrp!=NULL)
pGrp=pUserGrp->Clone();
if (pGrp==NULL)
pGrp=new SdrObjGroup;
pDstLst=pGrp->GetSubList();
DBG_ASSERT(pDstLst!=NULL,"Angebliches Gruppenobjekt liefert keine Objektliste");
}
SdrObject* pObj=pM->GetMarkedSdrObj();
pSrcLst=pObj->GetObjList();
if (pSrcLst!=pSrcLst0)
{
if (pSrcLst->IsObjOrdNumsDirty())
pSrcLst->RecalcObjOrdNums();
}
sal_Bool bForeignList=pSrcLst!=pAktLst;
sal_Bool bGrouped=pSrcLst!=pPage;
if (!bForeignList && bNeedInsPos)
{
nInsPos=pObj->GetOrdNum(); // ua, damit sind alle ObjOrdNum der Page gesetzt
nInsPos++;
bNeedInsPos=sal_False;
}
pSrcLst->RemoveObject(pObj->GetOrdNumDirect());
if (!bForeignList)
nInsPos--; // InsertPos korregieren
SdrInsertReason aReason(SDRREASON_VIEWCALL);
pDstLst->InsertObject(pObj,0,&aReason);
GetMarkedObjectListWriteAccess().DeleteMark(nm);
if (pRefObj1==NULL)
pRefObj1=pObj; // Das oberste sichtbare Objekt
if (!bGrouped)
{
if (pRefObj==NULL)
pRefObj=pObj; // Das oberste sichtbare nicht gruppierte Objekt
}
pSrcLst0=pSrcLst;
}
}
if (pRefObj==NULL)
pRefObj=pRefObj1;
if (pGrp!=NULL)
{
aNewMark.InsertEntry(SdrMark(pGrp,pPV));
sal_uIntPtr nAnz=pDstLst->GetObjCount();
SdrInsertReason aReason(SDRREASON_VIEWCALL,pRefObj);
pAktLst->InsertObject(pGrp,nInsPos,&aReason);
if( bUndo )
{
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // Kein Recalc!
for (sal_uIntPtr no=0; no<nAnz; no++)
{
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no)));
}
}
}
}
GetMarkedObjectListWriteAccess().Merge(aNewMark);
MarkListHasChanged();
if( bUndo )
EndUndo();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// # # # # #### #### ### # # ####
// # # ## # # # # # # # # # #
// # # # # # # ## #### # # # # ####
// # # # ## # # # # # # # # #
// ### # # #### # # ### ### #
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void SdrEditView::UnGroupMarked()
{
SdrMarkList aNewMark;
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo(String(), String(), SDRREPFUNC_OBJ_UNGROUP);
sal_uIntPtr nCount=0;
XubString aName1;
XubString aName;
sal_Bool bNameOk=sal_False;
for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) {
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pGrp=pM->GetMarkedSdrObj();
SdrObjList* pSrcLst=pGrp->GetSubList();
if (pSrcLst!=NULL) {
nCount++;
if (nCount==1) {
pGrp->TakeObjNameSingul(aName); // Bezeichnung der Gruppe holen
pGrp->TakeObjNamePlural(aName1); // Bezeichnung der Gruppe holen
bNameOk=sal_True;
} else {
if (nCount==2) aName=aName1; // Pluralname setzen
if (bNameOk) {
XubString aStr;
pGrp->TakeObjNamePlural(aStr); // Bezeichnung der Gruppe holen
if(!aStr.Equals(aName))
bNameOk = sal_False;
}
}
sal_uIntPtr nDstCnt=pGrp->GetOrdNum();
SdrObjList* pDstLst=pM->GetPageView()->GetObjList();
// FIRST move contained objects to parent of group, so that
// the contained objects are NOT migrated to the UNDO-ItemPool
// when AddUndo(new SdrUndoDelObj(*pGrp)) is called.
sal_uIntPtr nAnz=pSrcLst->GetObjCount();
sal_uIntPtr no;
if( bUndo )
{
for (no=nAnz; no>0;)
{
no--;
SdrObject* pObj=pSrcLst->GetObj(no);
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj));
}
}
for (no=0; no<nAnz; no++)
{
SdrObject* pObj=pSrcLst->RemoveObject(0);
SdrInsertReason aReason(SDRREASON_VIEWCALL,pGrp);
pDstLst->InsertObject(pObj,nDstCnt,&aReason);
if( bUndo )
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true));
nDstCnt++;
// Kein SortCheck beim einfuegen in die MarkList, denn das
// wuerde wg. pObj->GetOrdNum() jedesmal ein RecalcOrdNums()
// provozieren:
aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),sal_False);
}
if( bUndo )
{
// Now it is safe to add the delete-UNDO which trigers the
// MigrateItemPool now only for itself, not for the subobjects.
// nDstCnt is right, because previous inserts move group
// object deeper and increase nDstCnt.
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp));
}
pDstLst->RemoveObject(nDstCnt);
if( !bUndo )
SdrObject::Free(pGrp);
GetMarkedObjectListWriteAccess().DeleteMark(nm);
}
}
if (nCount!=0)
{
if (!bNameOk)
aName=ImpGetResStr(STR_ObjNamePluralGRUP); // Oberbegriff Gruppenobjekte verwenden, wenn verschiedene Objekte.
SetUndoComment(ImpGetResStr(STR_EditUngroup),aName);
}
if( bUndo )
EndUndo();
if (nCount!=0)
{
GetMarkedObjectListWriteAccess().Merge(aNewMark,sal_True); // Durch das obige Einsortieren ist aNewMark genau verkehrtherum
MarkListHasChanged();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ### ### # # # # ##### #### ##### ##### ### #### ### # # #
// # # # # ## # # # # # # # # # # # # # # # # #
// # # # # # # # # #### #### # # # # #### # # # #
// # # # # # ## # # # # # # # # # # # # # #
// ### ### # # # ##### # # # # ### # ### #### #
//
////////////////////////////////////////////////////////////////////////////////////////////////////
SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, sal_Bool bPath, sal_Bool bLineToArea)
{
SdrObject* pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea);
if (pNewObj!=NULL)
{
SdrObjList* pOL=pObj->GetObjList();
DBG_ASSERT(pOL!=NULL,"ConvertTo: Obj liefert keine ObjList");
if (pOL!=NULL)
{
const bool bUndo = IsUndoEnabled();
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj));
pOL->ReplaceObject(pNewObj,pObj->GetOrdNum());
if( !bUndo )
SdrObject::Free(pObj);
}
}
return pNewObj;
}
void SdrEditView::ImpConvertTo(sal_Bool bPath, sal_Bool bLineToArea)
{
sal_Bool bMrkChg=sal_False;
sal_Bool bModChg=sal_False;
if (AreObjectsMarked()) {
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
sal_uInt16 nDscrID=0;
if(bLineToArea)
{
if(nMarkAnz == 1)
nDscrID = STR_EditConvToContour;
else
nDscrID = STR_EditConvToContours;
BegUndo(ImpGetResStr(nDscrID), GetDescriptionOfMarkedObjects());
}
else
{
if (bPath) {
if (nMarkAnz==1) nDscrID=STR_EditConvToCurve;
else nDscrID=STR_EditConvToCurves;
BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPATH);
} else {
if (nMarkAnz==1) nDscrID=STR_EditConvToPoly;
else nDscrID=STR_EditConvToPolys;
BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPOLY);
}
}
for (sal_uIntPtr nm=nMarkAnz; nm>0;) {
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj=pM->GetMarkedSdrObj();
SdrPageView* pPV=pM->GetPageView();
if (pObj->IsGroupObject() && !pObj->Is3DObj()) {
SdrObject* pGrp=pObj;
SdrObjListIter aIter(*pGrp,IM_DEEPNOGROUPS);
while (aIter.IsMore()) {
pObj=aIter.Next();
if (ImpConvertOneObj(pObj,bPath,bLineToArea)) bModChg=sal_True;
}
} else {
SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea);
if (pNewObj!=NULL) {
bModChg=sal_True;
bMrkChg=sal_True;
GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm);
}
}
}
EndUndo();
if (bMrkChg) AdjustMarkHdl();
if (bMrkChg) MarkListHasChanged();
}
}
void SdrEditView::ConvertMarkedToPathObj(sal_Bool bLineToArea)
{
ImpConvertTo(sal_True, bLineToArea);
}
void SdrEditView::ConvertMarkedToPolyObj(sal_Bool bLineToArea)
{
ImpConvertTo(sal_False, bLineToArea);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// # # ##### ##### ### ##### # # ##### # # # #### ### #### #####
// ## ## # # # # # # # # # ## ## # # # # # # #
// # # # #### # ##### ### # # #### ### # # # # #### # # #### #
// # # # # # # # # # # # # # # # # # # #
// # # ##### # # # # # #### ##### # # # # ### # # #
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo)
{
const bool bUndo = IsUndoEnabled();
if( bUndo )
BegUndo(String(), String(), SDRREPFUNC_OBJ_IMPORTMTF);
SortMarkedObjects();
SdrMarkList aForTheDescription;
SdrMarkList aNewMarked;
sal_uIntPtr nAnz=GetMarkedObjectCount();
for (sal_uIntPtr nm=nAnz; nm>0;)
{ // Undo Objekte fuer alle neuen Objekte erzeugen
// zwischen den Metafiles auf Abbruch testen
if( pProgrInfo != NULL )
{
pProgrInfo->SetNextObject();
if(!pProgrInfo->ReportActions(0))
break;
}
nm--;
SdrMark* pM=GetSdrMarkByIndex(nm);
SdrObject* pObj=pM->GetMarkedSdrObj();
SdrPageView* pPV=pM->GetPageView();
SdrObjList* pOL=pObj->GetObjList();
sal_uIntPtr nInsPos=pObj->GetOrdNum()+1;
SdrGrafObj* pGraf=PTR_CAST(SdrGrafObj,pObj);
SdrOle2Obj* pOle2=PTR_CAST(SdrOle2Obj,pObj);
sal_uIntPtr nInsAnz=0;
Rectangle aLogicRect;
if(pGraf && (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedSvg()))
{
GDIMetaFile aMetaFile;
if(pGraf->HasGDIMetaFile())
{
aMetaFile = pGraf->GetTransformedGraphic(SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile();
}
else if(pGraf->isEmbeddedSvg())
{
aMetaFile = pGraf->getMetafileFromEmbeddedSvg();
}
if(aMetaFile.GetActionCount())
{
aLogicRect = pGraf->GetLogicRect();
ImpSdrGDIMetaFileImport aFilter(*pMod, pObj->GetLayer(), aLogicRect);
nInsAnz = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
}
}
if ( pOle2!=NULL && pOle2->GetGraphic() )
{
aLogicRect = pOle2->GetLogicRect();
ImpSdrGDIMetaFileImport aFilter(*pMod, pObj->GetLayer(), aLogicRect);
nInsAnz = aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(), *pOL, nInsPos, pProgrInfo);
}
if (nInsAnz!=0)
{
// transformation
GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat());
sal_uIntPtr nObj=nInsPos;
if(aGeoStat.nShearWink)
{
aGeoStat.RecalcTan();
}
if(aGeoStat.nDrehWink)
{
aGeoStat.RecalcSinCos();
}
for (sal_uIntPtr i=0; i<nInsAnz; i++)
{
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj)));
// Neue MarkList pflegen
SdrObject* pCandidate = pOL->GetObj(nObj);
// apply original transformation
if(aGeoStat.nShearWink)
{
pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearWink, aGeoStat.nTan, false);
}
if(aGeoStat.nDrehWink)
{
pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
}
SdrMark aNewMark(pCandidate, pPV);
aNewMarked.InsertEntry(aNewMark);
nObj++;
}
aForTheDescription.InsertEntry(*pM);
if( bUndo )
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
// Objekt aus selektion loesen und loeschen
GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj));
pOL->RemoveObject(nInsPos-1);
if( !bUndo )
SdrObject::Free(pObj);
}
}
// MarkObj... fehlt... jetzt nicht mehr (AW)
if(aNewMarked.GetMarkCount())
{
// Neue Selektion bilden
for(sal_uIntPtr a(0); a < aNewMarked.GetMarkCount(); a++)
{
GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a));
}
SortMarkedObjects();
}
if( bUndo )
{
SetUndoComment(ImpGetResStr(STR_EditImportMtf),aForTheDescription.GetMarkDescription());
EndUndo();
}
}