diff options
Diffstat (limited to 'svx/source/svdraw')
77 files changed, 76853 insertions, 0 deletions
diff --git a/svx/source/svdraw/ActionDescriptionProvider.cxx b/svx/source/svdraw/ActionDescriptionProvider.cxx new file mode 100644 index 000000000000..acd60e27680b --- /dev/null +++ b/svx/source/svdraw/ActionDescriptionProvider.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include "ActionDescriptionProvider.hxx" +#include "svdglob.hxx" +#include "svdstr.hrc" + +::rtl::OUString ActionDescriptionProvider::createDescription( ActionType eActionType + , const ::rtl::OUString& rObjectName ) +{ + USHORT nResID=0; + switch( eActionType ) + { + case INSERT: + nResID=STR_UndoInsertObj; + break; + case DELETE: + nResID= STR_EditDelete; + break; + case CUT: + nResID= STR_ExchangeClpCut; + break; + case MOVE: + nResID= STR_EditMove; + break; + case RESIZE: + nResID= STR_EditResize; + break; + case ROTATE: + nResID= STR_EditRotate; + break; + case TRANSFORM: + nResID= STR_EditTransform; + break; + case FORMAT: + nResID= STR_EditSetAttributes; + break; + case MOVE_TOTOP: + nResID= STR_EditMovToTop; + break; + case MOVE_TOBOTTOM: + nResID= STR_EditMovToBtm; + break; + case POS_SIZE: + nResID = STR_EditPosSize; + break; + } + if(!nResID) + return rtl::OUString(); + + XubString aStr(ImpGetResStr(nResID)); + XubString aName(rObjectName); + aStr.SearchAndReplaceAscii("%1", aName); + return rtl::OUString(aStr); +} diff --git a/svx/source/svdraw/clonelist.cxx b/svx/source/svdraw/clonelist.cxx new file mode 100644 index 000000000000..bae8ca9c188c --- /dev/null +++ b/svx/source/svdraw/clonelist.cxx @@ -0,0 +1,134 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +// #i13033# +// New mechanism to hold a ist of all original and cloned objects for later +// re-creating the connections for contained connectors +#include <clonelist.hxx> +#include <svx/svdoedge.hxx> +#include <svx/scene3d.hxx> + +CloneList::CloneList() +{ +} + +CloneList::~CloneList() +{ +} + +void CloneList::AddPair(const SdrObject* pOriginal, SdrObject* pClone) +{ + maOriginalList.Insert((SdrObject*)pOriginal, LIST_APPEND); + maCloneList.Insert(pClone, LIST_APPEND); + + // look for subobjects, too. + sal_Bool bOriginalIsGroup(pOriginal->IsGroupObject()); + sal_Bool bCloneIsGroup(pClone->IsGroupObject()); + + if(bOriginalIsGroup && pOriginal->ISA(E3dObject) && !pOriginal->ISA(E3dScene)) + bOriginalIsGroup = sal_False; + + if(bCloneIsGroup && pClone->ISA(E3dObject) && !pClone->ISA(E3dScene)) + bCloneIsGroup = sal_False; + + if(bOriginalIsGroup && bCloneIsGroup) + { + const SdrObjList* pOriginalList = pOriginal->GetSubList(); + SdrObjList* pCloneList = pClone->GetSubList(); + + if(pOriginalList && pCloneList + && pOriginalList->GetObjCount() == pCloneList->GetObjCount()) + { + for(sal_uInt32 a(0); a < pOriginalList->GetObjCount(); a++) + { + // recursive call + AddPair(pOriginalList->GetObj(a), pCloneList->GetObj(a)); + } + } + } +} + +sal_uInt32 CloneList::Count() const +{ + return maOriginalList.Count(); +} + +const SdrObject* CloneList::GetOriginal(sal_uInt32 nIndex) const +{ + return (SdrObject*)maOriginalList.GetObject(nIndex); +} + +SdrObject* CloneList::GetClone(sal_uInt32 nIndex) const +{ + return (SdrObject*)maCloneList.GetObject(nIndex); +} + +void CloneList::CopyConnections() const +{ + for(sal_uInt32 a(0); a < maOriginalList.Count(); a++) + { + const SdrEdgeObj* pOriginalEdge = PTR_CAST(SdrEdgeObj, GetOriginal(a)); + SdrEdgeObj* pCloneEdge = PTR_CAST(SdrEdgeObj, GetClone(a)); + + if(pOriginalEdge && pCloneEdge) + { + SdrObject* pOriginalNode1 = pOriginalEdge->GetConnectedNode(sal_True); + SdrObject* pOriginalNode2 = pOriginalEdge->GetConnectedNode(sal_False); + + if(pOriginalNode1) + { + ULONG nPos(maOriginalList.GetPos(pOriginalNode1)); + + if(LIST_ENTRY_NOTFOUND != nPos) + { + if(pOriginalEdge->GetConnectedNode(sal_True) != GetClone(nPos)) + { + pCloneEdge->ConnectToNode(sal_True, GetClone(nPos)); + } + } + } + + if(pOriginalNode2) + { + ULONG nPos(maOriginalList.GetPos(pOriginalNode2)); + + if(LIST_ENTRY_NOTFOUND != nPos) + { + if(pOriginalEdge->GetConnectedNode(sal_False) != GetClone(nPos)) + { + pCloneEdge->ConnectToNode(sal_False, GetClone(nPos)); + } + } + } + } + } +} + +// eof diff --git a/svx/source/svdraw/gradtrns.cxx b/svx/source/svdraw/gradtrns.cxx new file mode 100644 index 000000000000..57f6270c4f91 --- /dev/null +++ b/svx/source/svdraw/gradtrns.cxx @@ -0,0 +1,538 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include "gradtrns.hxx" +#include <svx/svdobj.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <vcl/salbtype.hxx> // FRound + +////////////////////////////////////////////////////////////////////////////// + +void GradTransformer::GradToVec(GradTransGradient& rG, GradTransVector& rV, const SdrObject* pObj) +{ + // handle start color + rV.aCol1 = rG.aGradient.GetStartColor(); + if(100 != rG.aGradient.GetStartIntens()) + { + const double fFact((double)rG.aGradient.GetStartIntens() / 100.0); + rV.aCol1 = Color(rV.aCol1.getBColor() * fFact); + } + + // handle end color + rV.aCol2 = rG.aGradient.GetEndColor(); + if(100 != rG.aGradient.GetEndIntens()) + { + const double fFact((double)rG.aGradient.GetEndIntens() / 100.0); + rV.aCol2 = Color(rV.aCol2.getBColor() * fFact); + } + + // calc the basic positions + const Rectangle aObjectSnapRectangle(pObj->GetSnapRect()); + const basegfx::B2DRange aRange(aObjectSnapRectangle.Left(), aObjectSnapRectangle.Top(), aObjectSnapRectangle.Right(), aObjectSnapRectangle.Bottom()); + const basegfx::B2DPoint aCenter(aRange.getCenter()); + basegfx::B2DPoint aStartPos, aEndPos; + + switch(rG.aGradient.GetGradientStyle()) + { + case XGRAD_LINEAR : + { + aStartPos = basegfx::B2DPoint(aCenter.getX(), aRange.getMinY()); + aEndPos = basegfx::B2DPoint(aCenter.getX(), aRange.getMaximum().getY()); + + if(rG.aGradient.GetBorder()) + { + basegfx::B2DVector aFullVec(aStartPos - aEndPos); + const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0; + aFullVec.normalize(); + aStartPos = aEndPos + (aFullVec * fLen); + } + + if(rG.aGradient.GetAngle()) + { + const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0); + const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aCenter, -fAngle)); + + aStartPos *= aTransformation; + aEndPos *= aTransformation; + } + break; + } + case XGRAD_AXIAL : + { + aStartPos = aCenter; + aEndPos = basegfx::B2DPoint(aCenter.getX(), aRange.getMaximum().getY()); + + if(rG.aGradient.GetBorder()) + { + basegfx::B2DVector aFullVec(aEndPos - aStartPos); + const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0; + aFullVec.normalize(); + aEndPos = aStartPos + (aFullVec * fLen); + } + + if(rG.aGradient.GetAngle()) + { + const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0); + const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aCenter, -fAngle)); + + aStartPos *= aTransformation; + aEndPos *= aTransformation; + } + break; + } + case XGRAD_RADIAL : + case XGRAD_SQUARE : + { + aStartPos = basegfx::B2DPoint(aRange.getMinX(), aRange.getMaximum().getY()); + aEndPos = basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()); + + if(rG.aGradient.GetBorder()) + { + basegfx::B2DVector aFullVec(aStartPos - aEndPos); + const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0; + aFullVec.normalize(); + aStartPos = aEndPos + (aFullVec * fLen); + } + + if(rG.aGradient.GetAngle()) + { + const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0); + const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aEndPos, -fAngle)); + + aStartPos *= aTransformation; + aEndPos *= aTransformation; + } + + if(rG.aGradient.GetXOffset() || rG.aGradient.GetYOffset()) + { + basegfx::B2DPoint aOffset( + (aRange.getWidth() * rG.aGradient.GetXOffset()) / 100.0, + (aRange.getHeight() * rG.aGradient.GetYOffset()) / 100.0); + + aStartPos += aOffset; + aEndPos += aOffset; + } + + break; + } + case XGRAD_ELLIPTICAL : + case XGRAD_RECT : + { + aStartPos = basegfx::B2DPoint(aRange.getMinX(), aCenter.getY()); + aEndPos = basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY()); + + if(rG.aGradient.GetBorder()) + { + basegfx::B2DVector aFullVec(aStartPos - aEndPos); + const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0; + aFullVec.normalize(); + aStartPos = aEndPos + (aFullVec * fLen); + } + + if(rG.aGradient.GetAngle()) + { + const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0); + const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aEndPos, -fAngle)); + + aStartPos *= aTransformation; + aEndPos *= aTransformation; + } + + if(rG.aGradient.GetXOffset() || rG.aGradient.GetYOffset()) + { + basegfx::B2DPoint aOffset( + (aRange.getWidth() * rG.aGradient.GetXOffset()) / 100.0, + (aRange.getHeight() * rG.aGradient.GetYOffset()) / 100.0); + + aStartPos += aOffset; + aEndPos += aOffset; + } + + break; + } + } + + // set values for vector positions now + rV.maPositionA = aStartPos; + rV.maPositionB = aEndPos; +} + +////////////////////////////////////////////////////////////////////////////// + +void GradTransformer::VecToGrad(GradTransVector& rV, GradTransGradient& rG, GradTransGradient& rGOld, const SdrObject* pObj, + sal_Bool bMoveSingle, sal_Bool bMoveFirst) +{ + // fill old gradient to new gradient to have a base + rG = rGOld; + + // handle color changes + if(rV.aCol1 != rGOld.aGradient.GetStartColor()) + { + rG.aGradient.SetStartColor(rV.aCol1); + rG.aGradient.SetStartIntens(100); + } + if(rV.aCol2 != rGOld.aGradient.GetEndColor()) + { + rG.aGradient.SetEndColor(rV.aCol2); + rG.aGradient.SetEndIntens(100); + } + + // calc the basic positions + const Rectangle aObjectSnapRectangle(pObj->GetSnapRect()); + const basegfx::B2DRange aRange(aObjectSnapRectangle.Left(), aObjectSnapRectangle.Top(), aObjectSnapRectangle.Right(), aObjectSnapRectangle.Bottom()); + const basegfx::B2DPoint aCenter(aRange.getCenter()); + basegfx::B2DPoint aStartPos(rV.maPositionA); + basegfx::B2DPoint aEndPos(rV.maPositionB); + + switch(rG.aGradient.GetGradientStyle()) + { + case XGRAD_LINEAR : + { + if(!bMoveSingle || (bMoveSingle && !bMoveFirst)) + { + basegfx::B2DVector aFullVec(aEndPos - aStartPos); + + if(bMoveSingle) + { + aFullVec = aEndPos - aCenter; + } + + aFullVec.normalize(); + + double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX())); + fNewFullAngle /= F_PI180; + fNewFullAngle *= -10.0; + fNewFullAngle += 900.0; + + // clip + while(fNewFullAngle < 0.0) + { + fNewFullAngle += 3600.0; + } + + while(fNewFullAngle >= 3600.0) + { + fNewFullAngle -= 3600.0; + } + + // to int and set + sal_Int32 nNewAngle = FRound(fNewFullAngle); + + if(nNewAngle != rGOld.aGradient.GetAngle()) + { + rG.aGradient.SetAngle(nNewAngle); + } + } + + if(!bMoveSingle || (bMoveSingle && bMoveFirst)) + { + const basegfx::B2DVector aFullVec(aEndPos - aStartPos); + const basegfx::B2DPoint aBottomLeft(aRange.getMinX(), aRange.getMaximum().getY()); + const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY()); + const basegfx::B2DVector aOldVec(aBottomLeft - aTopLeft); + const double fFullLen(aFullVec.getLength()); + const double fOldLen(aOldVec.getLength()); + const double fNewBorder((fFullLen * 100.0) / fOldLen); + sal_Int32 nNewBorder(100L - FRound(fNewBorder)); + + // clip + if(nNewBorder < 0L) + { + nNewBorder = 0L; + } + + if(nNewBorder > 100L) + { + nNewBorder = 100L; + } + + // set + if(nNewBorder != rG.aGradient.GetBorder()) + { + rG.aGradient.SetBorder((sal_uInt16)nNewBorder); + } + } + + break; + } + case XGRAD_AXIAL : + { + if(!bMoveSingle || (bMoveSingle && !bMoveFirst)) + { + basegfx::B2DVector aFullVec(aEndPos - aCenter); + const basegfx::B2DVector aOldVec(basegfx::B2DPoint(aCenter.getX(), aRange.getMaximum().getY()) - aCenter); + const double fFullLen(aFullVec.getLength()); + const double fOldLen(aOldVec.getLength()); + const double fNewBorder((fFullLen * 100.0) / fOldLen); + sal_Int32 nNewBorder = 100 - FRound(fNewBorder); + + // clip + if(nNewBorder < 0L) + { + nNewBorder = 0L; + } + + if(nNewBorder > 100L) + { + nNewBorder = 100L; + } + + // set + if(nNewBorder != rG.aGradient.GetBorder()) + { + rG.aGradient.SetBorder((sal_uInt16)nNewBorder); + } + + aFullVec.normalize(); + double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX())); + fNewFullAngle /= F_PI180; + fNewFullAngle *= -10.0; + fNewFullAngle += 900.0; + + // clip + while(fNewFullAngle < 0.0) + { + fNewFullAngle += 3600.0; + } + + while(fNewFullAngle >= 3600.0) + { + fNewFullAngle -= 3600.0; + } + + // to int and set + const sal_Int32 nNewAngle(FRound(fNewFullAngle)); + + if(nNewAngle != rGOld.aGradient.GetAngle()) + { + rG.aGradient.SetAngle(nNewAngle); + } + } + + break; + } + case XGRAD_RADIAL : + case XGRAD_SQUARE : + { + if(!bMoveSingle || (bMoveSingle && !bMoveFirst)) + { + const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY()); + const basegfx::B2DPoint aOffset(aEndPos - aTopLeft); + sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / aRange.getWidth())); + sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / aRange.getHeight())); + + // clip + if(nNewXOffset < 0L) + { + nNewXOffset = 0L; + } + + if(nNewXOffset > 100L) + { + nNewXOffset = 100L; + } + + if(nNewYOffset < 0L) + { + nNewYOffset = 0L; + } + + if(nNewYOffset > 100L) + { + nNewYOffset = 100L; + } + + rG.aGradient.SetXOffset((sal_uInt16)nNewXOffset); + rG.aGradient.SetYOffset((sal_uInt16)nNewYOffset); + + aStartPos -= aOffset; + aEndPos -= aOffset; + } + + if(!bMoveSingle || (bMoveSingle && bMoveFirst)) + { + basegfx::B2DVector aFullVec(aStartPos - aEndPos); + const basegfx::B2DPoint aBottomLeft(aRange.getMinX(), aRange.getMaximum().getY()); + const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY()); + const basegfx::B2DVector aOldVec(aBottomLeft - aTopLeft); + const double fFullLen(aFullVec.getLength()); + const double fOldLen(aOldVec.getLength()); + const double fNewBorder((fFullLen * 100.0) / fOldLen); + sal_Int32 nNewBorder(100L - FRound(fNewBorder)); + + // clip + if(nNewBorder < 0L) + { + nNewBorder = 0L; + } + + if(nNewBorder > 100L) + { + nNewBorder = 100L; + } + + // set + if(nNewBorder != rG.aGradient.GetBorder()) + { + rG.aGradient.SetBorder((sal_uInt16)nNewBorder); + } + + // angle is not definitely necessary for these modes, but it makes + // controlling more fun for the user + aFullVec.normalize(); + double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX())); + fNewFullAngle /= F_PI180; + fNewFullAngle *= -10.0; + fNewFullAngle += 900.0; + + // clip + while(fNewFullAngle < 0.0) + { + fNewFullAngle += 3600.0; + } + + while(fNewFullAngle >= 3600.0) + { + fNewFullAngle -= 3600.0; + } + + // to int and set + const sal_Int32 nNewAngle(FRound(fNewFullAngle)); + + if(nNewAngle != rGOld.aGradient.GetAngle()) + { + rG.aGradient.SetAngle(nNewAngle); + } + } + + break; + } + case XGRAD_ELLIPTICAL : + case XGRAD_RECT : + { + if(!bMoveSingle || (bMoveSingle && !bMoveFirst)) + { + const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY()); + const basegfx::B2DPoint aOffset(aEndPos - aTopLeft); + sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / aRange.getWidth())); + sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / aRange.getHeight())); + + // clip + if(nNewXOffset < 0L) + { + nNewXOffset = 0L; + } + + if(nNewXOffset > 100L) + { + nNewXOffset = 100L; + } + + if(nNewYOffset < 0L) + { + nNewYOffset = 0L; + } + + if(nNewYOffset > 100L) + { + nNewYOffset = 100L; + } + + rG.aGradient.SetXOffset((sal_uInt16)nNewXOffset); + rG.aGradient.SetYOffset((sal_uInt16)nNewYOffset); + + aStartPos -= aOffset; + aEndPos -= aOffset; + } + + if(!bMoveSingle || (bMoveSingle && bMoveFirst)) + { + basegfx::B2DVector aFullVec(aStartPos - aEndPos); + const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY()); + const basegfx::B2DPoint aCenterLeft(aRange.getMinX(), aRange.getHeight()); + const basegfx::B2DVector aOldVec(aCenterLeft - aTopLeft); + const double fFullLen(aFullVec.getLength()); + const double fOldLen(aOldVec.getLength()); + const double fNewBorder((fFullLen * 100.0) / fOldLen); + sal_Int32 nNewBorder(100L - FRound(fNewBorder)); + + // clip + if(nNewBorder < 0L) + { + nNewBorder = 0L; + } + + if(nNewBorder > 100L) + { + nNewBorder = 100L; + } + + // set + if(nNewBorder != rG.aGradient.GetBorder()) + { + rG.aGradient.SetBorder((sal_uInt16)nNewBorder); + } + + // angle is not definitely necessary for these modes, but it makes + // controlling more fun for the user + aFullVec.normalize(); + double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX())); + fNewFullAngle /= F_PI180; + fNewFullAngle *= -10.0; + fNewFullAngle += 900.0; + + // clip + while(fNewFullAngle < 0.0) + { + fNewFullAngle += 3600.0; + } + + while(fNewFullAngle >= 3600.0) + { + fNewFullAngle -= 3600.0; + } + + // to int and set + const sal_Int32 nNewAngle(FRound(fNewFullAngle)); + + if(nNewAngle != rGOld.aGradient.GetAngle()) + { + rG.aGradient.SetAngle(nNewAngle); + } + } + + break; + } + } +} + +// eof diff --git a/svx/source/svdraw/gradtrns.hxx b/svx/source/svdraw/gradtrns.hxx new file mode 100644 index 000000000000..bf5352632f40 --- /dev/null +++ b/svx/source/svdraw/gradtrns.hxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _GRADTRANS_HXX +#define _GRADTRANS_HXX + +#include <svx/xgrad.hxx> +#include <tools/gen.hxx> +#include <basegfx/point/b2dpoint.hxx> + +class SdrObject; + +class GradTransVector +{ +public: + basegfx::B2DPoint maPositionA; + basegfx::B2DPoint maPositionB; + Color aCol1; + Color aCol2; +}; + +class GradTransGradient +{ +public: + XGradient aGradient; +}; + +class GradTransformer +{ +public: + GradTransformer() {} + + void GradToVec(GradTransGradient& rG, GradTransVector& rV, + const SdrObject* pObj); + void VecToGrad(GradTransVector& rV, GradTransGradient& rG, + GradTransGradient& rGOld, const SdrObject* pObj, sal_Bool bMoveSingle, sal_Bool bMoveFirst); +}; + +#endif // _GRADTRANS_HXX + diff --git a/svx/source/svdraw/impgrfll.cxx b/svx/source/svdraw/impgrfll.cxx new file mode 100644 index 000000000000..be2fc907d173 --- /dev/null +++ b/svx/source/svdraw/impgrfll.cxx @@ -0,0 +1,255 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/rectenum.hxx> +#include <vcl/svapp.hxx> +#include <vcl/outdev.hxx> +#include <vcl/bitmap.hxx> + +/////////////////////////////////////////////////////////////////////////////// + +void ImpCalcBmpFillSizes( Size& rStartOffset, + Size& rBmpOutputSize, + const Rectangle& rOutputRect, + const MapMode& rOutputMapMode, + const Bitmap& rFillBitmap, + const Size& rBmpSize, + const Size& rBmpPerCent, + const Size& rBmpOffPerCent, + BOOL bBmpLogSize, + BOOL bBmpTile, + BOOL bBmpStretch, + RECT_POINT eBmpRectPoint ) +{ + BOOL bOriginalSize = FALSE, bScaleSize = FALSE; + + // Falls keine Groessen gegeben sind ( z.B. alte Dokumente ) + // berechnen wir uns die Groesse selber aus der Bitmap + // ==> altes Verhalten; + // wenn nur eine Groesse gegeben ist, wird die andere + // Groesse angepasst berechnet + if( bBmpLogSize ) + { + if( !rBmpSize.Width() && !rBmpSize.Height() ) + bOriginalSize = TRUE; + else if( !rBmpSize.Width() || !rBmpSize.Height() ) + bScaleSize = TRUE; + } + else + { + if( !rBmpPerCent.Width() && !rBmpPerCent.Height() ) + bOriginalSize = TRUE; + else if( !rBmpPerCent.Width() || !rBmpPerCent.Height() ) + bScaleSize = TRUE; + } + + // entweder Originalgroesse oder angepasste Groesse + if( bOriginalSize || bScaleSize ) + { + MapMode aBmpPrefMapMode( rFillBitmap.GetPrefMapMode() ); + Size aBmpPrefSize( rFillBitmap.GetPrefSize() ); + + // Falls keine gesetzt ist, nehmen wir Pixel + if( !aBmpPrefSize.Width() || !aBmpPrefSize.Height() ) + { + aBmpPrefSize = rFillBitmap.GetSizePixel(); + aBmpPrefMapMode = MAP_PIXEL; + } + + if( bOriginalSize ) + { + if( MAP_PIXEL == aBmpPrefMapMode.GetMapUnit() ) + rBmpOutputSize = Application::GetDefaultDevice()->PixelToLogic( aBmpPrefSize, rOutputMapMode ); + else + rBmpOutputSize = OutputDevice::LogicToLogic( aBmpPrefSize, aBmpPrefMapMode, rOutputMapMode ); + } + else + { + if( bBmpLogSize ) + { + rBmpOutputSize = rBmpSize; + + if( !rBmpSize.Width() ) + rBmpOutputSize.Width() = basegfx::fround( (double) rBmpSize.Height() * aBmpPrefSize.Width() / aBmpPrefSize.Height() ); + else + rBmpOutputSize.Height() = basegfx::fround( (double) rBmpSize.Width() * aBmpPrefSize.Height() / aBmpPrefSize.Width() ); + } + else + { + if( !rBmpPerCent.Width() ) + { + rBmpOutputSize.Height() = basegfx::fround( (double) rOutputRect.GetHeight() * rBmpPerCent.Height() / 100. ); + rBmpOutputSize.Width() = basegfx::fround( (double) rBmpOutputSize.Height() * aBmpPrefSize.Width() / aBmpPrefSize.Height() ); + } + else + { + rBmpOutputSize.Width() = basegfx::fround( (double) rOutputRect.GetWidth() * rBmpPerCent.Width() / 100. ); + rBmpOutputSize.Height() = basegfx::fround( (double) rBmpOutputSize.Width() * aBmpPrefSize.Height() / aBmpPrefSize.Width() ); + } + } + } + } + // ansonsten koennen wir die Groesse leicht selber berechnen + else + { + if( bBmpLogSize ) + rBmpOutputSize = rBmpSize; + else + { + rBmpOutputSize.Width() = basegfx::fround( (double) rOutputRect.GetWidth() * rBmpPerCent.Width() / 100. ); + rBmpOutputSize.Height() = basegfx::fround( (double) rOutputRect.GetHeight() * rBmpPerCent.Height() / 100. ); + } + } + + // nur bei Kachelung die anderen Positionen berechnen + if( bBmpTile ) + { + Point aStartPoint; + + // Grundposition der ersten Kachel berechen; + // Diese Position wird spaeter zur Berechnung der absoluten + // Startposition links oberhalb des Objektes benutzt + switch( eBmpRectPoint ) + { + case( RP_MT ): + { + aStartPoint.X() = rOutputRect.Left() + ( ( rOutputRect.GetWidth() - rBmpOutputSize.Width() ) >> 1 ); + aStartPoint.Y() = rOutputRect.Top(); + } + break; + + case( RP_RT ): + { + aStartPoint.X() = rOutputRect.Right() - rBmpOutputSize.Width(); + aStartPoint.Y() = rOutputRect.Top(); + } + break; + + case( RP_LM ): + { + aStartPoint.X() = rOutputRect.Left(); + aStartPoint.Y() = rOutputRect.Top() + ( ( rOutputRect.GetHeight() - rBmpOutputSize.Height() ) >> 1 ); + } + break; + + case( RP_MM ): + { + aStartPoint.X() = rOutputRect.Left() + ( ( rOutputRect.GetWidth() - rBmpOutputSize.Width() ) >> 1 ); + aStartPoint.Y() = rOutputRect.Top() + ( ( rOutputRect.GetHeight() - rBmpOutputSize.Height() ) >> 1 ); + } + break; + + case( RP_RM ): + { + aStartPoint.X() = rOutputRect.Right() - rBmpOutputSize.Width(); + aStartPoint.Y() = rOutputRect.Top() + ( ( rOutputRect.GetHeight() - rBmpOutputSize.Height() ) >> 1 ); + } + break; + + case( RP_LB ): + { + aStartPoint.X() = rOutputRect.Left(); + aStartPoint.Y() = rOutputRect.Bottom() - rBmpOutputSize.Height(); + } + break; + + case( RP_MB ): + { + aStartPoint.X() = rOutputRect.Left() + ( ( rOutputRect.GetWidth() - rBmpOutputSize.Width() ) >> 1 ); + aStartPoint.Y() = rOutputRect.Bottom() - rBmpOutputSize.Height(); + } + break; + + case( RP_RB ): + { + aStartPoint.X() = rOutputRect.Right() - rBmpOutputSize.Width(); + aStartPoint.Y() = rOutputRect.Bottom() - rBmpOutputSize.Height(); + } + break; + + // default linke obere Ecke + default: + aStartPoint = rOutputRect.TopLeft(); + break; + } + + // X- oder Y-Positionsoffset beruecksichtigen + if( rBmpOffPerCent.Width() ) + aStartPoint.X() += ( rBmpOutputSize.Width() * rBmpOffPerCent.Width() / 100 ); + + if( rBmpOffPerCent.Height() ) + aStartPoint.Y() += ( rBmpOutputSize.Height() * rBmpOffPerCent.Height() / 100 ); + + // echten Startpunkt berechnen ( links oben ) + if( rBmpOutputSize.Width() && rBmpOutputSize.Height() ) + { + const long nDiffX = aStartPoint.X() - rOutputRect.Left(); + const long nDiffY = aStartPoint.Y() - rOutputRect.Top(); + + if ( nDiffX ) + { + long nCount = nDiffX / rBmpOutputSize.Width() + 1; + + if ( rBmpOffPerCent.Height() && ( nCount & 1L ) ) + nCount++; + + aStartPoint.X() -= ( nCount * rBmpOutputSize.Width() ); + } + + if ( nDiffY ) + { + long nCount = nDiffY / rBmpOutputSize.Height() + 1; + + if ( rBmpOffPerCent.Width() && ( nCount & 1L ) ) + nCount++; + + aStartPoint.Y() -= ( nCount * rBmpOutputSize.Height() ); + } + } + + rStartOffset = Size( aStartPoint.X() - rOutputRect.Left(), + aStartPoint.Y() - rOutputRect.Top() ); + } + else + { + if( bBmpStretch ) + { + rStartOffset = Size(0, 0); + rBmpOutputSize = rOutputRect.GetSize(); + } + else + { + rStartOffset = Size( ( rOutputRect.GetWidth() - rBmpOutputSize.Width() ) >> 1, + ( rOutputRect.GetHeight() - rBmpOutputSize.Height() ) >> 1 ); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/makefile.mk b/svx/source/svdraw/makefile.mk new file mode 100644 index 000000000000..514c5b6d2cbc --- /dev/null +++ b/svx/source/svdraw/makefile.mk @@ -0,0 +1,124 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=svx +TARGET=svdraw +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +LIB1TARGET= $(SLB)$/$(TARGET)-core.lib +LIB1OBJFILES= \ + $(SLO)$/svdxcgv.obj \ + $(SLO)$/svdmodel.obj \ + $(SLO)$/svdpage.obj \ + $(SLO)$/svdobj.obj \ + $(SLO)$/svdedtv1.obj \ + $(SLO)$/svdcrtv.obj \ + $(SLO)$/svdograf.obj \ + $(SLO)$/svdoole2.obj \ + $(SLO)$/svdhdl.obj \ + $(SLO)$/svdmrkv.obj \ + $(SLO)$/svdogrp.obj \ + $(SLO)$/svdotxln.obj \ + $(SLO)$/svdotextdecomposition.obj \ + $(SLO)$/svdotextpathdecomposition.obj \ + $(SLO)$/svdouno.obj \ + $(SLO)$/svdpagv.obj \ + $(SLO)$/svddrgmt.obj \ + $(SLO)$/svdpntv.obj \ + $(SLO)$/svdsnpv.obj \ + $(SLO)$/svdview.obj \ + $(SLO)$/svdtext.obj \ + $(SLO)$/svdoashp.obj \ + $(SLO)$/svdoattr.obj \ + $(SLO)$/svdotext.obj \ + $(SLO)$/svdotxat.obj \ + $(SLO)$/svdotxdr.obj \ + $(SLO)$/svdotxed.obj \ + $(SLO)$/svdotxfl.obj \ + $(SLO)$/svdotxtr.obj \ + $(SLO)$/svdorect.obj \ + $(SLO)$/svdoedge.obj \ + $(SLO)$/svdomeas.obj \ + $(SLO)$/svdopath.obj \ + $(SLO)$/svdocapt.obj \ + $(SLO)$/svdocirc.obj \ + $(SLO)$/svdopage.obj \ + $(SLO)$/svdoutl.obj \ + $(SLO)$/svdovirt.obj \ + $(SLO)$/svdoutlinercache.obj \ + $(SLO)$/gradtrns.obj \ + $(SLO)$/svdattr.obj \ + $(SLO)$/svddrag.obj \ + $(SLO)$/svddrgv.obj \ + $(SLO)$/svdedtv2.obj \ + $(SLO)$/svdedxv.obj \ + $(SLO)$/svdetc.obj \ + $(SLO)$/sdrhittesthelper.obj \ + $(SLO)$/svdfmtf.obj \ + $(SLO)$/svdglev.obj \ + $(SLO)$/svdglue.obj \ + $(SLO)$/svdhlpln.obj \ + $(SLO)$/svditer.obj \ + $(SLO)$/svdlayer.obj \ + $(SLO)$/svdmark.obj \ + $(SLO)$/svdmrkv1.obj \ + $(SLO)$/sdrcomment.obj \ + $(SLO)$/sdrmasterpagedescriptor.obj \ + $(SLO)$/sdrpagewindow.obj \ + $(SLO)$/sdrpaintwindow.obj \ + $(SLO)$/svdpoev.obj \ + $(SLO)$/svdtrans.obj \ + $(SLO)$/svdundo.obj \ + $(SLO)$/svdviter.obj \ + $(SLO)$/clonelist.obj \ + $(SLO)$/svdedtv.obj \ + $(SLO)$/selectioncontroller.obj \ + $(SLO)$/polypolygoneditor.obj \ + $(SLO)$/svdibrow.obj \ + $(SLO)$/svdomedia.obj + +LIB2TARGET= $(SLB)$/$(TARGET).lib +LIB2OBJFILES= \ + $(SLO)$/ActionDescriptionProvider.obj \ + $(SLO)$/impgrfll.obj + +SLOFILES = $(LIB1OBJFILES) $(LIB2OBJFILES) + +SRS1NAME=svdstr +SRC1FILES= svdstr.src + +.INCLUDE : target.mk diff --git a/svx/source/svdraw/polypolygoneditor.cxx b/svx/source/svdraw/polypolygoneditor.cxx new file mode 100644 index 000000000000..804f39957938 --- /dev/null +++ b/svx/source/svdraw/polypolygoneditor.cxx @@ -0,0 +1,190 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +#include "svx/polypolygoneditor.hxx" + +namespace sdr { + +PolyPolygonEditor::PolyPolygonEditor( const basegfx::B2DPolyPolygon& rPolyPolygon, bool bClosed ) +: maPolyPolygon( rPolyPolygon ) +, mbIsClosed( bClosed ) +{ +} + +bool PolyPolygonEditor::DeletePoints( const std::set< sal_uInt16 >& rAbsPoints ) +{ + bool bPolyPolyChanged = false; + + std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() ); + for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ ) + { + sal_uInt32 nPoly, nPnt; + if( GetRelativePolyPoint(maPolyPolygon,(*aIter), nPoly, nPnt) ) + { + // remove point + basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPoly)); + + aCandidate.remove(nPnt); + + if( ( mbIsClosed && aCandidate.count() < 3L) || (aCandidate.count() < 2L) ) + { + maPolyPolygon.remove(nPoly); + } + else + { + maPolyPolygon.setB2DPolygon(nPoly, aCandidate); + } + + bPolyPolyChanged = true; + } + } + + return bPolyPolyChanged; +} + +bool PolyPolygonEditor::SetSegmentsKind(SdrPathSegmentKind eKind, const std::set< sal_uInt16 >& rAbsPoints ) +{ + bool bPolyPolyChanged = false; + + std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() ); + for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ ) + { + sal_uInt32 nPolyNum, nPntNum; + + if(PolyPolygonEditor::GetRelativePolyPoint(maPolyPolygon, (*aIter), nPolyNum, nPntNum)) + { + // do change at aNewPolyPolygon. Take a look at edge. + basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPolyNum)); + bool bCandidateChanged(false); + const sal_uInt32 nCount(aCandidate.count()); + + if(nCount && (nPntNum + 1 < nCount || aCandidate.isClosed())) + { + // it's a valid edge, check control point usage + const sal_uInt32 nNextIndex((nPntNum + 1) % nCount); + const bool bContolUsed(aCandidate.areControlPointsUsed() + && (aCandidate.isNextControlPointUsed(nPntNum) || aCandidate.isPrevControlPointUsed(nNextIndex))); + + if(bContolUsed) + { + if(SDRPATHSEGMENT_TOGGLE == eKind || SDRPATHSEGMENT_LINE == eKind) + { + // remove control + aCandidate.resetNextControlPoint(nPntNum); + aCandidate.resetPrevControlPoint(nNextIndex); + bCandidateChanged = true; + } + } + else + { + if(SDRPATHSEGMENT_TOGGLE == eKind || SDRPATHSEGMENT_CURVE == eKind) + { + // add control + const basegfx::B2DPoint aStart(aCandidate.getB2DPoint(nPntNum)); + const basegfx::B2DPoint aEnd(aCandidate.getB2DPoint(nNextIndex)); + + aCandidate.setNextControlPoint(nPntNum, interpolate(aStart, aEnd, (1.0 / 3.0))); + aCandidate.setPrevControlPoint(nNextIndex, interpolate(aStart, aEnd, (2.0 / 3.0))); + bCandidateChanged = true; + } + } + + if(bCandidateChanged) + { + maPolyPolygon.setB2DPolygon(nPolyNum, aCandidate); + bPolyPolyChanged = true; + } + } + } + } + + return bPolyPolyChanged; +} + +bool PolyPolygonEditor::SetPointsSmooth( basegfx::B2VectorContinuity eFlags, const std::set< sal_uInt16 >& rAbsPoints) +{ + bool bPolyPolygonChanged(false); + + std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() ); + for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ ) + { + sal_uInt32 nPolyNum, nPntNum; + + if(PolyPolygonEditor::GetRelativePolyPoint(maPolyPolygon, (*aIter), nPolyNum, nPntNum)) + { + // do change at aNewPolyPolygon... + basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPolyNum)); + + // set continuity in point, make sure there is a curve + bool bPolygonChanged(false); + bPolygonChanged = basegfx::tools::expandToCurveInPoint(aCandidate, nPntNum); + bPolygonChanged |= basegfx::tools::setContinuityInPoint(aCandidate, nPntNum, eFlags); + + if(bPolygonChanged) + { + maPolyPolygon.setB2DPolygon(nPolyNum, aCandidate); + bPolyPolygonChanged = true; + } + } + } + + return bPolyPolygonChanged; +} + +bool PolyPolygonEditor::GetRelativePolyPoint( const basegfx::B2DPolyPolygon& rPoly, sal_uInt32 nAbsPnt, sal_uInt32& rPolyNum, sal_uInt32& rPointNum ) +{ + const sal_uInt32 nPolyCount(rPoly.count()); + sal_uInt32 nPolyNum(0L); + + while(nPolyNum < nPolyCount) + { + const sal_uInt32 nPointCount(rPoly.getB2DPolygon(nPolyNum).count()); + + if(nAbsPnt < nPointCount) + { + rPolyNum = nPolyNum; + rPointNum = nAbsPnt; + + return true; + } + else + { + nPolyNum++; + nAbsPnt -= nPointCount; + } + } + + return false; +} + +} // end of namespace sdr diff --git a/svx/source/svdraw/sdrcomment.cxx b/svx/source/svdraw/sdrcomment.cxx new file mode 100644 index 000000000000..9f68b3e806ff --- /dev/null +++ b/svx/source/svdraw/sdrcomment.cxx @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/sdrcomment.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace sdr +{ + Comment::Comment( + sal_uInt32 nID, + Date aCreationDate, + const ::rtl::OUString& rUserName, + const ::rtl::OUString& rText, + const basegfx::B2DPoint& rPosition) + : mnID(nID), + maCreationDate(aCreationDate), + maUserName(rUserName), + maText(rText), + maPosition(rPosition) + { + } + + Comment::~Comment() + { + } + + sal_Bool Comment::operator==(const Comment& rCandidate) const + { + return ( + mnID == rCandidate.mnID + && maCreationDate == rCandidate.maCreationDate + && maUserName == rCandidate.maUserName + && maText == rCandidate.maText + && maPosition == rCandidate.maPosition); + } + + void Comment::SetCreationDate(Date aNewDate) + { + if(aNewDate != maCreationDate) + { + maCreationDate = aNewDate; + } + } + + void Comment::SetUserName(const ::rtl::OUString& rNewName) + { + if(rNewName != maUserName) + { + maUserName = rNewName; + } + } + + void Comment::SetText(const ::rtl::OUString& rNewText) + { + if(rNewText != maText) + { + maText = rNewText; + } + } + + void Comment::SetPosition(const basegfx::B2DPoint& rNewPos) + { + if(rNewPos != maPosition) + { + maPosition = rNewPos; + } + } +} // end of namespace sdr + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/sdrhittesthelper.cxx b/svx/source/svdraw/sdrhittesthelper.cxx new file mode 100644 index 000000000000..58eef58a9fd6 --- /dev/null +++ b/svx/source/svdraw/sdrhittesthelper.cxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/sdrhittesthelper.hxx> +#include <svx/obj3d.hxx> +#include <svx/helperhittest3d.hxx> +#include <svx/sdrpagewindow.hxx> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <svx/sdr/contact/objectcontact.hxx> +#include <drawinglayer/processor2d/hittestprocessor2d.hxx> +#include <svx/svdpagv.hxx> +#include <svx/sdr/contact/viewcontact.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i101872# new Object HitTest as View-tooling + +SdrObject* SdrObjectPrimitiveHit( + const SdrObject& rObject, + const Point& rPnt, + sal_uInt16 nTol, + const SdrPageView& rSdrPageView, + const SetOfByte* pVisiLayer, + bool bTextOnly) +{ + SdrObject* pResult = 0; + + if(rObject.GetSubList() && rObject.GetSubList()->GetObjCount()) + { + // group or scene with content. Single 3D objects also have a + // true == rObject.GetSubList(), but no content + pResult = SdrObjListPrimitiveHit(*rObject.GetSubList(), rPnt, nTol, rSdrPageView, pVisiLayer, bTextOnly); + } + else + { + if( rObject.IsVisible() && (!pVisiLayer || pVisiLayer->IsSet(rObject.GetLayer()))) + { + // single object, 3d object, empty scene or empty group. Check if + // it's a single 3D object + const E3dCompoundObject* pE3dCompoundObject = dynamic_cast< const E3dCompoundObject* >(&rObject); + + if(pE3dCompoundObject) + { + const basegfx::B2DPoint aHitPosition(rPnt.X(), rPnt.Y()); + + if(checkHitSingle3DObject(aHitPosition, *pE3dCompoundObject)) + { + pResult = const_cast< E3dCompoundObject* >(pE3dCompoundObject); + } + } + else + { + // not a single 3D object; Check in first PageWindow using prmitives (only SC + // with split views uses multiple PageWindows nowadays) + if(rSdrPageView.PageWindowCount()) + { + const double fLogicTolerance(nTol); + const basegfx::B2DPoint aHitPosition(rPnt.X(), rPnt.Y()); + const sdr::contact::ViewObjectContact& rVOC = rObject.GetViewContact().GetViewObjectContact( + rSdrPageView.GetPageWindow(0)->GetObjectContact()); + + if(ViewObjectContactPrimitiveHit(rVOC, aHitPosition, fLogicTolerance, bTextOnly)) + { + pResult = const_cast< SdrObject* >(&rObject); + } + } + } + } + } + + return pResult; +} + +///////////////////////////////////////////////////////////////////// + +SdrObject* SdrObjListPrimitiveHit( + const SdrObjList& rList, + const Point& rPnt, + sal_uInt16 nTol, + const SdrPageView& rSdrPageView, + const SetOfByte* pVisiLayer, + bool bTextOnly) +{ + sal_uInt32 nObjNum(rList.GetObjCount()); + SdrObject* pRetval = 0; + + while(!pRetval && nObjNum > 0) + { + nObjNum--; + SdrObject* pObj = rList.GetObj(nObjNum); + + pRetval = SdrObjectPrimitiveHit(*pObj, rPnt, nTol, rSdrPageView, pVisiLayer, bTextOnly); + } + + return pRetval; +} + +///////////////////////////////////////////////////////////////////// + +bool ViewObjectContactPrimitiveHit( + const sdr::contact::ViewObjectContact& rVOC, + const basegfx::B2DPoint& rHitPosition, + double fLogicHitTolerance, + bool bTextOnly) +{ + basegfx::B2DRange aObjectRange(rVOC.getObjectRange()); + + if(!aObjectRange.isEmpty()) + { + // first do a rough B2DRange based HitTest; do not forget to + // include the HitTolerance if given + if(basegfx::fTools::more(fLogicHitTolerance, 0.0)) + { + aObjectRange.grow(fLogicHitTolerance); + } + + if(aObjectRange.isInside(rHitPosition)) + { + // get primitive sequence + sdr::contact::DisplayInfo aDisplayInfo; + const drawinglayer::primitive2d::Primitive2DSequence& rSequence(rVOC.getPrimitive2DSequence(aDisplayInfo)); + + if(rSequence.hasElements()) + { + // create a HitTest processor + const drawinglayer::geometry::ViewInformation2D& rViewInformation2D = rVOC.GetObjectContact().getViewInformation2D(); + drawinglayer::processor2d::HitTestProcessor2D aHitTestProcessor2D( + rViewInformation2D, + rHitPosition, + fLogicHitTolerance, + bTextOnly); + + // feed it with the primitives + aHitTestProcessor2D.process(rSequence); + + // deliver result + return aHitTestProcessor2D.getHit(); + } + } + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/sdrmasterpagedescriptor.cxx b/svx/source/svdraw/sdrmasterpagedescriptor.cxx new file mode 100644 index 000000000000..67b2de8b693c --- /dev/null +++ b/svx/source/svdraw/sdrmasterpagedescriptor.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/sdrmasterpagedescriptor.hxx> +#include <svx/sdr/contact/viewcontactofmasterpagedescriptor.hxx> +#include <svx/svdpage.hxx> + +// #i42075# +#include <svx/svdobj.hxx> +#include <svx/xfillit0.hxx> +#include <svl/itemset.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace sdr +{ + // ViewContact part + sdr::contact::ViewContact* MasterPageDescriptor::CreateObjectSpecificViewContact() + { + return new sdr::contact::ViewContactOfMasterPageDescriptor(*this); + } + + MasterPageDescriptor::MasterPageDescriptor(SdrPage& aOwnerPage, SdrPage& aUsedPage) + : maOwnerPage(aOwnerPage), + maUsedPage(aUsedPage), + mpViewContact(0L) + { + // all layers visible + maVisibleLayers.SetAll(); + + // register at used page + maUsedPage.AddPageUser(*this); + } + + MasterPageDescriptor::~MasterPageDescriptor() + { + // de-register at used page + maUsedPage.RemovePageUser(*this); + + if(mpViewContact) + { + delete mpViewContact; + mpViewContact = 0L; + } + } + + // ViewContact part + sdr::contact::ViewContact& MasterPageDescriptor::GetViewContact() const + { + if(!mpViewContact) + { + const_cast< MasterPageDescriptor* >(this)->mpViewContact = + const_cast< MasterPageDescriptor* >(this)->CreateObjectSpecificViewContact(); + } + + return *mpViewContact; + } + + // this method is called form the destructor of the referenced page. + // do all necessary action to forget the page. It is not necessary to call + // RemovePageUser(), that is done form the destructor. + void MasterPageDescriptor::PageInDestruction(const SdrPage& /*rPage*/) + { + maOwnerPage.TRG_ClearMasterPage(); + } + + void MasterPageDescriptor::SetVisibleLayers(const SetOfByte& rNew) + { + if(rNew != maVisibleLayers) + { + maVisibleLayers = rNew; + GetViewContact().ActionChanged(); + } + } + + // operators + sal_Bool MasterPageDescriptor::operator==(const MasterPageDescriptor& rCandidate) const + { + return (&maOwnerPage == &rCandidate.maOwnerPage + && &maUsedPage == &rCandidate.maUsedPage + && maVisibleLayers == rCandidate.maVisibleLayers); + } + + sal_Bool MasterPageDescriptor::operator!=(const MasterPageDescriptor& rCandidate) const + { + return (&maOwnerPage != &rCandidate.maOwnerPage + || &maUsedPage != &rCandidate.maUsedPage + || maVisibleLayers != rCandidate.maVisibleLayers); + } +} // end of namespace sdr + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/sdrpagewindow.cxx b/svx/source/svdraw/sdrpagewindow.cxx new file mode 100644 index 000000000000..85513fb3b926 --- /dev/null +++ b/svx/source/svdraw/sdrpagewindow.cxx @@ -0,0 +1,464 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/sdrpagewindow.hxx> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/util/XModeChangeBroadcaster.hpp> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <sdrpaintwindow.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <vos/mutex.hxx> +#include <svx/fmview.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +using namespace ::rtl; +using namespace ::com::sun::star; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlContainer > SdrPageWindow::GetControlContainer( bool _bCreateIfNecessary ) const +{ + if ( !mxControlContainer.is() && _bCreateIfNecessary ) + { + SdrView& rView = GetPageView().GetView(); + + const SdrPaintWindow& rPaintWindow( GetOriginalPaintWindow() ? *GetOriginalPaintWindow() : GetPaintWindow() ); + if ( rPaintWindow.OutputToWindow() && !rView.IsPrintPreview() ) + { + Window& rWindow = dynamic_cast< Window& >( rPaintWindow.GetOutputDevice() ); + const_cast< SdrPageWindow* >( this )->mxControlContainer = VCLUnoHelper::CreateControlContainer( &rWindow ); + + // #100394# xC->setVisible triggers window->Show() and this has + // problems when the view is not completely constructed which may + // happen when loading. This leads to accessibility broadcasts which + // throw asserts due to the not finished view. All this chan be avoided + // since xC->setVisible is here called only for the side effect in + // UnoControlContainer::setVisible(...) which calls createPeer(...). + // This will now be called directly from here. + + // UnoContainerModel erzeugen + // uno::Reference< awt::XWindow > xC(mxControlContainer, uno::UNO_QUERY); + // CreateControlContainer() is only used from + // , thus it seems not necessary to make + // it visible her at all. + // #58917# Das Show darf nicht am VCL-Fenster landen, weil dann Assertion vom SFX + // BOOL bVis = pWindow->IsVisible(); + // xC->setVisible(TRUE); + // if ( !bVis ) + // pWindow->Hide(); + // if( !mxContext.is() && bVisible ) + // // Es ist ein TopWindow, also automatisch anzeigen + // createPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > (), ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > () ); + + uno::Reference< awt::XControl > xControl(mxControlContainer, uno::UNO_QUERY); + if(xControl.is()) + { + uno::Reference< uno::XInterface > xContext = xControl->getContext(); + if(!xContext.is()) + { + xControl->createPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > (), + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > () ); + } + } + } + else + { + // Printer und VirtualDevice, bzw. kein OutDev + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + if( xFactory.is() ) + { + const_cast< SdrPageWindow* >( this )->mxControlContainer = uno::Reference< awt::XControlContainer >(xFactory->createInstance(rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlContainer")), uno::UNO_QUERY); + uno::Reference< awt::XControlModel > xModel(xFactory->createInstance(rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlContainerModel")), uno::UNO_QUERY); + uno::Reference< awt::XControl > xControl(mxControlContainer, uno::UNO_QUERY); + if (xControl.is()) + xControl->setModel(xModel); + + OutputDevice& rOutDev = rPaintWindow.GetOutputDevice(); + Point aPosPix = rOutDev.GetMapMode().GetOrigin(); + Size aSizePix = rOutDev.GetOutputSizePixel(); + + uno::Reference< awt::XWindow > xContComp(mxControlContainer, uno::UNO_QUERY); + if( xContComp.is() ) + xContComp->setPosSize(aPosPix.X(), aPosPix.Y(), aSizePix.Width(), aSizePix.Height(), awt::PosSize::POSSIZE); + } + } + + FmFormView* pViewAsFormView = dynamic_cast< FmFormView* >( &rView ); + if ( pViewAsFormView ) + pViewAsFormView->InsertControlContainer(mxControlContainer); + } + return mxControlContainer; +} + +SdrPageWindow::SdrPageWindow(SdrPageView& rPageView, SdrPaintWindow& rPaintWindow) +: mpObjectContact(0L), + mrPageView(rPageView), + mpPaintWindow(&rPaintWindow), + mpOriginalPaintWindow(NULL) +{ +} + +SdrPageWindow::~SdrPageWindow() +{ + // #110094#, #i26631# + ResetObjectContact(); + + if (mxControlContainer.is()) + { + SdrView& rView = GetPageView().GetView(); + + // notify derived views + FmFormView* pViewAsFormView = dynamic_cast< FmFormView* >( &rView ); + if ( pViewAsFormView ) + pViewAsFormView->RemoveControlContainer(mxControlContainer); + + // dispose the control container + uno::Reference< lang::XComponent > xComponent(mxControlContainer, uno::UNO_QUERY); + xComponent->dispose(); + } +} + +// #110094# ObjectContact section +sdr::contact::ObjectContact* SdrPageWindow::CreateViewSpecificObjectContact() +{ + return new sdr::contact::ObjectContactOfPageView(*this); +} + +// OVERLAYMANAGER +::sdr::overlay::OverlayManager* SdrPageWindow::GetOverlayManager() const +{ + return GetPaintWindow().GetOverlayManager(); +} + +void SdrPageWindow::patchPaintWindow(SdrPaintWindow& rPaintWindow) +{ + mpOriginalPaintWindow = mpPaintWindow; + mpPaintWindow = &rPaintWindow; +} + +void SdrPageWindow::unpatchPaintWindow() +{ + DBG_ASSERT(mpOriginalPaintWindow, "SdrPageWindow::unpatchPaintWindow: paint window not patched!" ); + if ( mpOriginalPaintWindow ) + { + mpPaintWindow = mpOriginalPaintWindow; + mpOriginalPaintWindow = NULL; + } +} + +void SdrPageWindow::PrePaint() +{ + // give OC the chance to do ProcessDisplay preparations + if(HasObjectContact()) + { + GetObjectContact().PrepareProcessDisplay(); + } +} + +void SdrPageWindow::PrepareRedraw(const Region& rReg) +{ + // evtl. give OC the chance to do ProcessDisplay preparations + if(HasObjectContact()) + { + GetObjectContact().PrepareProcessDisplay(); + } + + // remember eventually changed RedrawArea at PaintWindow for usage with + // overlay and PreRenderDevice stuff + GetPaintWindow().SetRedrawRegion(rReg); +} + +////////////////////////////////////////////////////////////////////////////// +// clip test +#ifdef CLIPPER_TEST +#include <svx/svdopath.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <basegfx/polygon/b2dpolygoncutandtouch.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygonclipper.hxx> + +// for ::std::sort +#include <algorithm> + +namespace +{ + void impPaintStrokePolygon(const basegfx::B2DPolygon& rCandidate, OutputDevice& rOutDev, Color aColor) + { + basegfx::B2DPolygon aCandidate(rCandidate); + + if(aCandidate.areControlPointsUsed()) + { + aCandidate = basegfx::tools::adaptiveSubdivideByAngle(rCandidate); + } + + if(aCandidate.count()) + { + const sal_uInt32 nLoopCount(aCandidate.isClosed() ? aCandidate.count() : aCandidate.count() - 1L); + rOutDev.SetFillColor(); + rOutDev.SetLineColor(aColor); + + for(sal_uInt32 a(0L); a < nLoopCount; a++) + { + const basegfx::B2DPoint aBStart(aCandidate.getB2DPoint(a)); + const basegfx::B2DPoint aBEnd(aCandidate.getB2DPoint((a + 1) % aCandidate.count())); + const Point aStart(FRound(aBStart.getX()), FRound(aBStart.getY())); + const Point aEnd(FRound(aBEnd.getX()), FRound(aBEnd.getY())); + rOutDev.DrawLine(aStart, aEnd); + } + } + } + + void impTryTest(const SdrPageView& rPageView, OutputDevice& rOutDev) + { + if(rPageView.GetPage() && rPageView.GetPage()->GetObjCount() >= 2L) + { + SdrPage* pPage = rPageView.GetPage(); + SdrObject* pObjA = pPage->GetObj(0L); + + if(pObjA && pObjA->ISA(SdrPathObj)) + { + basegfx::B2DPolyPolygon aPolyA(((SdrPathObj*)pObjA)->GetPathPoly()); + aPolyA = basegfx::tools::correctOrientations(aPolyA); + + basegfx::B2DPolyPolygon aPolyB; + + for(sal_uInt32 a(1L); a < rPageView.GetPage()->GetObjCount(); a++) + { + SdrObject* pObjB = pPage->GetObj(a); + + if(pObjB && pObjB->ISA(SdrPathObj)) + { + basegfx::B2DPolyPolygon aCandidate(((SdrPathObj*)pObjB)->GetPathPoly()); + aCandidate = basegfx::tools::correctOrientations(aCandidate); + aPolyB.append(aCandidate); + } + } + + if(aPolyA.count() && aPolyA.isClosed() && aPolyB.count()) + { + // poly A is the clipregion, clip poly b against it. Algo depends on + // poly b being closed. + basegfx::B2DPolyPolygon aResult(basegfx::tools::clipPolyPolygonOnPolyPolygon(aPolyB, aPolyA)); + + for(sal_uInt32 a(0L); a < aResult.count(); a++) + { + Color aColor(rand()%255, rand()%255, rand()%255); + impPaintStrokePolygon(aResult.getB2DPolygon(a), rOutDev, aColor); + } + + bool bBla = true; + } + } + } + } +} // end of anonymous namespace +#endif // CLIPPER_TEST + +////////////////////////////////////////////////////////////////////////////// + +void SdrPageWindow::RedrawAll(sdr::contact::ViewObjectContactRedirector* pRedirector) const +{ + // set Redirector + GetObjectContact().SetViewObjectContactRedirector(pRedirector); + + // set PaintingPageView + const SdrView& rView = mrPageView.GetView(); + SdrModel& rModel = *((SdrModel*)rView.GetModel()); + + // get to be processed layers + const sal_Bool bPrinter(GetPaintWindow().OutputToPrinter()); + SetOfByte aProcessLayers = bPrinter ? mrPageView.GetPrintableLayers() : mrPageView.GetVisibleLayers(); + + // create PaintInfoRec, #114359# use Rectangle only temporarily + const Region& rRegion = GetPaintWindow().GetRedrawRegion(); + + // create processing data + sdr::contact::DisplayInfo aDisplayInfo; + + // Draw all layers. do NOT draw form layer from CompleteRedraw, this is done separate + // as a single layer paint + const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin(); + const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName(), sal_False); + aProcessLayers.Clear(nControlLayerId); + + // still something to paint? + if(!aProcessLayers.IsEmpty()) + { + aDisplayInfo.SetProcessLayers(aProcessLayers); + + // Set region as redraw area + aDisplayInfo.SetRedrawArea(rRegion); + + // Draw/Impress + aDisplayInfo.SetPageProcessingActive(rView.IsPagePaintingAllowed()); // #i72889# + + // paint page + GetObjectContact().ProcessDisplay(aDisplayInfo); + } + + // reset redirector + GetObjectContact().SetViewObjectContactRedirector(0L); + + // LineClip test +#ifdef CLIPPER_TEST + if(true) + { + impTryTest(GetPageView(), GetPaintWindow().GetOutputDevice()); + } +#endif // CLIPPER_TEST +} + +void SdrPageWindow::RedrawLayer(const SdrLayerID* pId, sdr::contact::ViewObjectContactRedirector* pRedirector) const +{ + // set redirector + GetObjectContact().SetViewObjectContactRedirector(pRedirector); + + // set PaintingPageView + const SdrView& rView = mrPageView.GetView(); + SdrModel& rModel = *((SdrModel*)rView.GetModel()); + + // get the layers to process + const sal_Bool bPrinter(GetPaintWindow().OutputToPrinter()); + SetOfByte aProcessLayers = bPrinter ? mrPageView.GetPrintableLayers() : mrPageView.GetVisibleLayers(); + + // is the given layer visible at all? + if(aProcessLayers.IsSet(*pId)) + { + // find out if we are painting the ControlLayer + const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin(); + const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName(), sal_False); + const sal_Bool bControlLayerProcessingActive(pId && nControlLayerId == *pId); + + // create PaintInfoRec, use Rectangle only temporarily + const Region& rRegion = GetPaintWindow().GetRedrawRegion(); + + // create processing data + sdr::contact::DisplayInfo aDisplayInfo; + + // is it the control layer? If Yes, set flag + aDisplayInfo.SetControlLayerProcessingActive(bControlLayerProcessingActive); + + // Draw just the one given layer + aProcessLayers.ClearAll(); + aProcessLayers.Set(*pId); + + aDisplayInfo.SetProcessLayers(aProcessLayers); + + // Set region as redraw area + aDisplayInfo.SetRedrawArea(rRegion); + + // Writer or calc, coming from original RedrawOneLayer. + // #i72889# no page painting for layer painting + aDisplayInfo.SetPageProcessingActive(false); + + // paint page + GetObjectContact().ProcessDisplay(aDisplayInfo); + } + + // reset redirector + GetObjectContact().SetViewObjectContactRedirector(0L); +} + +// Invalidate call, used from ObjectContact(OfPageView) in InvalidatePartOfView(...) +void SdrPageWindow::InvalidatePageWindow(const basegfx::B2DRange& rRange) +{ + if(GetPageView().IsVisible() && GetPaintWindow().OutputToWindow()) + { + const SvtOptionsDrawinglayer aDrawinglayerOpt; + Window& rWindow(static_cast< Window& >(GetPaintWindow().GetOutputDevice())); + basegfx::B2DRange aDiscreteRange(rRange); + aDiscreteRange.transform(rWindow.GetViewTransformation()); + + if(aDrawinglayerOpt.IsAntiAliasing()) + { + // invalidate one discrete unit more under the assumption that AA + // needs one pixel more + aDiscreteRange.grow(1.0); + } + + const Rectangle aVCLDiscreteRectangle( + (sal_Int32)floor(aDiscreteRange.getMinX()), (sal_Int32)floor(aDiscreteRange.getMinY()), + (sal_Int32)ceil(aDiscreteRange.getMaxX()), (sal_Int32)ceil(aDiscreteRange.getMaxY())); + const bool bWasMapModeEnabled(rWindow.IsMapModeEnabled()); + + rWindow.EnableMapMode(false); + rWindow.Invalidate(aVCLDiscreteRectangle, INVALIDATE_NOERASE); + rWindow.EnableMapMode(bWasMapModeEnabled); + } +} + +// #110094# ObjectContact section +sdr::contact::ObjectContact& SdrPageWindow::GetObjectContact() const +{ + if(!mpObjectContact) + { + ((SdrPageWindow*)this)->mpObjectContact = ((SdrPageWindow*)this)->CreateViewSpecificObjectContact(); + } + + return *mpObjectContact; +} + +bool SdrPageWindow::HasObjectContact() const +{ + return ( mpObjectContact != NULL ); +} + +// #i26631# +void SdrPageWindow::ResetObjectContact() +{ + if(mpObjectContact) + { + delete mpObjectContact; + mpObjectContact = 0L; + } +} + +void SdrPageWindow::SetDesignMode( bool _bDesignMode ) const +{ + const ::sdr::contact::ObjectContactOfPageView* pOC = dynamic_cast< const ::sdr::contact::ObjectContactOfPageView* >( &GetObjectContact() ); + DBG_ASSERT( pOC, "SdrPageWindow::SetDesignMode: invalid object contact!" ); + if ( pOC ) + pOC->SetUNOControlsDesignMode( _bDesignMode ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/sdrpaintwindow.cxx b/svx/source/svdraw/sdrpaintwindow.cxx new file mode 100644 index 000000000000..d173c1eea4d5 --- /dev/null +++ b/svx/source/svdraw/sdrpaintwindow.cxx @@ -0,0 +1,312 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <sdrpaintwindow.hxx> +#include <svx/sdr/overlay/overlaymanagerbuffered.hxx> +#include <svx/svdpntv.hxx> +#include <vcl/gdimtf.hxx> +#include <vcl/svapp.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrPreRenderDevice::SdrPreRenderDevice(OutputDevice& rOriginal) +: mrOutputDevice(rOriginal) +{ +} + +SdrPreRenderDevice::~SdrPreRenderDevice() +{ +} + +void SdrPreRenderDevice::PreparePreRenderDevice() +{ + // compare size of maPreRenderDevice with size of visible area + if(maPreRenderDevice.GetOutputSizePixel() != mrOutputDevice.GetOutputSizePixel()) + { + maPreRenderDevice.SetOutputSizePixel(mrOutputDevice.GetOutputSizePixel()); + } + + // Also compare the MapModes for zoom/scroll changes + if(maPreRenderDevice.GetMapMode() != mrOutputDevice.GetMapMode()) + { + maPreRenderDevice.SetMapMode(mrOutputDevice.GetMapMode()); + } + + // #i29186# + maPreRenderDevice.SetDrawMode(mrOutputDevice.GetDrawMode()); + maPreRenderDevice.SetSettings(mrOutputDevice.GetSettings()); +} + +void SdrPreRenderDevice::OutputPreRenderDevice(const Region& rExpandedRegion) +{ + // region to pixels + Region aRegionPixel(mrOutputDevice.LogicToPixel(rExpandedRegion)); + RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects()); + Rectangle aRegionRectanglePixel; + + // MapModes off + sal_Bool bMapModeWasEnabledDest(mrOutputDevice.IsMapModeEnabled()); + sal_Bool bMapModeWasEnabledSource(maPreRenderDevice.IsMapModeEnabled()); + mrOutputDevice.EnableMapMode(sal_False); + maPreRenderDevice.EnableMapMode(sal_False); + + while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel)) + { + // for each rectangle, copy the area + const Point aTopLeft(aRegionRectanglePixel.TopLeft()); + const Size aSize(aRegionRectanglePixel.GetSize()); + + mrOutputDevice.DrawOutDev( + aTopLeft, aSize, + aTopLeft, aSize, + maPreRenderDevice); + +#ifdef DBG_UTIL + // #i74769# + static bool bDoPaintForVisualControlRegion(false); + if(bDoPaintForVisualControlRegion) + { + Color aColor((((((rand()&0x7f)|0x80)<<8L)|((rand()&0x7f)|0x80))<<8L)|((rand()&0x7f)|0x80)); + mrOutputDevice.SetLineColor(aColor); + mrOutputDevice.SetFillColor(); + mrOutputDevice.DrawRect(aRegionRectanglePixel); + } +#endif + } + + aRegionPixel.EndEnumRects(aRegionHandle); + + mrOutputDevice.EnableMapMode(bMapModeWasEnabledDest); + maPreRenderDevice.EnableMapMode(bMapModeWasEnabledSource); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPaintWindow::impCreateOverlayManager(const bool bUseBuffer) +{ + // When the buffer usage has changed then we have to create a new + // overlay manager. Save the current one so that later we can move its + // overlay objects to the new one. + sdr::overlay::OverlayManager* pOldOverlayManager = NULL; + + if(mbUseBuffer != bUseBuffer) + { + mbUseBuffer = bUseBuffer; + pOldOverlayManager = mpOverlayManager; + mpOverlayManager = NULL; + } + + // not yet one created? + if(!mpOverlayManager) + { + // is it a window? + if(OUTDEV_WINDOW == GetOutputDevice().GetOutDevType()) + { + // decide which OverlayManager to use + if(GetPaintView().IsBufferedOverlayAllowed() && mbUseBuffer) + { + // buffered OverlayManager, buffers it's background and refreshes from there + // for pure overlay changes (no system redraw). The 3rd parameter specifies + // if that refresh itself will use a 2nd vdev to avoid flickering. + // Also hand over the evtl. existing old OverlayManager; this means to take over + // the registered OverlayObjects from it + mpOverlayManager = new ::sdr::overlay::OverlayManagerBuffered(GetOutputDevice(), pOldOverlayManager, true); + } + else + { + // unbuffered OverlayManager, just invalidates places where changes + // take place + // Also hand over the evtl. existing old OverlayManager; this means to take over + // the registered OverlayObjects from it + mpOverlayManager = new ::sdr::overlay::OverlayManager(GetOutputDevice(), pOldOverlayManager); + } + + OSL_ENSURE(mpOverlayManager, "SdrPaintWindow::SdrPaintWindow: Could not allocate an overlayManager (!)"); + + // Request a repaint so that the buffered overlay manager fills + // its buffer properly. This is a workaround for missing buffer + // updates. + Window* pWindow = dynamic_cast<Window*>(&GetOutputDevice()); + if (pWindow != NULL) + pWindow->Invalidate(); + + Color aColA(GetPaintView().getOptionsDrawinglayer().GetStripeColorA()); + Color aColB(GetPaintView().getOptionsDrawinglayer().GetStripeColorB()); + + if(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor(); + aColB.Invert(); + } + + mpOverlayManager->setStripeColorA(aColA); + mpOverlayManager->setStripeColorB(aColB); + mpOverlayManager->setStripeLengthPixel(GetPaintView().getOptionsDrawinglayer().GetStripeLength()); + } + } + + // OverlayObjects are transfered for the evtl. newly created OverlayManager by handing over + // at construction time + if(pOldOverlayManager) + { + // The old overlay manager is not used anymore and can be (has to be) deleted. + delete pOldOverlayManager; + } +} + +SdrPaintWindow::SdrPaintWindow(SdrPaintView& rNewPaintView, OutputDevice& rOut) +: mrOutputDevice(rOut), + mrPaintView(rNewPaintView), + mpOverlayManager(0L), + mpPreRenderDevice(0L), + mbTemporaryTarget(false), // #i72889# + mbUseBuffer(true) +{ +} + +SdrPaintWindow::~SdrPaintWindow() +{ + if(mpOverlayManager) + { + delete mpOverlayManager; + mpOverlayManager = 0L; + } + + DestroyPreRenderDevice(); +} + +::sdr::overlay::OverlayManager* SdrPaintWindow::GetOverlayManager() const +{ + if(!mpOverlayManager) + { + // Create buffered overlay manager by default. + const_cast< SdrPaintWindow* >(this)->impCreateOverlayManager(true); + } + + return mpOverlayManager; +} + +Rectangle SdrPaintWindow::GetVisibleArea() const +{ + Size aVisSizePixel(GetOutputDevice().GetOutputSizePixel()); + return Rectangle(GetOutputDevice().PixelToLogic(Rectangle(Point(0,0), aVisSizePixel))); +} + +sal_Bool SdrPaintWindow::OutputToRecordingMetaFile() const +{ + GDIMetaFile* pMetaFile = mrOutputDevice.GetConnectMetaFile(); + return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause()); +} + +void SdrPaintWindow::PreparePreRenderDevice() +{ + const sal_Bool bPrepareBufferedOutput( + mrPaintView.IsBufferedOutputAllowed() + && !OutputToPrinter() + && !OutputToVirtualDevice() + && !OutputToRecordingMetaFile()); + + if(bPrepareBufferedOutput) + { + if(!mpPreRenderDevice) + { + mpPreRenderDevice = new SdrPreRenderDevice(mrOutputDevice); + } + } + else + { + DestroyPreRenderDevice(); + } + + if(mpPreRenderDevice) + { + mpPreRenderDevice->PreparePreRenderDevice(); + } +} + +void SdrPaintWindow::DestroyPreRenderDevice() +{ + if(mpPreRenderDevice) + { + delete mpPreRenderDevice; + mpPreRenderDevice = 0L; + } +} + +void SdrPaintWindow::OutputPreRenderDevice(const Region& rExpandedRegion) +{ + if(mpPreRenderDevice) + { + mpPreRenderDevice->OutputPreRenderDevice(rExpandedRegion); + } +} + +// #i73602# add flag if buffer shall be used +void SdrPaintWindow::DrawOverlay(const Region& rRegion, bool bUseBuffer) +{ + // ## force creation of OverlayManager since the first repaint needs to + // save the background to get a controlled start into overlay mechanism + impCreateOverlayManager(bUseBuffer); + + if(mpOverlayManager && !OutputToPrinter()) + { + if(mpPreRenderDevice && bUseBuffer) + { + mpOverlayManager->completeRedraw(rRegion, &mpPreRenderDevice->GetPreRenderDevice()); + } + else + { + mpOverlayManager->completeRedraw(rRegion); + } + } +} + +void SdrPaintWindow::HideOverlay(const Region& rRegion) +{ + if(mpOverlayManager && !OutputToPrinter()) + { + if(!mpPreRenderDevice) + { + mpOverlayManager->restoreBackground(rRegion); + } + } +} + +const Region& SdrPaintWindow::GetRedrawRegion() const +{ + return maRedrawRegion; +} + +void SdrPaintWindow::SetRedrawRegion(const Region& rNew) +{ + maRedrawRegion = rNew; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/selectioncontroller.cxx b/svx/source/svdraw/selectioncontroller.cxx new file mode 100644 index 000000000000..d76f95837441 --- /dev/null +++ b/svx/source/svdraw/selectioncontroller.cxx @@ -0,0 +1,114 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <tools/debug.hxx> +#include <svx/selectioncontroller.hxx> + +namespace sdr +{ + +bool SelectionController::onKeyInput(const KeyEvent& /*rKEvt*/, Window* /*pWin*/) +{ + return false; +} + +bool SelectionController::onMouseButtonDown(const MouseEvent& /*rMEvt*/, Window* /*pWin*/) +{ + return false; +} + +bool SelectionController::onMouseButtonUp(const MouseEvent& /*rMEvt*/, Window* /*pWin*/) +{ + return false; +} + +bool SelectionController::onMouseMove(const MouseEvent& /*rMEvt*/, Window* /*pWin*/) +{ + return false; +} + +void SelectionController::onSelectionHasChanged() +{ +} + +void SelectionController::GetState( SfxItemSet& /*rSet*/ ) +{ +} + +void SelectionController::Execute( SfxRequest& /*rReq*/ ) +{ +} + +bool SelectionController::DeleteMarked() +{ + return false; +} + +bool SelectionController::GetAttributes(SfxItemSet& /*rTargetSet*/, bool /*bOnlyHardAttr*/) const +{ + return false; +} + +bool SelectionController::SetAttributes(const SfxItemSet& /*rSet*/, bool /*bReplaceAll*/) +{ + return false; +} + +bool SelectionController::GetStyleSheet( SfxStyleSheet* &/*rpStyleSheet*/ ) const +{ + return false; +} + +bool SelectionController::SetStyleSheet( SfxStyleSheet* /*pStyleSheet*/, bool /*bDontRemoveHardAttr*/ ) +{ + return false; +} + +bool SelectionController::GetMarkedObjModel( SdrPage* /*pNewPage*/ ) +{ + return false; +} + +bool SelectionController::PasteObjModel( const SdrModel& /*rModel*/ ) +{ + return false; +} + +bool SelectionController::TakeFormatPaintBrush( boost::shared_ptr< SfxItemSet >& /*rFormatSet*/ ) +{ + return false; +} + +bool SelectionController::ApplyFormatPaintBrush( SfxItemSet& /*rFormatSet*/, bool /*bNoCharacterFormats*/, bool /*bNoParagraphFormats*/ ) +{ + return false; +} + +} diff --git a/svx/source/svdraw/svdattr.cxx b/svx/source/svdraw/svdattr.cxx new file mode 100644 index 000000000000..3a3935f819f8 --- /dev/null +++ b/svx/source/svdraw/svdattr.cxx @@ -0,0 +1,2429 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + + +#include <com/sun/star/drawing/TextFitToSizeType.hpp> +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/TextAnimationKind.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/drawing/TextAnimationDirection.hpp> +#include <com/sun/star/drawing/ConnectorType.hpp> +#include <com/sun/star/drawing/MeasureKind.hpp> +#include <com/sun/star/drawing/MeasureTextHorzPos.hpp> +#include <com/sun/star/drawing/MeasureTextVertPos.hpp> +#include <com/sun/star/drawing/CircleKind.hpp> +#include <com/sun/star/uno/Sequence.hxx> + +#include <unotools/intlwrapper.hxx> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdattrx.hxx> +#include <svx/svdpool.hxx> + +#include <svl/solar.hrc> +#include "editeng/xmlcnitm.hxx" + +#include <svx/svxids.hrc> +#include <svx/xtable.hxx> // fuer RGB_Color() +#include "svditext.hxx" +#include <svx/svdmodel.hxx> // fuer DEGREE_CHAR +#include <svx/svdtrans.hxx> +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" +#include <svx/sdgcpitm.hxx> +#include <editeng/adjitem.hxx> +#include <svx/sdtfchim.hxx> +#include <editeng/writingmodeitem.hxx> +#include <tools/bigint.hxx> +#include <tools/stream.hxx> + +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/svx3ditems.hxx> + +#define ITEMID_BOX SDRATTR_TABLE_BORDER +#define ITEMID_BOXINFO SDRATTR_TABLE_BORDER_INNER +#include "editeng/boxitem.hxx" + +#define ITEMID_SHADOW SDRATTR_TABLE_BORDER_SHADOW +#include "editeng/shaditem.hxx" + +#define ITEMID_LINE 0 +#include "editeng/bolnitem.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star; + +/************************************************************************* +|* +|* Konstruktor +|* +\************************************************************************/ + +SdrItemPool::SdrItemPool( + SfxItemPool* _pMaster, + sal_Bool bLoadRefCounts) +: XOutdevItemPool(_pMaster, SDRATTR_START, SDRATTR_END, bLoadRefCounts) +{ + // preapare some constants + const Color aNullCol(RGB_Color(COL_BLACK)); + const XubString aEmptyStr; + const sal_Int32 nDefEdgeDist(500L); // Erstmal hart defaulted fuer Draw (100TH_MM). hier muss noch der MapMode beruecksichtigt werden. + + // init the non-persistent items + for(sal_uInt16 i(SDRATTR_NOTPERSIST_FIRST); i <= SDRATTR_NOTPERSIST_LAST; i++) + { + mpLocalItemInfos[i - SDRATTR_START]._nFlags=0; + } + + // init own PoolDefaults + mppLocalPoolDefaults[SDRATTR_SHADOW -SDRATTR_START]=new SdrShadowItem; + mppLocalPoolDefaults[SDRATTR_SHADOWCOLOR -SDRATTR_START]=new SdrShadowColorItem(aEmptyStr,aNullCol); + mppLocalPoolDefaults[SDRATTR_SHADOWXDIST -SDRATTR_START]=new SdrShadowXDistItem; + mppLocalPoolDefaults[SDRATTR_SHADOWYDIST -SDRATTR_START]=new SdrShadowYDistItem; + mppLocalPoolDefaults[SDRATTR_SHADOWTRANSPARENCE-SDRATTR_START]=new SdrShadowTransparenceItem; + mppLocalPoolDefaults[SDRATTR_SHADOW3D -SDRATTR_START]=new SfxVoidItem(SDRATTR_SHADOW3D ); + mppLocalPoolDefaults[SDRATTR_SHADOWPERSP -SDRATTR_START]=new SfxVoidItem(SDRATTR_SHADOWPERSP ); + mppLocalPoolDefaults[SDRATTR_CAPTIONTYPE -SDRATTR_START]=new SdrCaptionTypeItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONFIXEDANGLE-SDRATTR_START]=new SdrCaptionFixedAngleItem; + mppLocalPoolDefaults[SDRATTR_CAPTIONANGLE -SDRATTR_START]=new SdrCaptionAngleItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONGAP -SDRATTR_START]=new SdrCaptionGapItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONESCDIR -SDRATTR_START]=new SdrCaptionEscDirItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONESCISREL -SDRATTR_START]=new SdrCaptionEscIsRelItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONESCREL -SDRATTR_START]=new SdrCaptionEscRelItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONESCABS -SDRATTR_START]=new SdrCaptionEscAbsItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONLINELEN -SDRATTR_START]=new SdrCaptionLineLenItem ; + mppLocalPoolDefaults[SDRATTR_CAPTIONFITLINELEN-SDRATTR_START]=new SdrCaptionFitLineLenItem; + mppLocalPoolDefaults[SDRATTR_ECKENRADIUS -SDRATTR_START]=new SdrEckenradiusItem; + mppLocalPoolDefaults[SDRATTR_TEXT_MINFRAMEHEIGHT -SDRATTR_START]=new SdrTextMinFrameHeightItem; + mppLocalPoolDefaults[SDRATTR_TEXT_AUTOGROWHEIGHT -SDRATTR_START]=new SdrTextAutoGrowHeightItem; + mppLocalPoolDefaults[SDRATTR_TEXT_FITTOSIZE -SDRATTR_START]=new SdrTextFitToSizeTypeItem; + mppLocalPoolDefaults[SDRATTR_TEXT_LEFTDIST -SDRATTR_START]=new SdrTextLeftDistItem; + mppLocalPoolDefaults[SDRATTR_TEXT_RIGHTDIST -SDRATTR_START]=new SdrTextRightDistItem; + mppLocalPoolDefaults[SDRATTR_TEXT_UPPERDIST -SDRATTR_START]=new SdrTextUpperDistItem; + mppLocalPoolDefaults[SDRATTR_TEXT_LOWERDIST -SDRATTR_START]=new SdrTextLowerDistItem; + mppLocalPoolDefaults[SDRATTR_TEXT_VERTADJUST -SDRATTR_START]=new SdrTextVertAdjustItem; + mppLocalPoolDefaults[SDRATTR_TEXT_MAXFRAMEHEIGHT -SDRATTR_START]=new SdrTextMaxFrameHeightItem; + mppLocalPoolDefaults[SDRATTR_TEXT_MINFRAMEWIDTH -SDRATTR_START]=new SdrTextMinFrameWidthItem; + mppLocalPoolDefaults[SDRATTR_TEXT_MAXFRAMEWIDTH -SDRATTR_START]=new SdrTextMaxFrameWidthItem; + mppLocalPoolDefaults[SDRATTR_TEXT_AUTOGROWWIDTH -SDRATTR_START]=new SdrTextAutoGrowWidthItem; + mppLocalPoolDefaults[SDRATTR_TEXT_HORZADJUST -SDRATTR_START]=new SdrTextHorzAdjustItem; + mppLocalPoolDefaults[SDRATTR_TEXT_ANIKIND -SDRATTR_START]=new SdrTextAniKindItem; + mppLocalPoolDefaults[SDRATTR_TEXT_ANIDIRECTION -SDRATTR_START]=new SdrTextAniDirectionItem; + mppLocalPoolDefaults[SDRATTR_TEXT_ANISTARTINSIDE -SDRATTR_START]=new SdrTextAniStartInsideItem; + mppLocalPoolDefaults[SDRATTR_TEXT_ANISTOPINSIDE -SDRATTR_START]=new SdrTextAniStopInsideItem; + mppLocalPoolDefaults[SDRATTR_TEXT_ANICOUNT -SDRATTR_START]=new SdrTextAniCountItem; + mppLocalPoolDefaults[SDRATTR_TEXT_ANIDELAY -SDRATTR_START]=new SdrTextAniDelayItem; + mppLocalPoolDefaults[SDRATTR_TEXT_ANIAMOUNT -SDRATTR_START]=new SdrTextAniAmountItem; + mppLocalPoolDefaults[SDRATTR_TEXT_CONTOURFRAME -SDRATTR_START]=new SdrTextContourFrameItem; + mppLocalPoolDefaults[SDRATTR_CUSTOMSHAPE_ADJUSTMENT -SDRATTR_START]=new SdrCustomShapeAdjustmentItem; + mppLocalPoolDefaults[SDRATTR_XMLATTRIBUTES -SDRATTR_START]=new SvXMLAttrContainerItem( SDRATTR_XMLATTRIBUTES ); + mppLocalPoolDefaults[SDRATTR_TEXT_USEFIXEDCELLHEIGHT -SDRATTR_START]=new SdrTextFixedCellHeightItem; + mppLocalPoolDefaults[SDRATTR_TEXT_WORDWRAP -SDRATTR_START]=new SdrTextWordWrapItem; + mppLocalPoolDefaults[SDRATTR_TEXT_AUTOGROWSIZE -SDRATTR_START]=new SdrTextAutoGrowSizeItem; + mppLocalPoolDefaults[SDRATTR_EDGEKIND -SDRATTR_START]=new SdrEdgeKindItem; + mppLocalPoolDefaults[SDRATTR_EDGENODE1HORZDIST-SDRATTR_START]=new SdrEdgeNode1HorzDistItem(nDefEdgeDist); + mppLocalPoolDefaults[SDRATTR_EDGENODE1VERTDIST-SDRATTR_START]=new SdrEdgeNode1VertDistItem(nDefEdgeDist); + mppLocalPoolDefaults[SDRATTR_EDGENODE2HORZDIST-SDRATTR_START]=new SdrEdgeNode2HorzDistItem(nDefEdgeDist); + mppLocalPoolDefaults[SDRATTR_EDGENODE2VERTDIST-SDRATTR_START]=new SdrEdgeNode2VertDistItem(nDefEdgeDist); + mppLocalPoolDefaults[SDRATTR_EDGENODE1GLUEDIST-SDRATTR_START]=new SdrEdgeNode1GlueDistItem; + mppLocalPoolDefaults[SDRATTR_EDGENODE2GLUEDIST-SDRATTR_START]=new SdrEdgeNode2GlueDistItem; + mppLocalPoolDefaults[SDRATTR_EDGELINEDELTAANZ -SDRATTR_START]=new SdrEdgeLineDeltaAnzItem; + mppLocalPoolDefaults[SDRATTR_EDGELINE1DELTA -SDRATTR_START]=new SdrEdgeLine1DeltaItem; + mppLocalPoolDefaults[SDRATTR_EDGELINE2DELTA -SDRATTR_START]=new SdrEdgeLine2DeltaItem; + mppLocalPoolDefaults[SDRATTR_EDGELINE3DELTA -SDRATTR_START]=new SdrEdgeLine3DeltaItem; + mppLocalPoolDefaults[SDRATTR_MEASUREKIND -SDRATTR_START]=new SdrMeasureKindItem; + mppLocalPoolDefaults[SDRATTR_MEASURETEXTHPOS -SDRATTR_START]=new SdrMeasureTextHPosItem; + mppLocalPoolDefaults[SDRATTR_MEASURETEXTVPOS -SDRATTR_START]=new SdrMeasureTextVPosItem; + mppLocalPoolDefaults[SDRATTR_MEASURELINEDIST -SDRATTR_START]=new SdrMeasureLineDistItem(800); + mppLocalPoolDefaults[SDRATTR_MEASUREHELPLINEOVERHANG -SDRATTR_START]=new SdrMeasureHelplineOverhangItem(200); + mppLocalPoolDefaults[SDRATTR_MEASUREHELPLINEDIST -SDRATTR_START]=new SdrMeasureHelplineDistItem(100); + mppLocalPoolDefaults[SDRATTR_MEASUREHELPLINE1LEN -SDRATTR_START]=new SdrMeasureHelpline1LenItem; + mppLocalPoolDefaults[SDRATTR_MEASUREHELPLINE2LEN -SDRATTR_START]=new SdrMeasureHelpline2LenItem; + mppLocalPoolDefaults[SDRATTR_MEASUREBELOWREFEDGE -SDRATTR_START]=new SdrMeasureBelowRefEdgeItem; + mppLocalPoolDefaults[SDRATTR_MEASURETEXTROTA90 -SDRATTR_START]=new SdrMeasureTextRota90Item; + mppLocalPoolDefaults[SDRATTR_MEASURETEXTUPSIDEDOWN -SDRATTR_START]=new SdrMeasureTextUpsideDownItem; + mppLocalPoolDefaults[SDRATTR_MEASUREOVERHANG -SDRATTR_START]=new SdrMeasureOverhangItem(600); + mppLocalPoolDefaults[SDRATTR_MEASUREUNIT -SDRATTR_START]=new SdrMeasureUnitItem; + mppLocalPoolDefaults[SDRATTR_MEASURESCALE -SDRATTR_START]=new SdrMeasureScaleItem; + mppLocalPoolDefaults[SDRATTR_MEASURESHOWUNIT -SDRATTR_START]=new SdrMeasureShowUnitItem; + mppLocalPoolDefaults[SDRATTR_MEASUREFORMATSTRING -SDRATTR_START]=new SdrMeasureFormatStringItem(); + mppLocalPoolDefaults[SDRATTR_MEASURETEXTAUTOANGLE -SDRATTR_START]=new SdrMeasureTextAutoAngleItem(); + mppLocalPoolDefaults[SDRATTR_MEASURETEXTAUTOANGLEVIEW-SDRATTR_START]=new SdrMeasureTextAutoAngleViewItem(); + mppLocalPoolDefaults[SDRATTR_MEASURETEXTISFIXEDANGLE -SDRATTR_START]=new SdrMeasureTextIsFixedAngleItem(); + mppLocalPoolDefaults[SDRATTR_MEASURETEXTFIXEDANGLE -SDRATTR_START]=new SdrMeasureTextFixedAngleItem(); + mppLocalPoolDefaults[SDRATTR_MEASUREDECIMALPLACES -SDRATTR_START]=new SdrMeasureDecimalPlacesItem(); + mppLocalPoolDefaults[SDRATTR_CIRCKIND -SDRATTR_START]=new SdrCircKindItem; + mppLocalPoolDefaults[SDRATTR_CIRCSTARTANGLE-SDRATTR_START]=new SdrCircStartAngleItem; + mppLocalPoolDefaults[SDRATTR_CIRCENDANGLE -SDRATTR_START]=new SdrCircEndAngleItem; + mppLocalPoolDefaults[SDRATTR_OBJMOVEPROTECT -SDRATTR_START]=new SdrObjMoveProtectItem; + mppLocalPoolDefaults[SDRATTR_OBJSIZEPROTECT -SDRATTR_START]=new SdrObjSizeProtectItem; + mppLocalPoolDefaults[SDRATTR_OBJPRINTABLE -SDRATTR_START]=new SdrObjPrintableItem; + mppLocalPoolDefaults[SDRATTR_OBJVISIBLE -SDRATTR_START]=new SdrObjVisibleItem; + mppLocalPoolDefaults[SDRATTR_LAYERID -SDRATTR_START]=new SdrLayerIdItem; + mppLocalPoolDefaults[SDRATTR_LAYERNAME -SDRATTR_START]=new SdrLayerNameItem; + mppLocalPoolDefaults[SDRATTR_OBJECTNAME -SDRATTR_START]=new SdrObjectNameItem; + mppLocalPoolDefaults[SDRATTR_ALLPOSITIONX -SDRATTR_START]=new SdrAllPositionXItem; + mppLocalPoolDefaults[SDRATTR_ALLPOSITIONY -SDRATTR_START]=new SdrAllPositionYItem; + mppLocalPoolDefaults[SDRATTR_ALLSIZEWIDTH -SDRATTR_START]=new SdrAllSizeWidthItem; + mppLocalPoolDefaults[SDRATTR_ALLSIZEHEIGHT -SDRATTR_START]=new SdrAllSizeHeightItem; + mppLocalPoolDefaults[SDRATTR_ONEPOSITIONX -SDRATTR_START]=new SdrOnePositionXItem; + mppLocalPoolDefaults[SDRATTR_ONEPOSITIONY -SDRATTR_START]=new SdrOnePositionYItem; + mppLocalPoolDefaults[SDRATTR_ONESIZEWIDTH -SDRATTR_START]=new SdrOneSizeWidthItem; + mppLocalPoolDefaults[SDRATTR_ONESIZEHEIGHT -SDRATTR_START]=new SdrOneSizeHeightItem; + mppLocalPoolDefaults[SDRATTR_LOGICSIZEWIDTH -SDRATTR_START]=new SdrLogicSizeWidthItem; + mppLocalPoolDefaults[SDRATTR_LOGICSIZEHEIGHT-SDRATTR_START]=new SdrLogicSizeHeightItem; + mppLocalPoolDefaults[SDRATTR_ROTATEANGLE -SDRATTR_START]=new SdrRotateAngleItem; + mppLocalPoolDefaults[SDRATTR_SHEARANGLE -SDRATTR_START]=new SdrShearAngleItem; + mppLocalPoolDefaults[SDRATTR_MOVEX -SDRATTR_START]=new SdrMoveXItem; + mppLocalPoolDefaults[SDRATTR_MOVEY -SDRATTR_START]=new SdrMoveYItem; + mppLocalPoolDefaults[SDRATTR_RESIZEXONE -SDRATTR_START]=new SdrResizeXOneItem; + mppLocalPoolDefaults[SDRATTR_RESIZEYONE -SDRATTR_START]=new SdrResizeYOneItem; + mppLocalPoolDefaults[SDRATTR_ROTATEONE -SDRATTR_START]=new SdrRotateOneItem; + mppLocalPoolDefaults[SDRATTR_HORZSHEARONE -SDRATTR_START]=new SdrHorzShearOneItem; + mppLocalPoolDefaults[SDRATTR_VERTSHEARONE -SDRATTR_START]=new SdrVertShearOneItem; + mppLocalPoolDefaults[SDRATTR_RESIZEXALL -SDRATTR_START]=new SdrResizeXAllItem; + mppLocalPoolDefaults[SDRATTR_RESIZEYALL -SDRATTR_START]=new SdrResizeYAllItem; + mppLocalPoolDefaults[SDRATTR_ROTATEALL -SDRATTR_START]=new SdrRotateAllItem; + mppLocalPoolDefaults[SDRATTR_HORZSHEARALL -SDRATTR_START]=new SdrHorzShearAllItem; + mppLocalPoolDefaults[SDRATTR_VERTSHEARALL -SDRATTR_START]=new SdrVertShearAllItem; + mppLocalPoolDefaults[SDRATTR_TRANSFORMREF1X -SDRATTR_START]=new SdrTransformRef1XItem; + mppLocalPoolDefaults[SDRATTR_TRANSFORMREF1Y -SDRATTR_START]=new SdrTransformRef1YItem; + mppLocalPoolDefaults[SDRATTR_TRANSFORMREF2X -SDRATTR_START]=new SdrTransformRef2XItem; + mppLocalPoolDefaults[SDRATTR_TRANSFORMREF2Y -SDRATTR_START]=new SdrTransformRef2YItem; + mppLocalPoolDefaults[SDRATTR_TEXTDIRECTION -SDRATTR_START]=new SvxWritingModeItem(com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION); + mppLocalPoolDefaults[ SDRATTR_GRAFRED - SDRATTR_START] = new SdrGrafRedItem; + mppLocalPoolDefaults[ SDRATTR_GRAFGREEN - SDRATTR_START] = new SdrGrafGreenItem; + mppLocalPoolDefaults[ SDRATTR_GRAFBLUE - SDRATTR_START] = new SdrGrafBlueItem; + mppLocalPoolDefaults[ SDRATTR_GRAFLUMINANCE - SDRATTR_START] = new SdrGrafLuminanceItem; + mppLocalPoolDefaults[ SDRATTR_GRAFCONTRAST - SDRATTR_START] = new SdrGrafContrastItem; + mppLocalPoolDefaults[ SDRATTR_GRAFGAMMA - SDRATTR_START] = new SdrGrafGamma100Item; + mppLocalPoolDefaults[ SDRATTR_GRAFTRANSPARENCE - SDRATTR_START] = new SdrGrafTransparenceItem; + mppLocalPoolDefaults[ SDRATTR_GRAFINVERT - SDRATTR_START] = new SdrGrafInvertItem; + mppLocalPoolDefaults[ SDRATTR_GRAFMODE - SDRATTR_START] = new SdrGrafModeItem; + mppLocalPoolDefaults[ SDRATTR_GRAFCROP - SDRATTR_START] = new SdrGrafCropItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_PERCENT_DIAGONAL - SDRATTR_START ] = new Svx3DPercentDiagonalItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_BACKSCALE - SDRATTR_START ] = new Svx3DBackscaleItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_DEPTH - SDRATTR_START ] = new Svx3DDepthItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_HORZ_SEGS - SDRATTR_START ] = new Svx3DHorizontalSegmentsItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_VERT_SEGS - SDRATTR_START ] = new Svx3DVerticalSegmentsItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_END_ANGLE - SDRATTR_START ] = new Svx3DEndAngleItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_DOUBLE_SIDED - SDRATTR_START ] = new Svx3DDoubleSidedItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_NORMALS_KIND - SDRATTR_START ] = new Svx3DNormalsKindItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_NORMALS_INVERT - SDRATTR_START ] = new Svx3DNormalsInvertItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_TEXTURE_PROJ_X - SDRATTR_START ] = new Svx3DTextureProjectionXItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_TEXTURE_PROJ_Y - SDRATTR_START ] = new Svx3DTextureProjectionYItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_SHADOW_3D - SDRATTR_START ] = new Svx3DShadow3DItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_MAT_COLOR - SDRATTR_START ] = new Svx3DMaterialColorItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_MAT_EMISSION - SDRATTR_START ] = new Svx3DMaterialEmissionItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_MAT_SPECULAR - SDRATTR_START ] = new Svx3DMaterialSpecularItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_MAT_SPECULAR_INTENSITY - SDRATTR_START ] = new Svx3DMaterialSpecularIntensityItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_TEXTURE_KIND - SDRATTR_START ] = new Svx3DTextureKindItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_TEXTURE_MODE - SDRATTR_START ] = new Svx3DTextureModeItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_TEXTURE_FILTER - SDRATTR_START ] = new Svx3DTextureFilterItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_SMOOTH_NORMALS - SDRATTR_START ] = new Svx3DSmoothNormalsItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_SMOOTH_LIDS - SDRATTR_START ] = new Svx3DSmoothLidsItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_CHARACTER_MODE - SDRATTR_START ] = new Svx3DCharacterModeItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_CLOSE_FRONT - SDRATTR_START ] = new Svx3DCloseFrontItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_CLOSE_BACK - SDRATTR_START ] = new Svx3DCloseBackItem; + mppLocalPoolDefaults[ SDRATTR_3DOBJ_REDUCED_LINE_GEOMETRY - SDRATTR_START ] = new Svx3DReducedLineGeometryItem; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_PERSPECTIVE - SDRATTR_START ] = new Svx3DPerspectiveItem; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_DISTANCE - SDRATTR_START ] = new Svx3DDistanceItem; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_FOCAL_LENGTH - SDRATTR_START ] = new Svx3DFocalLengthItem; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_TWO_SIDED_LIGHTING - SDRATTR_START ] = new Svx3DTwoSidedLightingItem; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_1 - SDRATTR_START ] = new Svx3DLightcolor1Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_2 - SDRATTR_START ] = new Svx3DLightcolor2Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_3 - SDRATTR_START ] = new Svx3DLightcolor3Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_4 - SDRATTR_START ] = new Svx3DLightcolor4Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_5 - SDRATTR_START ] = new Svx3DLightcolor5Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_6 - SDRATTR_START ] = new Svx3DLightcolor6Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_7 - SDRATTR_START ] = new Svx3DLightcolor7Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTCOLOR_8 - SDRATTR_START ] = new Svx3DLightcolor8Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_AMBIENTCOLOR - SDRATTR_START ] = new Svx3DAmbientcolorItem; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_1 - SDRATTR_START ] = new Svx3DLightOnOff1Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_2 - SDRATTR_START ] = new Svx3DLightOnOff2Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_3 - SDRATTR_START ] = new Svx3DLightOnOff3Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_4 - SDRATTR_START ] = new Svx3DLightOnOff4Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_5 - SDRATTR_START ] = new Svx3DLightOnOff5Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_6 - SDRATTR_START ] = new Svx3DLightOnOff6Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_7 - SDRATTR_START ] = new Svx3DLightOnOff7Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTON_8 - SDRATTR_START ] = new Svx3DLightOnOff8Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_1 - SDRATTR_START ] = new Svx3DLightDirection1Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_2 - SDRATTR_START ] = new Svx3DLightDirection2Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_3 - SDRATTR_START ] = new Svx3DLightDirection3Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_4 - SDRATTR_START ] = new Svx3DLightDirection4Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_5 - SDRATTR_START ] = new Svx3DLightDirection5Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_6 - SDRATTR_START ] = new Svx3DLightDirection6Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_7 - SDRATTR_START ] = new Svx3DLightDirection7Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_LIGHTDIRECTION_8 - SDRATTR_START ] = new Svx3DLightDirection8Item; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_SHADOW_SLANT - SDRATTR_START ] = new Svx3DShadowSlantItem; + mppLocalPoolDefaults[ SDRATTR_3DSCENE_SHADE_MODE - SDRATTR_START ] = new Svx3DShadeModeItem; + mppLocalPoolDefaults[ SDRATTR_CUSTOMSHAPE_ENGINE - SDRATTR_START ] = new SdrCustomShapeEngineItem; + mppLocalPoolDefaults[ SDRATTR_CUSTOMSHAPE_DATA - SDRATTR_START ] = new SdrCustomShapeDataItem; + mppLocalPoolDefaults[ SDRATTR_CUSTOMSHAPE_GEOMETRY - SDRATTR_START ] = new SdrCustomShapeGeometryItem; + mppLocalPoolDefaults[ SDRATTR_CUSTOMSHAPE_REPLACEMENT_URL - SDRATTR_START ] = new SdrCustomShapeReplacementURLItem; + + SvxBoxItem* pboxItem = new SvxBoxItem( SDRATTR_TABLE_BORDER ); + pboxItem->SetDistance( 100 ); + mppLocalPoolDefaults[ SDRATTR_TABLE_BORDER - SDRATTR_START ] = pboxItem; + + SvxBoxInfoItem* pBoxInfoItem = new SvxBoxInfoItem( SDRATTR_TABLE_BORDER_INNER ); + + pBoxInfoItem->SetTable( TRUE ); + pBoxInfoItem->SetDist( TRUE); // Abstandsfeld immer anzeigen +// pBoxInfoItem->SetMinDist( TRUE );// Minimalgroesse in Tabellen und Absaetzen setzen +// pBoxInfoItem->SetDefDist( MIN_BORDER_DIST );// Default-Abstand immer setzen + pBoxInfoItem->SetValid( VALID_DISABLE, TRUE ); // Einzelne Linien koennen nur in Tabellen DontCare-Status haben + + mppLocalPoolDefaults[ SDRATTR_TABLE_BORDER_INNER - SDRATTR_START ] = pBoxInfoItem; +// mppLocalPoolDefaults[ SDRATTR_TABLE_BORDER_SHADOW - SDRATTR_START ] = new SvxShadowItem( SDRATTR_TABLE_BORDER_SHADOW ); + mppLocalPoolDefaults[ SDRATTR_TABLE_BORDER_TLBR - SDRATTR_START ] = new SvxLineItem( SDRATTR_TABLE_BORDER_TLBR ); + mppLocalPoolDefaults[ SDRATTR_TABLE_BORDER_BLTR - SDRATTR_START ] = new SvxLineItem( SDRATTR_TABLE_BORDER_BLTR ); + + // set own ItemInfos + mpLocalItemInfos[SDRATTR_SHADOW-SDRATTR_START]._nSID=SID_ATTR_FILL_SHADOW; + mpLocalItemInfos[SDRATTR_TEXT_FITTOSIZE-SDRATTR_START]._nSID=SID_ATTR_TEXT_FITTOSIZE; + mpLocalItemInfos[SDRATTR_GRAFCROP-SDRATTR_START]._nSID=SID_ATTR_GRAF_CROP; + + mpLocalItemInfos[SDRATTR_TABLE_BORDER - SDRATTR_START ]._nSID = SID_ATTR_BORDER_OUTER; + mpLocalItemInfos[SDRATTR_TABLE_BORDER_INNER - SDRATTR_START ]._nSID = SID_ATTR_BORDER_INNER; +// mpLocalItemInfos[SDRATTR_TABLE_BORDER_SHADOW - SDRATTR_START ]._nSID = SID_ATTR_BORDER_SHADOW; + mpLocalItemInfos[SDRATTR_TABLE_BORDER_TLBR - SDRATTR_START ]._nSID = SID_ATTR_BORDER_DIAG_TLBR; + mpLocalItemInfos[SDRATTR_TABLE_BORDER_BLTR - SDRATTR_START ]._nSID = SID_ATTR_BORDER_DIAG_BLTR; + + // it's my own creation level, set Defaults and ItemInfos + SetDefaults(mppLocalPoolDefaults); + SetItemInfos(mpLocalItemInfos); +} + +/************************************************************************* +|* +|* copy ctor, sorgt dafuer, dass die static defaults gecloned werden +|* (Parameter 2 = TRUE) +|* +\************************************************************************/ + +SdrItemPool::SdrItemPool(const SdrItemPool& rPool) +: XOutdevItemPool(rPool) +{ +} + +/************************************************************************* +|* +|* Clone() +|* +\************************************************************************/ + +SfxItemPool* __EXPORT SdrItemPool::Clone() const +{ + return new SdrItemPool(*this); +} + +/************************************************************************* +|* +|* Destruktor +|* +\************************************************************************/ + +SdrItemPool::~SdrItemPool() +{ + // dtor of SfxItemPool + Delete(); + + // clear own static Defaults + if(mppLocalPoolDefaults) + { + const sal_uInt16 nBeg(SDRATTR_SHADOW_FIRST - SDRATTR_START); + const sal_uInt16 nEnd2(SDRATTR_END - SDRATTR_START); + + for(sal_uInt16 i(nBeg); i <= nEnd2; i++) + { + SetRefCount(*mppLocalPoolDefaults[i],0); + delete mppLocalPoolDefaults[i]; + mppLocalPoolDefaults[i] = 0L; + } + } + + // split pools before detroying + SetSecondaryPool(NULL); +} + +SfxItemPresentation __EXPORT SdrItemPool::GetPresentation( + const SfxPoolItem& rItem, SfxItemPresentation ePresentation, + SfxMapUnit ePresentationMetric, XubString& rText, + const IntlWrapper * pIntlWrapper) const +{ + if (!IsInvalidItem(&rItem)) { + USHORT nWhich=rItem.Which(); + if (nWhich>=SDRATTR_SHADOW_FIRST && nWhich<=SDRATTR_END) { + rItem.GetPresentation(SFX_ITEM_PRESENTATION_NAMELESS, + GetMetric(nWhich),ePresentationMetric,rText, + pIntlWrapper); + String aStr; + + TakeItemName(nWhich, aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + + return ePresentation; + } + } + return XOutdevItemPool::GetPresentation(rItem,ePresentation,ePresentationMetric,rText,pIntlWrapper); +} + +void SdrItemPool::TakeItemName(sal_uInt16 nWhich, String& rItemName) +{ + ResMgr* pResMgr = ImpGetResMgr(); + USHORT nResId = SIP_UNKNOWN_ATTR; + + switch (nWhich) + { + case XATTR_LINESTYLE : nResId = SIP_XA_LINESTYLE;break; + case XATTR_LINEDASH : nResId = SIP_XA_LINEDASH;break; + case XATTR_LINEWIDTH : nResId = SIP_XA_LINEWIDTH;break; + case XATTR_LINECOLOR : nResId = SIP_XA_LINECOLOR;break; + case XATTR_LINESTART : nResId = SIP_XA_LINESTART;break; + case XATTR_LINEEND : nResId = SIP_XA_LINEEND;break; + case XATTR_LINESTARTWIDTH : nResId = SIP_XA_LINESTARTWIDTH;break; + case XATTR_LINEENDWIDTH : nResId = SIP_XA_LINEENDWIDTH;break; + case XATTR_LINESTARTCENTER : nResId = SIP_XA_LINESTARTCENTER;break; + case XATTR_LINEENDCENTER : nResId = SIP_XA_LINEENDCENTER;break; + case XATTR_LINETRANSPARENCE : nResId = SIP_XA_LINETRANSPARENCE;break; + case XATTR_LINEJOINT : nResId = SIP_XA_LINEJOINT;break; + case XATTRSET_LINE : nResId = SIP_XATTRSET_LINE;break; + + case XATTR_FILLSTYLE : nResId = SIP_XA_FILLSTYLE;break; + case XATTR_FILLCOLOR : nResId = SIP_XA_FILLCOLOR;break; + case XATTR_FILLGRADIENT : nResId = SIP_XA_FILLGRADIENT;break; + case XATTR_FILLHATCH : nResId = SIP_XA_FILLHATCH;break; + case XATTR_FILLBITMAP : nResId = SIP_XA_FILLBITMAP;break; + case XATTR_FILLTRANSPARENCE : nResId = SIP_XA_FILLTRANSPARENCE;break; + case XATTR_GRADIENTSTEPCOUNT : nResId = SIP_XA_GRADIENTSTEPCOUNT;break; + case XATTR_FILLBMP_TILE : nResId = SIP_XA_FILLBMP_TILE;break; + case XATTR_FILLBMP_POS : nResId = SIP_XA_FILLBMP_POS;break; + case XATTR_FILLBMP_SIZEX : nResId = SIP_XA_FILLBMP_SIZEX;break; + case XATTR_FILLBMP_SIZEY : nResId = SIP_XA_FILLBMP_SIZEY;break; + case XATTR_FILLFLOATTRANSPARENCE: nResId = SIP_XA_FILLFLOATTRANSPARENCE;break; + case XATTR_SECONDARYFILLCOLOR : nResId = SIP_XA_SECONDARYFILLCOLOR;break; + case XATTR_FILLBMP_SIZELOG : nResId = SIP_XA_FILLBMP_SIZELOG;break; + case XATTR_FILLBMP_TILEOFFSETX : nResId = SIP_XA_FILLBMP_TILEOFFSETX;break; + case XATTR_FILLBMP_TILEOFFSETY : nResId = SIP_XA_FILLBMP_TILEOFFSETY;break; + case XATTR_FILLBMP_STRETCH : nResId = SIP_XA_FILLBMP_STRETCH;break; + case XATTR_FILLBMP_POSOFFSETX : nResId = SIP_XA_FILLBMP_POSOFFSETX;break; + case XATTR_FILLBMP_POSOFFSETY : nResId = SIP_XA_FILLBMP_POSOFFSETY;break; + case XATTR_FILLBACKGROUND : nResId = SIP_XA_FILLBACKGROUND;break; + + case XATTRSET_FILL : nResId = SIP_XATTRSET_FILL;break; + + case XATTR_FORMTXTSTYLE : nResId = SIP_XA_FORMTXTSTYLE;break; + case XATTR_FORMTXTADJUST : nResId = SIP_XA_FORMTXTADJUST;break; + case XATTR_FORMTXTDISTANCE : nResId = SIP_XA_FORMTXTDISTANCE;break; + case XATTR_FORMTXTSTART : nResId = SIP_XA_FORMTXTSTART;break; + case XATTR_FORMTXTMIRROR : nResId = SIP_XA_FORMTXTMIRROR;break; + case XATTR_FORMTXTOUTLINE : nResId = SIP_XA_FORMTXTOUTLINE;break; + case XATTR_FORMTXTSHADOW : nResId = SIP_XA_FORMTXTSHADOW;break; + case XATTR_FORMTXTSHDWCOLOR : nResId = SIP_XA_FORMTXTSHDWCOLOR;break; + case XATTR_FORMTXTSHDWXVAL : nResId = SIP_XA_FORMTXTSHDWXVAL;break; + case XATTR_FORMTXTSHDWYVAL : nResId = SIP_XA_FORMTXTSHDWYVAL;break; + case XATTR_FORMTXTSTDFORM : nResId = SIP_XA_FORMTXTSTDFORM;break; + case XATTR_FORMTXTHIDEFORM : nResId = SIP_XA_FORMTXTHIDEFORM;break; + case XATTR_FORMTXTSHDWTRANSP: nResId = SIP_XA_FORMTXTSHDWTRANSP;break; + + case SDRATTR_SHADOW : nResId = SIP_SA_SHADOW;break; + case SDRATTR_SHADOWCOLOR : nResId = SIP_SA_SHADOWCOLOR;break; + case SDRATTR_SHADOWXDIST : nResId = SIP_SA_SHADOWXDIST;break; + case SDRATTR_SHADOWYDIST : nResId = SIP_SA_SHADOWYDIST;break; + case SDRATTR_SHADOWTRANSPARENCE: nResId = SIP_SA_SHADOWTRANSPARENCE;break; + case SDRATTR_SHADOW3D : nResId = SIP_SA_SHADOW3D;break; + case SDRATTR_SHADOWPERSP : nResId = SIP_SA_SHADOWPERSP;break; + + case SDRATTR_CAPTIONTYPE : nResId = SIP_SA_CAPTIONTYPE;break; + case SDRATTR_CAPTIONFIXEDANGLE: nResId = SIP_SA_CAPTIONFIXEDANGLE;break; + case SDRATTR_CAPTIONANGLE : nResId = SIP_SA_CAPTIONANGLE;break; + case SDRATTR_CAPTIONGAP : nResId = SIP_SA_CAPTIONGAP;break; + case SDRATTR_CAPTIONESCDIR : nResId = SIP_SA_CAPTIONESCDIR;break; + case SDRATTR_CAPTIONESCISREL : nResId = SIP_SA_CAPTIONESCISREL;break; + case SDRATTR_CAPTIONESCREL : nResId = SIP_SA_CAPTIONESCREL;break; + case SDRATTR_CAPTIONESCABS : nResId = SIP_SA_CAPTIONESCABS;break; + case SDRATTR_CAPTIONLINELEN : nResId = SIP_SA_CAPTIONLINELEN;break; + case SDRATTR_CAPTIONFITLINELEN: nResId = SIP_SA_CAPTIONFITLINELEN;break; + + case SDRATTR_ECKENRADIUS : nResId = SIP_SA_ECKENRADIUS;break; + case SDRATTR_TEXT_MINFRAMEHEIGHT : nResId = SIP_SA_TEXT_MINFRAMEHEIGHT;break; + case SDRATTR_TEXT_AUTOGROWHEIGHT : nResId = SIP_SA_TEXT_AUTOGROWHEIGHT;break; + case SDRATTR_TEXT_FITTOSIZE : nResId = SIP_SA_TEXT_FITTOSIZE;break; + case SDRATTR_TEXT_LEFTDIST : nResId = SIP_SA_TEXT_LEFTDIST;break; + case SDRATTR_TEXT_RIGHTDIST : nResId = SIP_SA_TEXT_RIGHTDIST;break; + case SDRATTR_TEXT_UPPERDIST : nResId = SIP_SA_TEXT_UPPERDIST;break; + case SDRATTR_TEXT_LOWERDIST : nResId = SIP_SA_TEXT_LOWERDIST;break; + case SDRATTR_TEXT_VERTADJUST : nResId = SIP_SA_TEXT_VERTADJUST;break; + case SDRATTR_TEXT_MAXFRAMEHEIGHT : nResId = SIP_SA_TEXT_MAXFRAMEHEIGHT;break; + case SDRATTR_TEXT_MINFRAMEWIDTH : nResId = SIP_SA_TEXT_MINFRAMEWIDTH;break; + case SDRATTR_TEXT_MAXFRAMEWIDTH : nResId = SIP_SA_TEXT_MAXFRAMEWIDTH;break; + case SDRATTR_TEXT_AUTOGROWWIDTH : nResId = SIP_SA_TEXT_AUTOGROWWIDTH;break; + case SDRATTR_TEXT_HORZADJUST : nResId = SIP_SA_TEXT_HORZADJUST;break; + case SDRATTR_TEXT_ANIKIND : nResId = SIP_SA_TEXT_ANIKIND;break; + case SDRATTR_TEXT_ANIDIRECTION : nResId = SIP_SA_TEXT_ANIDIRECTION;break; + case SDRATTR_TEXT_ANISTARTINSIDE : nResId = SIP_SA_TEXT_ANISTARTINSIDE;break; + case SDRATTR_TEXT_ANISTOPINSIDE : nResId = SIP_SA_TEXT_ANISTOPINSIDE;break; + case SDRATTR_TEXT_ANICOUNT : nResId = SIP_SA_TEXT_ANICOUNT;break; + case SDRATTR_TEXT_ANIDELAY : nResId = SIP_SA_TEXT_ANIDELAY;break; + case SDRATTR_TEXT_ANIAMOUNT : nResId = SIP_SA_TEXT_ANIAMOUNT;break; + case SDRATTR_TEXT_CONTOURFRAME : nResId = SIP_SA_TEXT_CONTOURFRAME;break; + case SDRATTR_CUSTOMSHAPE_ADJUSTMENT : nResId = SIP_SA_CUSTOMSHAPE_ADJUSTMENT;break; + case SDRATTR_XMLATTRIBUTES : nResId = SIP_SA_XMLATTRIBUTES;break; + case SDRATTR_TEXT_USEFIXEDCELLHEIGHT: nResId = SIP_SA_TEXT_USEFIXEDCELLHEIGHT;break; + case SDRATTR_TEXT_WORDWRAP : nResId = SIP_SA_WORDWRAP;break; + case SDRATTR_TEXT_AUTOGROWSIZE : nResId = SIP_SA_AUTOGROWSIZE;break; + + case SDRATTR_EDGEKIND : nResId = SIP_SA_EDGEKIND;break; + case SDRATTR_EDGENODE1HORZDIST : nResId = SIP_SA_EDGENODE1HORZDIST;break; + case SDRATTR_EDGENODE1VERTDIST : nResId = SIP_SA_EDGENODE1VERTDIST;break; + case SDRATTR_EDGENODE2HORZDIST : nResId = SIP_SA_EDGENODE2HORZDIST;break; + case SDRATTR_EDGENODE2VERTDIST : nResId = SIP_SA_EDGENODE2VERTDIST;break; + case SDRATTR_EDGENODE1GLUEDIST : nResId = SIP_SA_EDGENODE1GLUEDIST;break; + case SDRATTR_EDGENODE2GLUEDIST : nResId = SIP_SA_EDGENODE2GLUEDIST;break; + case SDRATTR_EDGELINEDELTAANZ : nResId = SIP_SA_EDGELINEDELTAANZ;break; + case SDRATTR_EDGELINE1DELTA : nResId = SIP_SA_EDGELINE1DELTA;break; + case SDRATTR_EDGELINE2DELTA : nResId = SIP_SA_EDGELINE2DELTA;break; + case SDRATTR_EDGELINE3DELTA : nResId = SIP_SA_EDGELINE3DELTA;break; + + case SDRATTR_MEASUREKIND : nResId = SIP_SA_MEASUREKIND;break; + case SDRATTR_MEASURETEXTHPOS : nResId = SIP_SA_MEASURETEXTHPOS;break; + case SDRATTR_MEASURETEXTVPOS : nResId = SIP_SA_MEASURETEXTVPOS;break; + case SDRATTR_MEASURELINEDIST : nResId = SIP_SA_MEASURELINEDIST;break; + case SDRATTR_MEASUREHELPLINEOVERHANG : nResId = SIP_SA_MEASUREHELPLINEOVERHANG;break; + case SDRATTR_MEASUREHELPLINEDIST : nResId = SIP_SA_MEASUREHELPLINEDIST;break; + case SDRATTR_MEASUREHELPLINE1LEN : nResId = SIP_SA_MEASUREHELPLINE1LEN;break; + case SDRATTR_MEASUREHELPLINE2LEN : nResId = SIP_SA_MEASUREHELPLINE2LEN;break; + case SDRATTR_MEASUREBELOWREFEDGE : nResId = SIP_SA_MEASUREBELOWREFEDGE;break; + case SDRATTR_MEASURETEXTROTA90 : nResId = SIP_SA_MEASURETEXTROTA90;break; + case SDRATTR_MEASURETEXTUPSIDEDOWN : nResId = SIP_SA_MEASURETEXTUPSIDEDOWN;break; + case SDRATTR_MEASUREOVERHANG : nResId = SIP_SA_MEASUREOVERHANG;break; + case SDRATTR_MEASUREUNIT : nResId = SIP_SA_MEASUREUNIT;break; + case SDRATTR_MEASURESCALE : nResId = SIP_SA_MEASURESCALE;break; + case SDRATTR_MEASURESHOWUNIT : nResId = SIP_SA_MEASURESHOWUNIT;break; + case SDRATTR_MEASUREFORMATSTRING : nResId = SIP_SA_MEASUREFORMATSTRING;break; + case SDRATTR_MEASURETEXTAUTOANGLE : nResId = SIP_SA_MEASURETEXTAUTOANGLE;break; + case SDRATTR_MEASURETEXTAUTOANGLEVIEW: nResId = SIP_SA_MEASURETEXTAUTOANGLEVIEW;break; + case SDRATTR_MEASURETEXTISFIXEDANGLE : nResId = SIP_SA_MEASURETEXTISFIXEDANGLE;break; + case SDRATTR_MEASURETEXTFIXEDANGLE : nResId = SIP_SA_MEASURETEXTFIXEDANGLE;break; + case SDRATTR_MEASUREDECIMALPLACES : nResId = SIP_SA_MEASUREDECIMALPLACES;break; + + case SDRATTR_CIRCKIND : nResId = SIP_SA_CIRCKIND;break; + case SDRATTR_CIRCSTARTANGLE: nResId = SIP_SA_CIRCSTARTANGLE;break; + case SDRATTR_CIRCENDANGLE : nResId = SIP_SA_CIRCENDANGLE;break; + + case SDRATTR_OBJMOVEPROTECT : nResId = SIP_SA_OBJMOVEPROTECT;break; + case SDRATTR_OBJSIZEPROTECT : nResId = SIP_SA_OBJSIZEPROTECT;break; + case SDRATTR_OBJPRINTABLE : nResId = SIP_SA_OBJPRINTABLE;break; + case SDRATTR_OBJVISIBLE : nResId = SIP_SA_OBJVISIBLE;break; + case SDRATTR_LAYERID : nResId = SIP_SA_LAYERID;break; + case SDRATTR_LAYERNAME : nResId = SIP_SA_LAYERNAME;break; + case SDRATTR_OBJECTNAME : nResId = SIP_SA_OBJECTNAME;break; + case SDRATTR_ALLPOSITIONX : nResId = SIP_SA_ALLPOSITIONX;break; + case SDRATTR_ALLPOSITIONY : nResId = SIP_SA_ALLPOSITIONY;break; + case SDRATTR_ALLSIZEWIDTH : nResId = SIP_SA_ALLSIZEWIDTH;break; + case SDRATTR_ALLSIZEHEIGHT : nResId = SIP_SA_ALLSIZEHEIGHT;break; + case SDRATTR_ONEPOSITIONX : nResId = SIP_SA_ONEPOSITIONX;break; + case SDRATTR_ONEPOSITIONY : nResId = SIP_SA_ONEPOSITIONY;break; + case SDRATTR_ONESIZEWIDTH : nResId = SIP_SA_ONESIZEWIDTH;break; + case SDRATTR_ONESIZEHEIGHT : nResId = SIP_SA_ONESIZEHEIGHT;break; + case SDRATTR_LOGICSIZEWIDTH : nResId = SIP_SA_LOGICSIZEWIDTH;break; + case SDRATTR_LOGICSIZEHEIGHT: nResId = SIP_SA_LOGICSIZEHEIGHT;break; + case SDRATTR_ROTATEANGLE : nResId = SIP_SA_ROTATEANGLE;break; + case SDRATTR_SHEARANGLE : nResId = SIP_SA_SHEARANGLE;break; + case SDRATTR_MOVEX : nResId = SIP_SA_MOVEX;break; + case SDRATTR_MOVEY : nResId = SIP_SA_MOVEY;break; + case SDRATTR_RESIZEXONE : nResId = SIP_SA_RESIZEXONE;break; + case SDRATTR_RESIZEYONE : nResId = SIP_SA_RESIZEYONE;break; + case SDRATTR_ROTATEONE : nResId = SIP_SA_ROTATEONE;break; + case SDRATTR_HORZSHEARONE : nResId = SIP_SA_HORZSHEARONE;break; + case SDRATTR_VERTSHEARONE : nResId = SIP_SA_VERTSHEARONE;break; + case SDRATTR_RESIZEXALL : nResId = SIP_SA_RESIZEXALL;break; + case SDRATTR_RESIZEYALL : nResId = SIP_SA_RESIZEYALL;break; + case SDRATTR_ROTATEALL : nResId = SIP_SA_ROTATEALL;break; + case SDRATTR_HORZSHEARALL : nResId = SIP_SA_HORZSHEARALL;break; + case SDRATTR_VERTSHEARALL : nResId = SIP_SA_VERTSHEARALL;break; + case SDRATTR_TRANSFORMREF1X : nResId = SIP_SA_TRANSFORMREF1X;break; + case SDRATTR_TRANSFORMREF1Y : nResId = SIP_SA_TRANSFORMREF1Y;break; + case SDRATTR_TRANSFORMREF2X : nResId = SIP_SA_TRANSFORMREF2X;break; + case SDRATTR_TRANSFORMREF2Y : nResId = SIP_SA_TRANSFORMREF2Y;break; + + case SDRATTR_GRAFRED : nResId = SIP_SA_GRAFRED;break; + case SDRATTR_GRAFGREEN : nResId = SIP_SA_GRAFGREEN;break; + case SDRATTR_GRAFBLUE : nResId = SIP_SA_GRAFBLUE;break; + case SDRATTR_GRAFLUMINANCE : nResId = SIP_SA_GRAFLUMINANCE;break; + case SDRATTR_GRAFCONTRAST : nResId = SIP_SA_GRAFCONTRAST;break; + case SDRATTR_GRAFGAMMA : nResId = SIP_SA_GRAFGAMMA;break; + case SDRATTR_GRAFTRANSPARENCE : nResId = SIP_SA_GRAFTRANSPARENCE;break; + case SDRATTR_GRAFINVERT : nResId = SIP_SA_GRAFINVERT;break; + case SDRATTR_GRAFMODE : nResId = SIP_SA_GRAFMODE;break; + case SDRATTR_GRAFCROP : nResId = SIP_SA_GRAFCROP;break; + + case EE_PARA_HYPHENATE : nResId = SIP_EE_PARA_HYPHENATE;break; + case EE_PARA_BULLETSTATE: nResId = SIP_EE_PARA_BULLETSTATE;break; + case EE_PARA_OUTLLRSPACE: nResId = SIP_EE_PARA_OUTLLRSPACE;break; + case EE_PARA_OUTLLEVEL : nResId = SIP_EE_PARA_OUTLLEVEL;break; + case EE_PARA_BULLET : nResId = SIP_EE_PARA_BULLET;break; + case EE_PARA_LRSPACE : nResId = SIP_EE_PARA_LRSPACE;break; + case EE_PARA_ULSPACE : nResId = SIP_EE_PARA_ULSPACE;break; + case EE_PARA_SBL : nResId = SIP_EE_PARA_SBL;break; + case EE_PARA_JUST : nResId = SIP_EE_PARA_JUST;break; + case EE_PARA_TABS : nResId = SIP_EE_PARA_TABS;break; + + case EE_CHAR_COLOR : nResId = SIP_EE_CHAR_COLOR;break; + case EE_CHAR_FONTINFO : nResId = SIP_EE_CHAR_FONTINFO;break; + case EE_CHAR_FONTHEIGHT : nResId = SIP_EE_CHAR_FONTHEIGHT;break; + case EE_CHAR_FONTWIDTH : nResId = SIP_EE_CHAR_FONTWIDTH;break; + case EE_CHAR_WEIGHT : nResId = SIP_EE_CHAR_WEIGHT;break; + case EE_CHAR_UNDERLINE : nResId = SIP_EE_CHAR_UNDERLINE;break; + case EE_CHAR_OVERLINE : nResId = SIP_EE_CHAR_OVERLINE;break; + case EE_CHAR_STRIKEOUT : nResId = SIP_EE_CHAR_STRIKEOUT;break; + case EE_CHAR_ITALIC : nResId = SIP_EE_CHAR_ITALIC;break; + case EE_CHAR_OUTLINE : nResId = SIP_EE_CHAR_OUTLINE;break; + case EE_CHAR_SHADOW : nResId = SIP_EE_CHAR_SHADOW;break; + case EE_CHAR_ESCAPEMENT : nResId = SIP_EE_CHAR_ESCAPEMENT;break; + case EE_CHAR_PAIRKERNING: nResId = SIP_EE_CHAR_PAIRKERNING;break; + case EE_CHAR_KERNING : nResId = SIP_EE_CHAR_KERNING;break; + case EE_CHAR_WLM : nResId = SIP_EE_CHAR_WLM;break; + case EE_FEATURE_TAB : nResId = SIP_EE_FEATURE_TAB;break; + case EE_FEATURE_LINEBR : nResId = SIP_EE_FEATURE_LINEBR;break; + case EE_FEATURE_NOTCONV : nResId = SIP_EE_FEATURE_NOTCONV;break; + case EE_FEATURE_FIELD : nResId = SIP_EE_FEATURE_FIELD;break; + } // switch + + rItemName = String( ResId( nResId, *pResMgr ) ); +} + +//////////////////////////////////////////////////////////////////////////////// +// FractionItem +//////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1_AUTOFACTORY(SdrFractionItem,SfxPoolItem); + +SdrFractionItem::SdrFractionItem(USHORT nId, SvStream& rIn): + SfxPoolItem(nId) +{ + INT32 nMul,nDiv; + rIn>>nMul; + rIn>>nDiv; + nValue=Fraction(nMul,nDiv); +} + +int __EXPORT SdrFractionItem::operator==(const SfxPoolItem& rCmp) const +{ + return SfxPoolItem::operator==(rCmp) && + ((SdrFractionItem&)rCmp).GetValue()==nValue; +} + +SfxItemPresentation __EXPORT SdrFractionItem::GetPresentation( + SfxItemPresentation ePresentation, SfxMapUnit /*eCoreMetric*/, + SfxMapUnit /*ePresentationMetric*/, XubString &rText, const IntlWrapper *) const +{ + if(nValue.IsValid()) + { + INT32 nDiv = nValue.GetDenominator(); + rText = UniString::CreateFromInt32(nValue.GetNumerator()); + + if(nDiv != 1) + { + rText += sal_Unicode('/'); + rText += UniString::CreateFromInt32(nDiv); + } + } + else + { + rText = UniString(); + rText += sal_Unicode('?'); + } + + if(ePresentation == SFX_ITEM_PRESENTATION_COMPLETE) + { + XubString aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + + return ePresentation; +} + +SfxPoolItem* __EXPORT SdrFractionItem::Create(SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrFractionItem(Which(),rIn); +} + +SvStream& __EXPORT SdrFractionItem::Store(SvStream& rOut, USHORT /*nItemVers*/) const +{ + rOut<<INT32(nValue.GetNumerator()); + rOut<<INT32(nValue.GetDenominator()); + return rOut; +} + +SfxPoolItem* __EXPORT SdrFractionItem::Clone(SfxItemPool * /*pPool*/) const +{ + return new SdrFractionItem(Which(),GetValue()); +} + +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrFractionItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId<SDRATTR_NOTPERSIST_FIRST || nId>SDRATTR_NOTPERSIST_LAST; +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +// ScaleItem +//////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1_AUTOFACTORY(SdrScaleItem,SdrFractionItem); + +SfxItemPresentation __EXPORT SdrScaleItem::GetPresentation( + SfxItemPresentation ePresentation, SfxMapUnit /*eCoreMetric*/, + SfxMapUnit /*ePresentationMetric*/, XubString &rText, const IntlWrapper *) const +{ + if(GetValue().IsValid()) + { + INT32 nDiv = GetValue().GetDenominator(); + + rText = UniString::CreateFromInt32(GetValue().GetNumerator()); + rText += sal_Unicode(':'); + rText += UniString::CreateFromInt32(nDiv); + } + else + { + rText = UniString(); + rText += sal_Unicode('?'); + } + + if(ePresentation == SFX_ITEM_PRESENTATION_COMPLETE) + { + XubString aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + + return ePresentation; +} + +SfxPoolItem* __EXPORT SdrScaleItem::Create(SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrScaleItem(Which(),rIn); +} + +SfxPoolItem* __EXPORT SdrScaleItem::Clone(SfxItemPool * /*pPool*/) const +{ + return new SdrScaleItem(Which(),GetValue()); +} + +//////////////////////////////////////////////////////////////////////////////// +// OnOffItem +//////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1_AUTOFACTORY(SdrOnOffItem,SfxBoolItem); + +SfxPoolItem* __EXPORT SdrOnOffItem::Clone(SfxItemPool* /*pPool*/) const +{ + return new SdrOnOffItem(Which(),GetValue()); +} + +SfxPoolItem* __EXPORT SdrOnOffItem::Create(SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrOnOffItem(Which(),rIn); +} + +XubString __EXPORT SdrOnOffItem::GetValueTextByVal(BOOL bVal) const +{ + if (bVal) return ImpGetResStr(STR_ItemValON); + else return ImpGetResStr(STR_ItemValOFF); +} + +SfxItemPresentation __EXPORT SdrOnOffItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByVal(GetValue()); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrOnOffItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId<SDRATTR_NOTPERSIST_FIRST || nId>SDRATTR_NOTPERSIST_LAST; +} +#endif + +TYPEINIT1_AUTOFACTORY(SdrYesNoItem,SfxBoolItem); + +SfxPoolItem* __EXPORT SdrYesNoItem::Clone(SfxItemPool* /*pPool*/) const +{ + return new SdrYesNoItem(Which(),GetValue()); +} + +SfxPoolItem* __EXPORT SdrYesNoItem::Create(SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrYesNoItem(Which(),rIn); +} + +XubString __EXPORT SdrYesNoItem::GetValueTextByVal(BOOL bVal) const +{ + if (bVal) return ImpGetResStr(STR_ItemValYES); + else return ImpGetResStr(STR_ItemValNO); +} + +SfxItemPresentation __EXPORT SdrYesNoItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByVal(GetValue()); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrYesNoItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId<SDRATTR_NOTPERSIST_FIRST || nId>SDRATTR_NOTPERSIST_LAST; +} +#endif + +//------------------------------------------------------------ +// class SdrPercentItem +//------------------------------------------------------------ + +TYPEINIT1_AUTOFACTORY(SdrPercentItem,SfxUInt16Item); + +SfxPoolItem* __EXPORT SdrPercentItem::Clone(SfxItemPool* /*pPool*/) const +{ + return new SdrPercentItem(Which(),GetValue()); +} + +SfxPoolItem* __EXPORT SdrPercentItem::Create(SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrPercentItem(Which(),rIn); +} + +SfxItemPresentation __EXPORT SdrPercentItem::GetPresentation( + SfxItemPresentation ePres, SfxMapUnit /*eCoreMetric*/, + SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText = UniString::CreateFromInt32(GetValue()); + rText += sal_Unicode('%'); + + if(ePres == SFX_ITEM_PRESENTATION_COMPLETE) + { + XubString aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + + return ePres; +} + +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrPercentItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId<SDRATTR_NOTPERSIST_FIRST || nId>SDRATTR_NOTPERSIST_LAST; +} +#endif + +//------------------------------------------------------------ +// class SdrAngleItem +//------------------------------------------------------------ + +TYPEINIT1_AUTOFACTORY(SdrAngleItem,SfxInt32Item); + +SfxPoolItem* __EXPORT SdrAngleItem::Clone(SfxItemPool* /*pPool*/) const +{ + return new SdrAngleItem(Which(),GetValue()); +} + +SfxPoolItem* __EXPORT SdrAngleItem::Create(SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrAngleItem(Which(),rIn); +} + +SfxItemPresentation __EXPORT SdrAngleItem::GetPresentation( + SfxItemPresentation ePres, SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, + XubString& rText, const IntlWrapper * pIntlWrapper) const +{ + INT32 nValue(GetValue()); + BOOL bNeg(nValue < 0); + + if(bNeg) + nValue = -nValue; + + rText = UniString::CreateFromInt32(nValue); + + if(nValue) + { + sal_Unicode aUnicodeNull('0'); + xub_StrLen nAnz(2); + + const IntlWrapper* pMyIntlWrapper = NULL; +// DBG_ASSERT( pIntlWrapper, "SdrAngleItem::GetPresentation: using default App-IntlWrapper" ); + if(!pIntlWrapper) + pIntlWrapper = pMyIntlWrapper = new IntlWrapper( + ::comphelper::getProcessServiceFactory(), + Application::GetSettings().GetLanguage() ); + + if(pIntlWrapper->getLocaleData()->isNumLeadingZero()) + nAnz++; + + while(rText.Len() < nAnz) + rText.Insert(aUnicodeNull, 0); + + xub_StrLen nLen = rText.Len(); + BOOL bNull1(rText.GetChar(nLen-1) == aUnicodeNull); + BOOL bNull2(bNull1 && rText.GetChar(nLen-2) == aUnicodeNull); + + if(bNull2) + { + // keine Nachkommastellen + rText.Erase(nLen-2); + } + else + { + sal_Unicode cDec = + pIntlWrapper->getLocaleData()->getNumDecimalSep().GetChar(0); + rText.Insert(cDec, nLen-2); + + if(bNull1) + rText.Erase(nLen); + } + + if(bNeg) + rText.Insert(sal_Unicode('-'), 0); + + if ( pMyIntlWrapper ) + { + delete pMyIntlWrapper; + pIntlWrapper = NULL; + } + } + + rText += sal_Unicode(DEGREE_CHAR); + + if(ePres == SFX_ITEM_PRESENTATION_COMPLETE) + { + XubString aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + + return ePres; +} + +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrAngleItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId<SDRATTR_NOTPERSIST_FIRST || nId>SDRATTR_NOTPERSIST_LAST; +} +#endif + +//------------------------------------------------------------ +// class SdrMetricItem +//------------------------------------------------------------ + +TYPEINIT1_AUTOFACTORY(SdrMetricItem,SfxInt32Item); + +SfxPoolItem* __EXPORT SdrMetricItem::Clone(SfxItemPool* /*pPool*/) const +{ + return new SdrMetricItem(Which(),GetValue()); +} + +SfxPoolItem* __EXPORT SdrMetricItem::Create(SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrMetricItem(Which(),rIn); +} + +FASTBOOL __EXPORT SdrMetricItem::HasMetrics() const +{ + return TRUE; +} + +FASTBOOL __EXPORT SdrMetricItem::ScaleMetrics(long nMul, long nDiv) +{ + if (GetValue()!=0) { + BigInt aVal(GetValue()); + aVal*=nMul; + aVal+=nDiv/2; // fuer korrektes Runden + aVal/=nDiv; + SetValue(long(aVal)); + } + return TRUE; +} + +SfxItemPresentation __EXPORT SdrMetricItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit eCoreMetric, SfxMapUnit ePresMetric, XubString& rText, const IntlWrapper *) const +{ + long nValue=GetValue(); + SdrFormatter aFmt((MapUnit)eCoreMetric,(MapUnit)ePresMetric); + aFmt.TakeStr(nValue,rText); + String aStr; + aFmt.TakeUnitStr((MapUnit)ePresMetric,aStr); + rText+=aStr; + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr2; + + SdrItemPool::TakeItemName(Which(), aStr2); + aStr2 += sal_Unicode(' '); + rText.Insert(aStr2, 0); + } + return ePres; +} + +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrMetricItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId<SDRATTR_NOTPERSIST_FIRST || nId>SDRATTR_NOTPERSIST_LAST; +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Items des Legendenobjekts +//////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1_AUTOFACTORY(SdrCaptionTypeItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrCaptionTypeItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrCaptionTypeItem(*this); } + +SfxPoolItem* __EXPORT SdrCaptionTypeItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrCaptionTypeItem(rIn); } + +USHORT __EXPORT SdrCaptionTypeItem::GetValueCount() const { return 4; } + +XubString __EXPORT SdrCaptionTypeItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValCAPTIONTYPE1+nPos); +} + +SfxItemPresentation __EXPORT SdrCaptionTypeItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +TYPEINIT1_AUTOFACTORY(SdrCaptionEscDirItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrCaptionEscDirItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrCaptionEscDirItem(*this); } + +SfxPoolItem* __EXPORT SdrCaptionEscDirItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrCaptionEscDirItem(rIn); } + +USHORT __EXPORT SdrCaptionEscDirItem::GetValueCount() const { return 3; } + +XubString __EXPORT SdrCaptionEscDirItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValCAPTIONESCHORI+nPos); +} + +SfxItemPresentation __EXPORT SdrCaptionEscDirItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +//////////////////////////////////////////////////////////////////////////////// +// MiscItems +//////////////////////////////////////////////////////////////////////////////// + +// FitToSize +TYPEINIT1_AUTOFACTORY(SdrTextFitToSizeTypeItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrTextFitToSizeTypeItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrTextFitToSizeTypeItem(*this); } + +SfxPoolItem* __EXPORT SdrTextFitToSizeTypeItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrTextFitToSizeTypeItem(rIn); } + +USHORT __EXPORT SdrTextFitToSizeTypeItem::GetValueCount() const { return 4; } + +XubString __EXPORT SdrTextFitToSizeTypeItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValFITTOSIZENONE+nPos); +} + +SfxItemPresentation __EXPORT SdrTextFitToSizeTypeItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +int __EXPORT SdrTextFitToSizeTypeItem::HasBoolValue() const { return TRUE; } + +BOOL __EXPORT SdrTextFitToSizeTypeItem::GetBoolValue() const { return GetValue()!=SDRTEXTFIT_NONE; } + +void __EXPORT SdrTextFitToSizeTypeItem::SetBoolValue(BOOL bVal) { SetValue(sal::static_int_cast< USHORT >(bVal ? SDRTEXTFIT_PROPORTIONAL : SDRTEXTFIT_NONE)); } + +sal_Bool SdrTextFitToSizeTypeItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + drawing::TextFitToSizeType eFS = (drawing::TextFitToSizeType)GetValue(); + rVal <<= eFS; + + return sal_True; +} + +sal_Bool SdrTextFitToSizeTypeItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::TextFitToSizeType eFS; + if(!(rVal >>= eFS)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + eFS = (drawing::TextFitToSizeType) nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrFitToSizeType)eFS ) ); + + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrTextVertAdjustItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrTextVertAdjustItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrTextVertAdjustItem(*this); } + +SfxPoolItem* __EXPORT SdrTextVertAdjustItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrTextVertAdjustItem(rIn); } + +USHORT __EXPORT SdrTextVertAdjustItem::GetValueCount() const { return 5; } + +XubString __EXPORT SdrTextVertAdjustItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValTEXTVADJTOP+nPos); +} + +SfxItemPresentation __EXPORT SdrTextVertAdjustItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrTextVertAdjustItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::TextVerticalAdjust)GetValue(); + return sal_True; +} + +sal_Bool SdrTextVertAdjustItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::TextVerticalAdjust eAdj; + if(!(rVal >>= eAdj)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + eAdj = (drawing::TextVerticalAdjust)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrTextVertAdjust)eAdj ) ); + + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrTextHorzAdjustItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrTextHorzAdjustItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrTextHorzAdjustItem(*this); } + +SfxPoolItem* __EXPORT SdrTextHorzAdjustItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrTextHorzAdjustItem(rIn); } + +USHORT __EXPORT SdrTextHorzAdjustItem::GetValueCount() const { return 5; } + +XubString __EXPORT SdrTextHorzAdjustItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValTEXTHADJLEFT+nPos); +} + +SfxItemPresentation __EXPORT SdrTextHorzAdjustItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrTextHorzAdjustItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::TextHorizontalAdjust)GetValue(); + return sal_True; +} + +sal_Bool SdrTextHorzAdjustItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::TextHorizontalAdjust eAdj; + if(!(rVal >>= eAdj)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + eAdj = (drawing::TextHorizontalAdjust)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrTextHorzAdjust)eAdj ) ); + + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrTextAniKindItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrTextAniKindItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrTextAniKindItem(*this); } + +SfxPoolItem* __EXPORT SdrTextAniKindItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrTextAniKindItem(rIn); } + +USHORT __EXPORT SdrTextAniKindItem::GetValueCount() const { return 5; } + +XubString __EXPORT SdrTextAniKindItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValTEXTANI_NONE+nPos); +} + +SfxItemPresentation __EXPORT SdrTextAniKindItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrTextAniKindItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::TextAnimationKind)GetValue(); + return sal_True; +} + +sal_Bool SdrTextAniKindItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::TextAnimationKind eKind; + if(!(rVal >>= eKind)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + eKind = (drawing::TextAnimationKind)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrTextAniKind)eKind ) ); + + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrTextAniDirectionItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrTextAniDirectionItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrTextAniDirectionItem(*this); } + +SfxPoolItem* __EXPORT SdrTextAniDirectionItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrTextAniDirectionItem(rIn); } + +USHORT __EXPORT SdrTextAniDirectionItem::GetValueCount() const { return 4; } + +XubString __EXPORT SdrTextAniDirectionItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValTEXTANI_LEFT+nPos); +} + +SfxItemPresentation __EXPORT SdrTextAniDirectionItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrTextAniDirectionItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::TextAnimationDirection)GetValue(); + return sal_True; +} + +sal_Bool SdrTextAniDirectionItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::TextAnimationDirection eDir; + if(!(rVal >>= eDir)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + eDir = (drawing::TextAnimationDirection)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrTextAniDirection)eDir ) ); + + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrTextAniDelayItem,SfxUInt16Item); + +SfxPoolItem* __EXPORT SdrTextAniDelayItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrTextAniDelayItem(*this); } + +SfxPoolItem* __EXPORT SdrTextAniDelayItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrTextAniDelayItem(rIn); } + +SfxItemPresentation __EXPORT SdrTextAniDelayItem::GetPresentation( + SfxItemPresentation ePres, SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, + XubString& rText, const IntlWrapper *) const +{ + rText = UniString::CreateFromInt32(GetValue()); + rText += sal_Unicode('m'); + rText += sal_Unicode('s'); + + if(ePres == SFX_ITEM_PRESENTATION_COMPLETE) + { + XubString aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + + return ePres; +} + +TYPEINIT1_AUTOFACTORY(SdrTextAniAmountItem,SfxInt16Item); + +SfxPoolItem* __EXPORT SdrTextAniAmountItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrTextAniAmountItem(*this); } + +SfxPoolItem* __EXPORT SdrTextAniAmountItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrTextAniAmountItem(rIn); } + +FASTBOOL __EXPORT SdrTextAniAmountItem::HasMetrics() const +{ + return GetValue()>0; +} + +FASTBOOL __EXPORT SdrTextAniAmountItem::ScaleMetrics(long nMul, long nDiv) +{ + if (GetValue()>0) { + BigInt aVal(GetValue()); + aVal*=nMul; + aVal+=nDiv/2; // fuer korrektes Runden + aVal/=nDiv; + SetValue(short(aVal)); + return TRUE; + } else return FALSE; +} + +SfxItemPresentation __EXPORT SdrTextAniAmountItem::GetPresentation( + SfxItemPresentation ePres, SfxMapUnit eCoreMetric, SfxMapUnit ePresMetric, + XubString& rText, const IntlWrapper *) const +{ + INT32 nValue(GetValue()); + + if(!nValue) + nValue = -1L; + + if(nValue < 0) + { + sal_Char aText[] = "pixel"; + + rText = UniString::CreateFromInt32(-nValue); + rText += UniString(aText, sizeof(aText-1)); + } + else + { + SdrFormatter aFmt((MapUnit)eCoreMetric, (MapUnit)ePresMetric); + XubString aStr; + + aFmt.TakeStr(nValue, rText); + aFmt.TakeUnitStr((MapUnit)ePresMetric, aStr); + rText += aStr; + } + + if(ePres == SFX_ITEM_PRESENTATION_COMPLETE) + { + XubString aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + + return ePres; +} + +TYPEINIT1_AUTOFACTORY( SdrTextFixedCellHeightItem, SfxBoolItem ); +SdrTextFixedCellHeightItem::SdrTextFixedCellHeightItem( BOOL bUseFixedCellHeight ) + : SfxBoolItem( SDRATTR_TEXT_USEFIXEDCELLHEIGHT, bUseFixedCellHeight ) +{ +} +SdrTextFixedCellHeightItem::SdrTextFixedCellHeightItem( SvStream & rStream, sal_uInt16 nVersion ) + : SfxBoolItem( SDRATTR_TEXT_USEFIXEDCELLHEIGHT, FALSE ) +{ + if ( nVersion ) + { + sal_Bool bValue; + rStream >> bValue; + SetValue( bValue ); + } +} +SfxItemPresentation __EXPORT SdrTextFixedCellHeightItem::GetPresentation( SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresentationMetric*/, + String &rText, const IntlWrapper * ) const +{ + rText = GetValueTextByVal( GetValue() ); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) + { + String aStr; + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} +SfxPoolItem* __EXPORT SdrTextFixedCellHeightItem::Create( SvStream& rIn, sal_uInt16 nItemVersion ) const +{ + return new SdrTextFixedCellHeightItem( rIn, nItemVersion ); +} +SvStream& __EXPORT SdrTextFixedCellHeightItem::Store( SvStream& rOut, sal_uInt16 nItemVersion ) const +{ + if ( nItemVersion ) + { + sal_Bool bValue = (sal_Bool)GetValue(); + rOut << bValue; + } + return rOut; +} +SfxPoolItem* __EXPORT SdrTextFixedCellHeightItem::Clone( SfxItemPool * /*pPool*/) const +{ + return new SdrTextFixedCellHeightItem( GetValue() ); +} +sal_uInt16 SdrTextFixedCellHeightItem::GetVersion( sal_uInt16 /*nFileFormatVersion*/) const +{ + return 1; +} +sal_Bool SdrTextFixedCellHeightItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + sal_Bool bValue = (sal_Bool)GetValue(); + rVal <<= bValue; + return sal_True; +} +sal_Bool SdrTextFixedCellHeightItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Bool bValue = sal_Bool(); + if( !( rVal >>= bValue ) ) + return sal_False; + SetValue( bValue ); + return sal_True; +} +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrTextFixedCellHeightItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId < SDRATTR_NOTPERSIST_FIRST || nId > SDRATTR_NOTPERSIST_LAST; +} +#endif + +TYPEINIT1_AUTOFACTORY( SdrCustomShapeAdjustmentItem, SfxPoolItem ); + +SdrCustomShapeAdjustmentItem::SdrCustomShapeAdjustmentItem() : SfxPoolItem( SDRATTR_CUSTOMSHAPE_ADJUSTMENT ) +{ +} + +SdrCustomShapeAdjustmentItem::SdrCustomShapeAdjustmentItem( SvStream& rIn, sal_uInt16 nVersion ): + SfxPoolItem( SDRATTR_CUSTOMSHAPE_ADJUSTMENT ) +{ + if ( nVersion ) + { + SdrCustomShapeAdjustmentValue aVal; + sal_uInt32 i, nCount; + rIn >> nCount; + for ( i = 0; i < nCount; i++ ) + { + rIn >> aVal.nValue; + SetValue( i, aVal ); + } + } +} + +SdrCustomShapeAdjustmentItem::~SdrCustomShapeAdjustmentItem() +{ + void* pPtr; + for ( pPtr = aAdjustmentValueList.First(); pPtr; pPtr = aAdjustmentValueList.Next() ) + delete (SdrCustomShapeAdjustmentValue*)pPtr; +} + +int __EXPORT SdrCustomShapeAdjustmentItem::operator==( const SfxPoolItem& rCmp ) const +{ + int bRet = SfxPoolItem::operator==( rCmp ); + if ( bRet ) + { + bRet = ((SdrCustomShapeAdjustmentItem&)rCmp).GetCount() == GetCount(); + if ( bRet ) + { + sal_uInt32 i; + for ( i = 0; i < GetCount(); i++ ) + { + if ( ((SdrCustomShapeAdjustmentItem&)rCmp).GetValue( i ).nValue != GetValue( i ).nValue ) + { + bRet = 0; + break; + } + } + } + } + return bRet; +} + +SfxItemPresentation __EXPORT SdrCustomShapeAdjustmentItem::GetPresentation( + SfxItemPresentation ePresentation, SfxMapUnit /*eCoreMetric*/, + SfxMapUnit /*ePresentationMetric*/, XubString &rText, const IntlWrapper *) const +{ + sal_uInt32 i, nCount = GetCount(); + rText.Append( UniString::CreateFromInt32( nCount ) ); + for ( i = 0; i < nCount; i++ ) + { + rText += sal_Unicode( ' ' ); + rText.Append( UniString::CreateFromInt32( GetValue( i ).nValue ) ); + } + if ( ePresentation == SFX_ITEM_PRESENTATION_COMPLETE ) + { + XubString aStr; + + SdrItemPool::TakeItemName( Which(), aStr ); + aStr += sal_Unicode( ' ' ); + rText.Insert( aStr, 0 ); + } + return ePresentation; +} + +SfxPoolItem* __EXPORT SdrCustomShapeAdjustmentItem::Create( SvStream& rIn, sal_uInt16 nItemVersion ) const +{ + return new SdrCustomShapeAdjustmentItem( rIn, nItemVersion ); +} + +SvStream& __EXPORT SdrCustomShapeAdjustmentItem::Store( SvStream& rOut, sal_uInt16 nItemVersion ) const +{ + if ( nItemVersion ) + { + sal_uInt32 i, nCount = GetCount(); + rOut << nCount; + for ( i = 0; i < nCount; i++ ) + rOut << GetValue( i ).nValue; + } + return rOut; +} + +SfxPoolItem* __EXPORT SdrCustomShapeAdjustmentItem::Clone( SfxItemPool * /*pPool*/) const +{ + sal_uInt32 i; + SdrCustomShapeAdjustmentItem* pItem = new SdrCustomShapeAdjustmentItem; + for ( i = 0; i < GetCount(); i++ ) + { + const SdrCustomShapeAdjustmentValue& rVal = GetValue( i ); + pItem->SetValue( i, rVal ); + } + return pItem; +} + +#ifdef SDR_ISPOOLABLE +int __EXPORT SdrCustomShapeAdjustmentItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId < SDRATTR_NOTPERSIST_FIRST || nId > SDRATTR_NOTPERSIST_LAST; +} +#endif + +const SdrCustomShapeAdjustmentValue& SdrCustomShapeAdjustmentItem::GetValue( sal_uInt32 nIndex ) const +{ +#ifdef DBG_UTIL + if ( aAdjustmentValueList.Count() <= nIndex ) + DBG_ERROR( "SdrCustomShapeAdjustemntItem::GetValue - nIndex out of range (SJ)" ); +#endif + return *(SdrCustomShapeAdjustmentValue*)aAdjustmentValueList.GetObject( nIndex ); +} + +void SdrCustomShapeAdjustmentItem::SetValue( sal_uInt32 nIndex, const SdrCustomShapeAdjustmentValue& rVal ) +{ + sal_uInt32 i; + for ( i = GetCount(); i <= nIndex; i++ ) + { + SdrCustomShapeAdjustmentValue* pItem = new SdrCustomShapeAdjustmentValue; + aAdjustmentValueList.Insert( pItem, LIST_APPEND ); + } + SdrCustomShapeAdjustmentValue& rValue = *(SdrCustomShapeAdjustmentValue*)aAdjustmentValueList.GetObject( nIndex ); + rValue.nValue = rVal.nValue; +} + +sal_uInt16 SdrCustomShapeAdjustmentItem::GetVersion( sal_uInt16 /*nFileFormatVersion*/) const +{ + return 1; +} + +sal_Bool SdrCustomShapeAdjustmentItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + sal_uInt32 i, nCount = GetCount(); + uno::Sequence< sal_Int32 > aSequence( nCount ); + if ( nCount ) + { + sal_Int32* pPtr = aSequence.getArray(); + for ( i = 0; i < nCount; i++ ) + *pPtr++ = GetValue( i ).nValue; + } + rVal <<= aSequence; + return sal_True; +} + +sal_Bool SdrCustomShapeAdjustmentItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + uno::Sequence< sal_Int32 > aSequence; + if( !( rVal >>= aSequence ) ) + return sal_False; + + void* pPtr; + for ( pPtr = aAdjustmentValueList.First(); pPtr; pPtr = aAdjustmentValueList.Next() ) + delete (SdrCustomShapeAdjustmentValue*)pPtr; + + sal_uInt32 i, nCount = aSequence.getLength(); + if ( nCount ) + { + const sal_Int32* pPtr2 = aSequence.getConstArray(); + for ( i = 0; i < nCount; i++ ) + { + SdrCustomShapeAdjustmentValue* pItem = new SdrCustomShapeAdjustmentValue; + pItem->nValue = *pPtr2++; + aAdjustmentValueList.Insert( pItem, LIST_APPEND ); + } + } + return sal_True; +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Edge +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// EdgeKind +TYPEINIT1_AUTOFACTORY(SdrEdgeKindItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrEdgeKindItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrEdgeKindItem(*this); } + +SfxPoolItem* __EXPORT SdrEdgeKindItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrEdgeKindItem(rIn); } + +USHORT __EXPORT SdrEdgeKindItem::GetValueCount() const { return 4; } + +XubString __EXPORT SdrEdgeKindItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValEDGE_ORTHOLINES+nPos); +} + +SfxItemPresentation __EXPORT SdrEdgeKindItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrEdgeKindItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + drawing::ConnectorType eCT = drawing::ConnectorType_STANDARD; + + switch( GetValue() ) + { + case SDREDGE_ORTHOLINES : eCT = drawing::ConnectorType_STANDARD; break; + case SDREDGE_THREELINES : eCT = drawing::ConnectorType_LINES; break; + case SDREDGE_ONELINE : eCT = drawing::ConnectorType_LINE; break; + case SDREDGE_BEZIER : eCT = drawing::ConnectorType_CURVE; break; + case SDREDGE_ARC : eCT = drawing::ConnectorType_CURVE; break; + default: + DBG_ERROR( "SdrEdgeKindItem::QueryValue : unknown enum" ); + } + + rVal <<= eCT; + + return sal_True; +} + +sal_Bool SdrEdgeKindItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::ConnectorType eCT; + if(!(rVal >>= eCT)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + eCT = (drawing::ConnectorType)nEnum; + } + + SdrEdgeKind eEK = SDREDGE_ORTHOLINES; + switch( eCT ) + { + case drawing::ConnectorType_STANDARD : eEK = SDREDGE_ORTHOLINES; break; + case drawing::ConnectorType_CURVE : eEK = SDREDGE_BEZIER; break; + case drawing::ConnectorType_LINE : eEK = SDREDGE_ONELINE; break; + case drawing::ConnectorType_LINES : eEK = SDREDGE_THREELINES; break; + default: + DBG_ERROR( "SdrEdgeKindItem::PuValue : unknown enum" ); + } + SetValue( sal::static_int_cast< USHORT >( eEK ) ); + + return sal_True; +} + +sal_Bool SdrEdgeNode1HorzDistItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +sal_Bool SdrEdgeNode1HorzDistItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nValue = 0; + if(!(rVal >>= nValue)) + return sal_False; + + SetValue( nValue ); + return sal_True; +} + +BOOL SdrEdgeNode1VertDistItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +BOOL SdrEdgeNode1VertDistItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nValue = 0; + if(!(rVal >>= nValue)) + return sal_False; + + SetValue( nValue ); + return sal_True; +} + +BOOL SdrEdgeNode2HorzDistItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +BOOL SdrEdgeNode2HorzDistItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nValue = 0; + if(!(rVal >>= nValue)) + return sal_False; + + SetValue( nValue ); + return sal_True; +} + +BOOL SdrEdgeNode2VertDistItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +BOOL SdrEdgeNode2VertDistItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nValue = 0; + if(!(rVal >>= nValue)) + return sal_False; + + SetValue( nValue ); + return sal_True; +} + +BOOL SdrEdgeLine1DeltaItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +BOOL SdrEdgeLine1DeltaItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nValue = 0; + if(!(rVal >>= nValue)) + return sal_False; + + SetValue( nValue ); + return sal_True; +} + +BOOL SdrEdgeLine2DeltaItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +BOOL SdrEdgeLine2DeltaItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nValue = 0; + if(!(rVal >>= nValue)) + return sal_False; + + SetValue( nValue ); + return sal_True; +} + +BOOL SdrEdgeLine3DeltaItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +BOOL SdrEdgeLine3DeltaItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nValue = 0; + if(!(rVal >>= nValue)) + return sal_False; + + SetValue( nValue ); + return sal_True; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Measure +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// MeasureKind +TYPEINIT1_AUTOFACTORY(SdrMeasureKindItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrMeasureKindItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrMeasureKindItem(*this); } + +SfxPoolItem* __EXPORT SdrMeasureKindItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrMeasureKindItem(rIn); } + +USHORT __EXPORT SdrMeasureKindItem::GetValueCount() const { return 2; } + +XubString __EXPORT SdrMeasureKindItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValMEASURE_STD+nPos); +} + +SfxItemPresentation __EXPORT SdrMeasureKindItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrMeasureKindItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::MeasureKind)GetValue(); + return sal_True; +} + +sal_Bool SdrMeasureKindItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::MeasureKind eKind; + if(!(rVal >>= eKind)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + eKind = (drawing::MeasureKind)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrMeasureKind)eKind ) ); + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrMeasureTextHPosItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrMeasureTextHPosItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrMeasureTextHPosItem(*this); } + +SfxPoolItem* __EXPORT SdrMeasureTextHPosItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrMeasureTextHPosItem(rIn); } + +USHORT __EXPORT SdrMeasureTextHPosItem::GetValueCount() const { return 4; } + +XubString __EXPORT SdrMeasureTextHPosItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValMEASURE_TEXTHAUTO+nPos); +} + +SfxItemPresentation __EXPORT SdrMeasureTextHPosItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrMeasureTextHPosItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::MeasureTextHorzPos)GetValue(); + return sal_True; +} + +sal_Bool SdrMeasureTextHPosItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::MeasureTextHorzPos ePos; + if(!(rVal >>= ePos)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + ePos = (drawing::MeasureTextHorzPos)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrMeasureTextHPos)ePos ) ); + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrMeasureTextVPosItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrMeasureTextVPosItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrMeasureTextVPosItem(*this); } + +SfxPoolItem* __EXPORT SdrMeasureTextVPosItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrMeasureTextVPosItem(rIn); } + +USHORT __EXPORT SdrMeasureTextVPosItem::GetValueCount() const { return 5; } + +XubString __EXPORT SdrMeasureTextVPosItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValMEASURE_TEXTVAUTO+nPos); +} + +SfxItemPresentation __EXPORT SdrMeasureTextVPosItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrMeasureTextVPosItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::MeasureTextVertPos)GetValue(); + return sal_True; +} + +sal_Bool SdrMeasureTextVPosItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::MeasureTextVertPos ePos; + if(!(rVal >>= ePos)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + ePos = (drawing::MeasureTextVertPos)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrMeasureTextHPos)ePos ) ); + return sal_True; +} + +TYPEINIT1_AUTOFACTORY(SdrMeasureUnitItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrMeasureUnitItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrMeasureUnitItem(*this); } + +SfxPoolItem* __EXPORT SdrMeasureUnitItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrMeasureUnitItem(rIn); } + +USHORT __EXPORT SdrMeasureUnitItem::GetValueCount() const { return 14; } + +XubString __EXPORT SdrMeasureUnitItem::GetValueTextByPos(USHORT nPos) const +{ + XubString aRetval; + + if((FieldUnit)nPos == FUNIT_NONE) + { + sal_Char aText[] = "default"; + aRetval += UniString(aText, sizeof(aText-1)); + } + else + { + SdrFormatter::TakeUnitStr((FieldUnit)nPos, aRetval); + } + + return aRetval; +} + +SfxItemPresentation __EXPORT SdrMeasureUnitItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrMeasureUnitItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (sal_Int32)GetValue(); + return sal_True; +} + +sal_Bool SdrMeasureUnitItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + sal_Int32 nMeasure = 0; + if(!(rVal >>= nMeasure)) + return sal_False; + + SetValue( sal::static_int_cast< USHORT >( (FieldUnit)nMeasure ) ); + return sal_True; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Circ +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// CircKind +TYPEINIT1_AUTOFACTORY(SdrCircKindItem,SfxEnumItem); + +SfxPoolItem* __EXPORT SdrCircKindItem::Clone(SfxItemPool* /*pPool*/) const { return new SdrCircKindItem(*this); } + +SfxPoolItem* __EXPORT SdrCircKindItem::Create(SvStream& rIn, USHORT /*nVer*/) const { return new SdrCircKindItem(rIn); } + +USHORT __EXPORT SdrCircKindItem::GetValueCount() const { return 4; } + +XubString __EXPORT SdrCircKindItem::GetValueTextByPos(USHORT nPos) const +{ + return ImpGetResStr(STR_ItemValCIRC_FULL+nPos); +} + +SfxItemPresentation __EXPORT SdrCircKindItem::GetPresentation(SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, XubString& rText, const IntlWrapper *) const +{ + rText=GetValueTextByPos(sal::static_int_cast< USHORT >(GetValue())); + if (ePres==SFX_ITEM_PRESENTATION_COMPLETE) { + String aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + return ePres; +} + +sal_Bool SdrCircKindItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= (drawing::CircleKind)GetValue(); + return sal_True; +} + +sal_Bool SdrCircKindItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + drawing::CircleKind eKind; + if(!(rVal >>= eKind)) + { + sal_Int32 nEnum = 0; + if(!(rVal >>= nEnum)) + return sal_False; + + eKind = (drawing::CircleKind)nEnum; + } + + SetValue( sal::static_int_cast< USHORT >( (SdrCircKind)eKind ) ); + return sal_True; +} + +//------------------------------------------------------------ +// class SdrSignedPercentItem +//------------------------------------------------------------ + +TYPEINIT1_AUTOFACTORY( SdrSignedPercentItem, SfxInt16Item ); + + +SfxPoolItem* __EXPORT SdrSignedPercentItem::Clone(SfxItemPool* /*pPool*/) const +{ + return new SdrSignedPercentItem( Which(), GetValue() ); +} + +SfxPoolItem* __EXPORT SdrSignedPercentItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrSignedPercentItem( Which(), rIn ); +} + +SfxItemPresentation __EXPORT SdrSignedPercentItem::GetPresentation( + SfxItemPresentation ePres, SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, + XubString& rText, const IntlWrapper *) const +{ + rText = UniString::CreateFromInt32(GetValue()); + rText += sal_Unicode('%'); + + if(ePres == SFX_ITEM_PRESENTATION_COMPLETE) + { + XubString aStr; + + SdrItemPool::TakeItemName(Which(), aStr); + aStr += sal_Unicode(' '); + rText.Insert(aStr, 0); + } + + return ePres; +} + +#ifdef SDR_ISPOOLABLE + +int __EXPORT SdrSignedPercentItem::IsPoolable() const +{ + USHORT nId=Which(); + return nId < SDRATTR_NOTPERSIST_FIRST || nId > SDRATTR_NOTPERSIST_LAST; +} +#endif + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafRedItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafRedItem, SdrSignedPercentItem ); + +SfxPoolItem* __EXPORT SdrGrafRedItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafRedItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafRedItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafRedItem( rIn ); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafGreenItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafGreenItem, SdrSignedPercentItem ); + +SfxPoolItem* __EXPORT SdrGrafGreenItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafGreenItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafGreenItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafGreenItem( rIn ); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafBlueItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafBlueItem, SdrSignedPercentItem ); + +SfxPoolItem* __EXPORT SdrGrafBlueItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafBlueItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafBlueItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafBlueItem( rIn ); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafLuminanceItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafLuminanceItem, SdrSignedPercentItem ); + +SfxPoolItem* __EXPORT SdrGrafLuminanceItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafLuminanceItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafLuminanceItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafLuminanceItem( rIn ); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafContrastItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafContrastItem, SdrSignedPercentItem ); + +SfxPoolItem* __EXPORT SdrGrafContrastItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafContrastItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafContrastItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafContrastItem( rIn ); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafGamma100Item +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafGamma100Item, SfxUInt32Item ); + +SfxPoolItem* __EXPORT SdrGrafGamma100Item::Clone( SfxItemPool* /*pPool */) const +{ + return new SdrGrafGamma100Item( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafGamma100Item::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafGamma100Item( rIn ); +} + +sal_Bool SdrGrafGamma100Item::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/) const +{ + rVal <<= ((double)GetValue()) / 100.0; + return sal_True; +} + +sal_Bool SdrGrafGamma100Item::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/) +{ + double nGamma = 0; + if(!(rVal >>= nGamma)) + return sal_False; + + SetValue( (UINT32)(nGamma * 100.0 ) ); + return sal_True; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafInvertItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafInvertItem, SdrOnOffItem ); + +SfxPoolItem* __EXPORT SdrGrafInvertItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafInvertItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafInvertItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafInvertItem( rIn ); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafTransparenceItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafTransparenceItem, SdrPercentItem ); + +SfxPoolItem* __EXPORT SdrGrafTransparenceItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafTransparenceItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafTransparenceItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafTransparenceItem( rIn ); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafModeItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafModeItem, SfxEnumItem ); + +SfxPoolItem* __EXPORT SdrGrafModeItem::Clone(SfxItemPool* /*pPool*/) const +{ + return new SdrGrafModeItem( *this ); +} + +SfxPoolItem* __EXPORT SdrGrafModeItem::Create( SvStream& rIn, USHORT /*nVer*/) const +{ + return new SdrGrafModeItem( rIn ); +} + +USHORT __EXPORT SdrGrafModeItem::GetValueCount() const +{ + return 4; +} + +XubString __EXPORT SdrGrafModeItem::GetValueTextByPos(UINT16 nPos) const +{ + XubString aStr; + + switch(nPos) + { + case 1: + { + sal_Char aTextGreys[] = "Greys"; + aStr += UniString(aTextGreys, sizeof(aTextGreys-1)); + break; + } + case 2: + { + sal_Char aTextBlackWhite[] = "Black/White"; + aStr += UniString(aTextBlackWhite, sizeof(aTextBlackWhite-1)); + break; + } + case 3: + { + sal_Char aTextWatermark[] = "Watermark"; + aStr += UniString(aTextWatermark, sizeof(aTextWatermark-1)); + break; + } + default: + { + sal_Char aTextStandard[] = "Standard"; + aStr += UniString(aTextStandard, sizeof(aTextStandard-1)); + break; + } + } + + return aStr; +} + +SfxItemPresentation __EXPORT SdrGrafModeItem::GetPresentation( SfxItemPresentation ePres, + SfxMapUnit /*eCoreMetric*/, SfxMapUnit /*ePresMetric*/, + XubString& rText, const IntlWrapper *) const +{ + rText = GetValueTextByPos( sal::static_int_cast< USHORT >( GetValue() ) ); + + if( ePres == SFX_ITEM_PRESENTATION_COMPLETE ) + { + String aStr; + + SdrItemPool::TakeItemName( Which(), aStr ); + aStr += sal_Unicode(' '); + rText.Insert( aStr, 0 ); + } + + return ePres; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// SdrGrafCropItem +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPEINIT1( SdrGrafCropItem, SvxGrfCrop ); + +SfxPoolItem* SdrGrafCropItem::Clone( SfxItemPool* /*pPool*/) const +{ + return new SdrGrafCropItem( *this ); +} + +SfxPoolItem* SdrGrafCropItem::Create( SvStream& rIn, USHORT nVer ) const +{ + return( ( 0 == nVer ) ? Clone( NULL ) : SvxGrfCrop::Create( rIn, nVer ) ); +} + +USHORT SdrGrafCropItem::GetVersion( USHORT /*nFileVersion*/) const +{ + // GRFCROP_VERSION_MOVETOSVX is 1 + return GRFCROP_VERSION_MOVETOSVX; +} + +// eof diff --git a/svx/source/svdraw/svdcrtv.cxx b/svx/source/svdraw/svdcrtv.cxx new file mode 100644 index 000000000000..9fd0edd3aac0 --- /dev/null +++ b/svx/source/svdraw/svdcrtv.cxx @@ -0,0 +1,964 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdcrtv.hxx> +#include "xattr.hxx" +#include <svx/svdundo.hxx> +#include <svx/svdocapt.hxx> // Spezialbehandlung: Nach dem Create transparente Fuellung +#include <svx/svdoedge.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdetc.hxx> +#include <svx/scene3d.hxx> +#include <svx/view3d.hxx> +#include <svx/sdr/contact/objectcontactofobjlistpainter.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <svx/svdouno.hxx> +#define XOR_CREATE_PEN PEN_SOLID +#include <svx/svdopath.hxx> +#include <svx/sdr/overlay/overlaypolypolygon.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <sdrpaintwindow.hxx> +#include "fmobj.hxx" +#include <svx/svdocirc.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImplConnectMarkerOverlay +{ + // The OverlayObjects + ::sdr::overlay::OverlayObjectList maObjects; + + // The remembered target object + const SdrObject& mrObject; + +public: + ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject& rObject); + ~ImplConnectMarkerOverlay(); + + const SdrObject& GetTargetObject() const { return mrObject; } +}; + +ImplConnectMarkerOverlay::ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject& rObject) +: mrObject(rObject) +{ + basegfx::B2DPolyPolygon aB2DPolyPolygon(rObject.TakeXorPoly()); + + for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); + + if(pTargetOverlay) + { + Size aHalfLogicSize(pTargetOverlay->getOutputDevice().PixelToLogic(Size(4, 4))); + + // object + ::sdr::overlay::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(aB2DPolyPolygon); + pTargetOverlay->add(*pNew); + maObjects.append(*pNew); + + // gluepoints + if(rView.IsAutoVertexConnectors()) + { + for(sal_uInt16 i(0); i < 4; i++) + { + SdrGluePoint aGluePoint(rObject.GetVertexGluePoint(i)); + const Point& rPosition = aGluePoint.GetAbsolutePos(rObject); + + basegfx::B2DPoint aTopLeft(rPosition.X() - aHalfLogicSize.Width(), rPosition.Y() - aHalfLogicSize.Height()); + basegfx::B2DPoint aBottomRight(rPosition.X() + aHalfLogicSize.Width(), rPosition.Y() + aHalfLogicSize.Height()); + + basegfx::B2DPolygon aTempPoly; + aTempPoly.append(aTopLeft); + aTempPoly.append(basegfx::B2DPoint(aBottomRight.getX(), aTopLeft.getY())); + aTempPoly.append(aBottomRight); + aTempPoly.append(basegfx::B2DPoint(aTopLeft.getX(), aBottomRight.getY())); + aTempPoly.setClosed(true); + + basegfx::B2DPolyPolygon aTempPolyPoly; + aTempPolyPoly.append(aTempPoly); + + pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(aTempPolyPoly); + pTargetOverlay->add(*pNew); + maObjects.append(*pNew); + } + } + } + } +} + +ImplConnectMarkerOverlay::~ImplConnectMarkerOverlay() +{ + // The OverlayObjects are cleared using the destructor of OverlayObjectList. + // That destructor calls clear() at the list which removes all objects from the + // OverlayManager and deletes them. +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpSdrCreateViewExtraData +{ + // The OverlayObjects for XOR replacement + ::sdr::overlay::OverlayObjectList maObjects; + +public: + ImpSdrCreateViewExtraData(); + ~ImpSdrCreateViewExtraData(); + + void CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly); + void HideOverlay(); +}; + +ImpSdrCreateViewExtraData::ImpSdrCreateViewExtraData() +{ +} + +ImpSdrCreateViewExtraData::~ImpSdrCreateViewExtraData() +{ + HideOverlay(); +} + +void ImpSdrCreateViewExtraData::CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly) +{ + for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + ::sdr::overlay::OverlayManager* pOverlayManager = pCandidate->GetOverlayManager(); + + if(pOverlayManager) + { + if(pObject) + { + const sdr::contact::ViewContact& rVC = pObject->GetViewContact(); + const drawinglayer::primitive2d::Primitive2DSequence aSequence = rVC.getViewIndependentPrimitive2DSequence(); + sdr::overlay::OverlayObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence); + + pOverlayManager->add(*pNew); + maObjects.append(*pNew); + } + + if(rPolyPoly.count()) + { + ::sdr::overlay::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(rPolyPoly); + pOverlayManager->add(*pNew); + maObjects.append(*pNew); + } + } + } +} + +void ImpSdrCreateViewExtraData::HideOverlay() +{ + // the clear() call at the list removes all objects from the + // OverlayManager and deletes them. + maObjects.clear(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@@@@ @@@@@ @@@@ @@@@@@ @@@@@ @@ @@ @@ @@@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ +// @@ @@@@@ @@@@ @@@@@@ @@ @@@@ @@@@@ @@ @@@@ @@@@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ +// @@@@ @@ @@ @@@@@ @@ @@ @@ @@@@@ @ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrCreateView::ImpClearConnectMarker() +{ + if(mpCoMaOverlay) + { + delete mpCoMaOverlay; + mpCoMaOverlay = 0L; + } +} + +void SdrCreateView::ImpClearVars() +{ + nAktInvent=SdrInventor; + nAktIdent=OBJ_NONE; + pAktCreate=NULL; + pCreatePV=NULL; + bAutoTextEdit=FALSE; + b1stPointAsCenter=FALSE; + aAktCreatePointer=Pointer(POINTER_CROSS); + bUseIncompatiblePathCreateInterface=FALSE; + bAutoClosePolys=TRUE; + nAutoCloseDistPix=5; + nFreeHandMinDistPix=10; + + ImpClearConnectMarker(); +} + +void SdrCreateView::ImpMakeCreateAttr() +{ +} + +SdrCreateView::SdrCreateView(SdrModel* pModel1, OutputDevice* pOut) +: SdrDragView(pModel1,pOut), + mpCoMaOverlay(0L), + mpCreateViewExtraData(new ImpSdrCreateViewExtraData()) +{ + ImpClearVars(); + ImpMakeCreateAttr(); +} + +SdrCreateView::~SdrCreateView() +{ + ImpClearConnectMarker(); + delete mpCreateViewExtraData; + SdrObject::Free( pAktCreate ); +} + +void SdrCreateView::ImpDelCreateAttr() +{ +} + +BOOL SdrCreateView::IsAction() const +{ + return SdrDragView::IsAction() || pAktCreate!=NULL; +} + +void SdrCreateView::MovAction(const Point& rPnt) +{ + SdrDragView::MovAction(rPnt); + if (pAktCreate!=NULL) { + MovCreateObj(rPnt); + } +} + +void SdrCreateView::EndAction() +{ + if (pAktCreate!=NULL) EndCreateObj(SDRCREATE_FORCEEND); + SdrDragView::EndAction(); +} + +void SdrCreateView::BckAction() +{ + if (pAktCreate!=NULL) BckCreateObj(); + SdrDragView::BckAction(); +} + +void SdrCreateView::BrkAction() +{ + SdrDragView::BrkAction(); + BrkCreateObj(); +} + +void SdrCreateView::TakeActionRect(Rectangle& rRect) const +{ + if (pAktCreate!=NULL) + { + rRect=aDragStat.GetActionRect(); + if (rRect.IsEmpty()) + { + rRect=Rectangle(aDragStat.GetPrev(),aDragStat.GetNow()); + } + } + else + { + SdrDragView::TakeActionRect(rRect); + } +} + +BOOL SdrCreateView::CheckEdgeMode() +{ + UINT32 nInv=nAktInvent; + UINT16 nIdn=nAktIdent; + if (pAktCreate!=NULL) + { + nInv=pAktCreate->GetObjInventor(); + nIdn=pAktCreate->GetObjIdentifier(); + // wird vom EdgeObj gemanaged + if (nAktInvent==SdrInventor && nAktIdent==OBJ_EDGE) return FALSE; + } + + if (!IsCreateMode() || nAktInvent!=SdrInventor || nAktIdent!=OBJ_EDGE) + { + ImpClearConnectMarker(); + return FALSE; + } + else + { + // TRUE heisst: MouseMove soll Connect checken + return !IsAction(); + } +} + +void SdrCreateView::SetConnectMarker(const SdrObjConnection& rCon, const SdrPageView& /*rPV*/) +{ + SdrObject* pTargetObject = rCon.pObj; + + if(pTargetObject) + { + // if target object changes, throw away overlay object to make room for changes + if(mpCoMaOverlay && pTargetObject != &mpCoMaOverlay->GetTargetObject()) + { + ImpClearConnectMarker(); + } + + if(!mpCoMaOverlay) + { + mpCoMaOverlay = new ImplConnectMarkerOverlay(*this, *pTargetObject); + } + } + else + { + ImpClearConnectMarker(); + } +} + +void SdrCreateView::HideConnectMarker() +{ + ImpClearConnectMarker(); +} + +BOOL SdrCreateView::MouseMove(const MouseEvent& rMEvt, Window* pWin) +{ + if(CheckEdgeMode() && pWin) + { + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + // Defaultete Hit-Toleranz bei IsMarkedHit() mal aendern !!!! + Point aPos(pWin->PixelToLogic(rMEvt.GetPosPixel())); + BOOL bMarkHit=PickHandle(aPos)!=NULL || IsMarkedObjHit(aPos); + SdrObjConnection aCon; + if (!bMarkHit) SdrEdgeObj::ImpFindConnector(aPos,*pPV,aCon,NULL,pWin); + SetConnectMarker(aCon,*pPV); + } + } + return SdrDragView::MouseMove(rMEvt,pWin); +} + +BOOL SdrCreateView::IsTextTool() const +{ + return eEditMode==SDREDITMODE_CREATE && nAktInvent==SdrInventor && (nAktIdent==OBJ_TEXT || nAktIdent==OBJ_TEXTEXT || nAktIdent==OBJ_TITLETEXT || nAktIdent==OBJ_OUTLINETEXT); +} + +BOOL SdrCreateView::IsEdgeTool() const +{ + return eEditMode==SDREDITMODE_CREATE && nAktInvent==SdrInventor && (nAktIdent==OBJ_EDGE); +} + +BOOL SdrCreateView::IsMeasureTool() const +{ + return eEditMode==SDREDITMODE_CREATE && nAktInvent==SdrInventor && (nAktIdent==OBJ_MEASURE); +} + +void SdrCreateView::SetCurrentObj(UINT16 nIdent, UINT32 nInvent) +{ + if (nAktInvent!=nInvent || nAktIdent!=nIdent) + { + nAktInvent=nInvent; + nAktIdent=nIdent; + SdrObject* pObj = SdrObjFactory::MakeNewObject(nInvent,nIdent,NULL,NULL); + + if(pObj) + { + // Auf pers. Wunsch von Marco: + // Mauszeiger bei Textwerkzeug immer I-Beam. Fadenkreuz + // mit kleinem I-Beam erst bai MouseButtonDown + if(IsTextTool()) + { + // #81944# AW: Here the correct pointer needs to be used + // if the default is set to vertical writing + aAktCreatePointer = POINTER_TEXT; + } + else + aAktCreatePointer = pObj->GetCreatePointer(); + + SdrObject::Free( pObj ); + } + else + { + aAktCreatePointer = Pointer(POINTER_CROSS); + } + } + + CheckEdgeMode(); + ImpSetGlueVisible3(IsEdgeTool()); +} + +BOOL SdrCreateView::ImpBegCreateObj(UINT32 nInvent, UINT16 nIdent, const Point& rPnt, OutputDevice* pOut, + short nMinMov, SdrPageView* pPV, const Rectangle& rLogRect, SdrObject* pPreparedFactoryObject) +{ + BOOL bRet=FALSE; + UnmarkAllObj(); + BrkAction(); + + ImpClearConnectMarker(); + + if (pPV!=NULL) + { + pCreatePV=pPV; + } + else + { + pCreatePV = GetSdrPageView(); + } + if (pCreatePV!=NULL) + { // ansonsten keine Seite angemeldet! + String aLay(aAktLayer); + + if(nInvent == SdrInventor && nIdent == OBJ_MEASURE && aMeasureLayer.Len()) + { + aLay = aMeasureLayer; + } + + SdrLayerID nLayer=pCreatePV->GetPage()->GetLayerAdmin().GetLayerID(aLay,TRUE); + if (nLayer==SDRLAYER_NOTFOUND) nLayer=0; + if (!pCreatePV->GetLockedLayers().IsSet(nLayer) && pCreatePV->GetVisibleLayers().IsSet(nLayer)) + { + if(pPreparedFactoryObject) + { + pAktCreate = pPreparedFactoryObject; + + if(pCreatePV->GetPage()) + { + pAktCreate->SetPage(pCreatePV->GetPage()); + } + else if (pMod) + { + pAktCreate->SetModel(pMod); + } + } + else + { + pAktCreate = SdrObjFactory::MakeNewObject(nInvent, nIdent, pCreatePV->GetPage(), pMod); + } + + Point aPnt(rPnt); + if (nAktInvent!=SdrInventor || (nAktIdent!=USHORT(OBJ_EDGE) && + nAktIdent!=USHORT(OBJ_FREELINE) && + nAktIdent!=USHORT(OBJ_FREEFILL) )) { // Kein Fang fuer Edge und Freihand! + aPnt=GetSnapPos(aPnt,pCreatePV); + } + if (pAktCreate!=NULL) + { + BOOL bStartEdit=FALSE; // nach Ende von Create automatisch TextEdit starten + if (pDefaultStyleSheet!=NULL) pAktCreate->NbcSetStyleSheet(pDefaultStyleSheet, sal_False); + + // #101618# SW uses a naked SdrObject for frame construction. Normally, such an + // object should not be created. Since it is possible to use it as a helper + // object (e.g. in letting the user define an area with the interactive + // construction) at least no items should be set at that object. + if(nInvent != SdrInventor || nIdent != OBJ_NONE) + { + pAktCreate->SetMergedItemSet(aDefaultAttr); + } + + if (HAS_BASE(SdrCaptionObj,pAktCreate)) + { + SfxItemSet aSet(pMod->GetItemPool()); + aSet.Put(XFillColorItem(String(),Color(COL_WHITE))); // Falls einer auf Solid umschaltet + aSet.Put(XFillStyleItem(XFILL_NONE)); + + pAktCreate->SetMergedItemSet(aSet); + + bStartEdit=TRUE; + } + if (nInvent==SdrInventor && (nIdent==OBJ_TEXT || nIdent==OBJ_TEXTEXT || + nIdent==OBJ_TITLETEXT || nIdent==OBJ_OUTLINETEXT)) + { + // Fuer alle Textrahmen default keinen Hintergrund und keine Umrandung + SfxItemSet aSet(pMod->GetItemPool()); + aSet.Put(XFillColorItem(String(),Color(COL_WHITE))); // Falls einer auf Solid umschaltet + aSet.Put(XFillStyleItem(XFILL_NONE)); + aSet.Put(XLineColorItem(String(),Color(COL_BLACK))); // Falls einer auf Solid umschaltet + aSet.Put(XLineStyleItem(XLINE_NONE)); + + pAktCreate->SetMergedItemSet(aSet); + + bStartEdit=TRUE; + } + if (!rLogRect.IsEmpty()) pAktCreate->NbcSetLogicRect(rLogRect); + + // #90129# make sure drag start point is inside WorkArea + const Rectangle& rWorkArea = ((SdrDragView*)this)->GetWorkArea(); + + if(!rWorkArea.IsEmpty()) + { + if(aPnt.X() < rWorkArea.Left()) + { + aPnt.X() = rWorkArea.Left(); + } + + if(aPnt.X() > rWorkArea.Right()) + { + aPnt.X() = rWorkArea.Right(); + } + + if(aPnt.Y() < rWorkArea.Top()) + { + aPnt.Y() = rWorkArea.Top(); + } + + if(aPnt.Y() > rWorkArea.Bottom()) + { + aPnt.Y() = rWorkArea.Bottom(); + } + } + + aDragStat.Reset(aPnt); + aDragStat.SetView((SdrView*)this); + aDragStat.SetPageView(pCreatePV); + aDragStat.SetMinMove(ImpGetMinMovLogic(nMinMov,pOut)); + pDragWin=pOut; + if (pAktCreate->BegCreate(aDragStat)) + { + ShowCreateObj(/*pOut,TRUE*/); + bRet=TRUE; + } + else + { + SdrObject::Free( pAktCreate ); + pAktCreate=NULL; + pCreatePV=NULL; + } + } + } + } + return bRet; +} + +BOOL SdrCreateView::BegCreateObj(const Point& rPnt, OutputDevice* pOut, short nMinMov, SdrPageView* pPV) +{ + return ImpBegCreateObj(nAktInvent,nAktIdent,rPnt,pOut,nMinMov,pPV,Rectangle(), 0L); +} + +sal_Bool SdrCreateView::BegCreatePreparedObject(const Point& rPnt, sal_Int16 nMinMov, SdrObject* pPreparedFactoryObject) +{ + sal_uInt32 nInvent(nAktInvent); + sal_uInt16 nIdent(nAktIdent); + + if(pPreparedFactoryObject) + { + nInvent = pPreparedFactoryObject->GetObjInventor(); + nIdent = pPreparedFactoryObject->GetObjIdentifier(); + } + + return ImpBegCreateObj(nInvent, nIdent, rPnt, 0L, nMinMov, 0L, Rectangle(), pPreparedFactoryObject); +} + +BOOL SdrCreateView::BegCreateCaptionObj(const Point& rPnt, const Size& rObjSiz, + OutputDevice* pOut, short nMinMov, SdrPageView* pPV) +{ + return ImpBegCreateObj(SdrInventor,OBJ_CAPTION,rPnt,pOut,nMinMov,pPV, + Rectangle(rPnt,Size(rObjSiz.Width()+1,rObjSiz.Height()+1)), 0L); +} + +void SdrCreateView::MovCreateObj(const Point& rPnt) +{ + if (pAktCreate!=NULL) { + Point aPnt(rPnt); + if (!aDragStat.IsNoSnap()) + { + aPnt=GetSnapPos(aPnt,pCreatePV); + } + if (IsOrtho()) + { + if (aDragStat.IsOrtho8Possible()) OrthoDistance8(aDragStat.GetPrev(),aPnt,IsBigOrtho()); + else if (aDragStat.IsOrtho4Possible()) OrthoDistance4(aDragStat.GetPrev(),aPnt,IsBigOrtho()); + } + + // #77734# If the drag point was limited and Ortho is active, do + // the small ortho correction (reduction) -> last parameter to FALSE. + sal_Bool bDidLimit(ImpLimitToWorkArea(aPnt)); + if(bDidLimit && IsOrtho()) + { + if(aDragStat.IsOrtho8Possible()) + OrthoDistance8(aDragStat.GetPrev(), aPnt, FALSE); + else if(aDragStat.IsOrtho4Possible()) + OrthoDistance4(aDragStat.GetPrev(), aPnt, FALSE); + } + + if (aPnt==aDragStat.GetNow()) return; + bool bMerk(aDragStat.IsMinMoved()); + if (aDragStat.CheckMinMoved(aPnt)) + { + Rectangle aBound; + if (!bMerk) aDragStat.NextPoint(); + aDragStat.NextMove(aPnt); + pAktCreate->MovCreate(aDragStat); + + // MovCreate changes the object, so use ActionChanged() on it + pAktCreate->ActionChanged(); + + // replace for DrawCreateObjDiff + HideCreateObj(); + ShowCreateObj(); + } + } +} + +BOOL SdrCreateView::EndCreateObj(SdrCreateCmd eCmd) +{ + BOOL bRet=FALSE; + SdrObject* pObjMerk=pAktCreate; + SdrPageView* pPVMerk=pCreatePV; + + if (pAktCreate!=NULL) + { + ULONG nAnz=aDragStat.GetPointAnz(); + + if (nAnz<=1 && eCmd==SDRCREATE_FORCEEND) + { + BrkCreateObj(); // Objekte mit nur einem Punkt gibt's nicht (zumindest noch nicht) + return FALSE; // FALSE=Event nicht ausgewertet + } + + BOOL bPntsEq=nAnz>1; + ULONG i=1; + Point aP0=aDragStat.GetPoint(0); + while (bPntsEq && i<nAnz) { bPntsEq=aP0==aDragStat.GetPoint(i); i++; } + + if (pAktCreate->EndCreate(aDragStat,eCmd)) + { + HideCreateObj(); + + if (!bPntsEq) + { + // sonst Brk, weil alle Punkte gleich sind. + SdrObject* pObj=pAktCreate; + pAktCreate=NULL; + + const SdrLayerAdmin& rAd = pCreatePV->GetPage()->GetLayerAdmin(); + SdrLayerID nLayer(0); + + // #i72535# + if(pObj->ISA(FmFormObj)) + { + // for FormControls, force to form layer + nLayer = rAd.GetLayerID(rAd.GetControlLayerName(), true); + } + else + { + nLayer = rAd.GetLayerID(aAktLayer, TRUE); + } + + if(SDRLAYER_NOTFOUND == nLayer) + { + nLayer=0; + } + + pObj->SetLayer(nLayer); + + // #83403# recognize creation of a new 3D object inside a 3D scene + BOOL bSceneIntoScene(FALSE); + + if(pObjMerk + && pObjMerk->ISA(E3dScene) + && pCreatePV + && pCreatePV->GetAktGroup() + && pCreatePV->GetAktGroup()->ISA(E3dScene)) + { + BOOL bDidInsert = ((E3dView*)this)->ImpCloneAll3DObjectsToDestScene( + (E3dScene*)pObjMerk, (E3dScene*)pCreatePV->GetAktGroup(), Point(0, 0)); + + if(bDidInsert) + { + // delete object, it's content is cloned and inserted + SdrObject::Free( pObjMerk ); + pObjMerk = 0L; + bRet = FALSE; + bSceneIntoScene = TRUE; + } + } + + if(!bSceneIntoScene) + { + // do the same as before + InsertObjectAtView(pObj, *pCreatePV); + } + + pCreatePV=NULL; + bRet=TRUE; // TRUE=Event ausgewertet + } + else + { + BrkCreateObj(); + } + } + else + { // Mehr Punkte + if (eCmd==SDRCREATE_FORCEEND || // nix da, Ende erzwungen + nAnz==0 || // keine Punkte da (kann eigentlich nicht vorkommen) + (nAnz<=1 && !aDragStat.IsMinMoved())) { // MinMove nicht erfuellt + BrkCreateObj(); + } + else + { + // replace for DrawCreateObjDiff + HideCreateObj(); + ShowCreateObj(); + aDragStat.ResetMinMoved(); // NextPoint gibt's bei MovCreateObj() + bRet=TRUE; + } + } + if (bRet && pObjMerk!=NULL && IsTextEditAfterCreate()) + { + SdrTextObj* pText=PTR_CAST(SdrTextObj,pObjMerk); + if (pText!=NULL && pText->IsTextFrame()) + { + SdrBeginTextEdit(pText, pPVMerk, (Window*)0L, sal_True, (SdrOutliner*)0L, (OutlinerView*)0L); + } + } + } + return bRet; +} + +void SdrCreateView::BckCreateObj() +{ + if (pAktCreate!=NULL) + { + if (aDragStat.GetPointAnz()<=2 ) + { + BrkCreateObj(); + } + else + { + HideCreateObj(); + aDragStat.PrevPoint(); + if (pAktCreate->BckCreate(aDragStat)) + { + ShowCreateObj(); + } + else + { + BrkCreateObj(); + } + } + } +} + +void SdrCreateView::BrkCreateObj() +{ + if (pAktCreate!=NULL) + { + HideCreateObj(); + pAktCreate->BrkCreate(aDragStat); + SdrObject::Free( pAktCreate ); + pAktCreate=NULL; + pCreatePV=NULL; + } +} + +void SdrCreateView::ShowCreateObj(/*OutputDevice* pOut, BOOL bFull*/) +{ + if(IsCreateObj() && !aDragStat.IsShown()) + { + if(pAktCreate) + { + // for migration from XOR, replace DrawDragObj here to create + // overlay objects instead. + sal_Bool bUseSolidDragging(IsSolidDragging()); + + // #i101648# check if dragged object is a naked SdrObject (no + // derivation of). This is e.g. used in SW Frame construction + // as placeholder. Do not use SolidDragging for naked SDrObjects, + // they cannot have a valid optical representation + if(bUseSolidDragging && OBJ_NONE == pAktCreate->GetObjIdentifier()) + { + bUseSolidDragging = false; + } + + // check for objects with no fill and no line + if(bUseSolidDragging) + { + const SfxItemSet& rSet = pAktCreate->GetMergedItemSet(); + const XFillStyle eFill(((XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue()); + const XLineStyle eLine(((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue()); + + if(XLINE_NONE == eLine && XFILL_NONE == eFill) + { + bUseSolidDragging = sal_False; + } + } + + // check for form controls + if(bUseSolidDragging) + { + if(pAktCreate->ISA(SdrUnoObj)) + { + bUseSolidDragging = sal_False; + } + } + + // #i101781# force to non-solid dragging when not creating a full circle + if(bUseSolidDragging) + { + SdrCircObj* pCircObj = dynamic_cast< SdrCircObj* >(pAktCreate); + + if(pCircObj && OBJ_CIRC != pCircObj->GetObjIdentifier()) + { + // #i103058# Allow SolidDragging with four points + if(aDragStat.GetPointAnz() < 4) + { + bUseSolidDragging = false; + } + } + } + + if(bUseSolidDragging) + { + basegfx::B2DPolyPolygon aDragPolyPolygon; + + if(pAktCreate->ISA(SdrRectObj)) + { + // ensure object has some size, necessary for SdrTextObj because + // there are still untested divisions by that sizes + Rectangle aCurrentSnapRect(pAktCreate->GetSnapRect()); + + if(!(aCurrentSnapRect.GetWidth() > 1 && aCurrentSnapRect.GetHeight() > 1)) + { + Rectangle aNewRect(aDragStat.GetStart(), aDragStat.GetStart() + Point(2, 2)); + pAktCreate->NbcSetSnapRect(aNewRect); + } + } + + if(pAktCreate->ISA(SdrPathObj)) + { + // The up-to-now created path needs to be set at the object to have something + // that can be visualized + SdrPathObj& rPathObj((SdrPathObj&)(*pAktCreate)); + const basegfx::B2DPolyPolygon aCurrentPolyPolygon(rPathObj.getObjectPolyPolygon(aDragStat)); + + if(aCurrentPolyPolygon.count()) + { + rPathObj.NbcSetPathPoly(aCurrentPolyPolygon); + } + + aDragPolyPolygon = rPathObj.getDragPolyPolygon(aDragStat); + } + + // use directly the SdrObject for overlay + mpCreateViewExtraData->CreateAndShowOverlay(*this, pAktCreate, aDragPolyPolygon); + } + else + { + mpCreateViewExtraData->CreateAndShowOverlay(*this, 0, pAktCreate->TakeCreatePoly(aDragStat)); + } + + // #i101679# Force changed overlay to be shown + for(sal_uInt32 a(0); a < PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = GetPaintWindow(a); + sdr::overlay::OverlayManager* pOverlayManager = pCandidate->GetOverlayManager(); + + if(pOverlayManager) + { + pOverlayManager->flush(); + } + } + } + + aDragStat.SetShown(TRUE); + } +} + +void SdrCreateView::HideCreateObj() +{ + if(IsCreateObj() && aDragStat.IsShown()) + { + // for migration from XOR, replace DrawDragObj here to create + // overlay objects instead. + mpCreateViewExtraData->HideOverlay(); + + //DrawCreateObj(pOut,bFull); + aDragStat.SetShown(FALSE); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/* new interface src537 */ +BOOL SdrCreateView::GetAttributes(SfxItemSet& rTargetSet, BOOL bOnlyHardAttr) const +{ + if(pAktCreate) + { + rTargetSet.Put(pAktCreate->GetMergedItemSet()); + return TRUE; + } + else + { + return SdrDragView::GetAttributes(rTargetSet, bOnlyHardAttr); + } +} + +BOOL SdrCreateView::SetAttributes(const SfxItemSet& rSet, BOOL bReplaceAll) +{ + if(pAktCreate) + { + pAktCreate->SetMergedItemSetAndBroadcast(rSet, bReplaceAll); + + return TRUE; + } + else + { + return SdrDragView::SetAttributes(rSet,bReplaceAll); + } +} + +SfxStyleSheet* SdrCreateView::GetStyleSheet() const // SfxStyleSheet* SdrCreateView::GetStyleSheet(BOOL& rOk) const +{ + if (pAktCreate!=NULL) + { + //rOk=TRUE; + return pAktCreate->GetStyleSheet(); + } + else + { + return SdrDragView::GetStyleSheet(); // SdrDragView::GetStyleSheet(rOk); + } +} + +BOOL SdrCreateView::SetStyleSheet(SfxStyleSheet* pStyleSheet, BOOL bDontRemoveHardAttr) +{ + if (pAktCreate!=NULL) + { + pAktCreate->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr); + return TRUE; + } + else + { + return SdrDragView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr); + } +} + diff --git a/svx/source/svdraw/svddrag.cxx b/svx/source/svdraw/svddrag.cxx new file mode 100644 index 000000000000..74d8fd10a402 --- /dev/null +++ b/svx/source/svdraw/svddrag.cxx @@ -0,0 +1,153 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/svdview.hxx> +#include <svx/svddrag.hxx> + +void SdrDragStat::Clear(FASTBOOL bLeaveOne) +{ + void* pP=aPnts.First(); + while (pP!=NULL) { + delete (Point*)pP; + pP=aPnts.Next(); + } + if (pUser!=NULL) delete pUser; + pUser=NULL; + aPnts.Clear(); + if (bLeaveOne) { + aPnts.Insert(new Point,CONTAINER_APPEND); + } +} + +void SdrDragStat::Reset() +{ + pView=NULL; + pPageView=NULL; + bShown=FALSE; + nMinMov=1; + bMinMoved=FALSE; + bHorFixed=FALSE; + bVerFixed=FALSE; + bWantNoSnap=FALSE; + pHdl=NULL; + bOrtho4=FALSE; + bOrtho8=FALSE; + pDragMethod=NULL; + bEndDragChangesAttributes=FALSE; + bEndDragChangesGeoAndAttributes=FALSE; + bMouseIsUp=FALSE; + Clear(TRUE); + aActionRect=Rectangle(); +} + +void SdrDragStat::Reset(const Point& rPnt) +{ + Reset(); + Start()=rPnt; + aPos0=rPnt; + aRealPos0=rPnt; + RealNow()=rPnt; +} + +void SdrDragStat::NextMove(const Point& rPnt) +{ + aRealPos0=GetRealNow(); + aPos0=GetNow(); + RealNow()=rPnt; + Point aBla=KorregPos(GetRealNow(),GetPrev()); + Now()=aBla; +} + +void SdrDragStat::NextPoint(FASTBOOL bSaveReal) +{ + Point aPnt(GetNow()); + if (bSaveReal) aPnt=aRealNow; + aPnts.Insert(new Point(KorregPos(GetRealNow(),aPnt)),CONTAINER_APPEND); + Prev()=aPnt; +} + +void SdrDragStat::PrevPoint() +{ + if (aPnts.Count()>=2) { // einer muss immer da bleiben + Point* pPnt=(Point*)(aPnts.GetObject(aPnts.Count()-2)); + aPnts.Remove(aPnts.Count()-2); + delete pPnt; + Now()=KorregPos(GetRealNow(),GetPrev()); + } +} + +Point SdrDragStat::KorregPos(const Point& rNow, const Point& /*rPrev*/) const +{ + Point aRet(rNow); + return aRet; +} + +FASTBOOL SdrDragStat::CheckMinMoved(const Point& rPnt) +{ + if (!bMinMoved) { + long dx=rPnt.X()-GetPrev().X(); if (dx<0) dx=-dx; + long dy=rPnt.Y()-GetPrev().Y(); if (dy<0) dy=-dy; + if (dx>=long(nMinMov) || dy>=long(nMinMov)) + bMinMoved=TRUE; + } + return bMinMoved; +} + +Fraction SdrDragStat::GetXFact() const +{ + long nMul=GetNow().X()-aRef1.X(); + long nDiv=GetPrev().X()-aRef1.X(); + if (nDiv==0) nDiv=1; + if (bHorFixed) { nMul=1; nDiv=1; } + return Fraction(nMul,nDiv); +} + +Fraction SdrDragStat::GetYFact() const +{ + long nMul=GetNow().Y()-aRef1.Y(); + long nDiv=GetPrev().Y()-aRef1.Y(); + if (nDiv==0) nDiv=1; + if (bVerFixed) { nMul=1; nDiv=1; } + return Fraction(nMul,nDiv); +} + +void SdrDragStat::TakeCreateRect(Rectangle& rRect) const +{ + rRect=Rectangle(GetStart(),GetNow()); + if (GetPointAnz()>=2) { + Point aBtmRgt(GetPoint(1)); + rRect.Right()=aBtmRgt.X(); + rRect.Bottom()=aBtmRgt.Y(); + } + if (pView!=NULL && pView->IsCreate1stPointAsCenter()) { + rRect.Top()+=rRect.Top()-rRect.Bottom(); + rRect.Left()+=rRect.Left()-rRect.Right(); + } +} + diff --git a/svx/source/svdraw/svddrgm1.hxx b/svx/source/svdraw/svddrgm1.hxx new file mode 100644 index 000000000000..201d02e7b9f3 --- /dev/null +++ b/svx/source/svdraw/svddrgm1.hxx @@ -0,0 +1,277 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVDDRGM1_HXX +#define _SVDDRGM1_HXX + +#include <svx/xpoly.hxx> +#include <svx/svdhdl.hxx> +#include <svx/svddrgv.hxx> +#include <svx/svddrgmt.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// predeclarations + +class SdrDragView; +class SdrDragStat; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragMovHdl + +class SdrDragMovHdl : public SdrDragMethod +{ +private: + bool bMirrObjShown; + +protected: + // define nothing, overload to do so + virtual void createSdrDragEntries(); + +public: + TYPEINFO(); + SdrDragMovHdl(SdrDragView& rNewView); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + virtual void CancelSdrDrag(); + virtual Pointer GetSdrDragPointer() const; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragRotate + +class SdrDragRotate : public SdrDragMethod +{ +private: + double nSin; + double nCos; + long nWink0; + long nWink; + bool bRight; + +public: + TYPEINFO(); + SdrDragRotate(SdrDragView& rNewView); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + virtual Pointer GetSdrDragPointer() const; + + virtual basegfx::B2DHomMatrix getCurrentTransformation(); + virtual void applyCurrentTransformationToSdrObject(SdrObject& rTarget); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragShear + +class SdrDragShear : public SdrDragMethod +{ +private: + Fraction aFact; + long nWink0; + long nWink; + double nTan; + bool bVertical; // Vertikales verzerren + bool bResize; // Shear mit Resize + bool bUpSideDown; // Beim Shear/Slant gespiegelt + bool bSlant; + +public: + TYPEINFO(); + SdrDragShear(SdrDragView& rNewView,bool bSlant1); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + virtual Pointer GetSdrDragPointer() const; + + virtual basegfx::B2DHomMatrix getCurrentTransformation(); + virtual void applyCurrentTransformationToSdrObject(SdrObject& rTarget); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragMirror + +class SdrDragMirror : public SdrDragMethod +{ +private: + Point aDif; + long nWink; + bool bMirrored; + bool bSide0; + + bool ImpCheckSide(const Point& rPnt) const; + +public: + TYPEINFO(); + SdrDragMirror(SdrDragView& rNewView); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + virtual Pointer GetSdrDragPointer() const; + + virtual basegfx::B2DHomMatrix getCurrentTransformation(); + virtual void applyCurrentTransformationToSdrObject(SdrObject& rTarget); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragGradient + +class SdrDragGradient : public SdrDragMethod +{ +private: + // Handles to work on + SdrHdlGradient* pIAOHandle; + + // is this for gradient (or for transparence) ? + unsigned bIsGradient : 1; + +public: + TYPEINFO(); + SdrDragGradient(SdrDragView& rNewView, bool bGrad = true); + + bool IsGradient() const { return bIsGradient; } + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + virtual Pointer GetSdrDragPointer() const; + virtual void CancelSdrDrag(); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragCrook + +class SdrDragCrook : public SdrDragMethod +{ +private: + Rectangle aMarkRect; + Point aMarkCenter; + Point aCenter; + Point aStart; + Fraction aFact; + Point aRad; + bool bContortionAllowed; + bool bNoContortionAllowed; + bool bContortion; + bool bResizeAllowed; + bool bResize; + bool bRotateAllowed; + bool bRotate; + bool bVertical; + bool bValid; + bool bLft; + bool bRgt; + bool bUpr; + bool bLwr; + bool bAtCenter; + long nWink; + long nMarkSize; + SdrCrookMode eMode; + + // helpers for applyCurrentTransformationToPolyPolygon + void _MovAllPoints(basegfx::B2DPolyPolygon& rTarget); + void _MovCrookPoint(Point& rPnt, Point* pC1, Point* pC2); + +protected: + // needs to add drag geometry to the default + virtual void createSdrDragEntries(); + +public: + TYPEINFO(); + SdrDragCrook(SdrDragView& rNewView); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + virtual Pointer GetSdrDragPointer() const; + + virtual void applyCurrentTransformationToSdrObject(SdrObject& rTarget); + virtual void applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragDistort + +class SdrDragDistort : public SdrDragMethod +{ +private: + Rectangle aMarkRect; + XPolygon aDistortedRect; + sal_uInt16 nPolyPt; + bool bContortionAllowed; + bool bNoContortionAllowed; + bool bContortion; + + // helper for applyCurrentTransformationToPolyPolygon + void _MovAllPoints(basegfx::B2DPolyPolygon& rTarget); + +protected: + // needs to add drag geometry to the default + virtual void createSdrDragEntries(); + +public: + TYPEINFO(); + SdrDragDistort(SdrDragView& rNewView); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + virtual Pointer GetSdrDragPointer() const; + + virtual void applyCurrentTransformationToSdrObject(SdrObject& rTarget); + virtual void applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrDragCrop + +class SdrDragCrop : public SdrDragResize +{ +public: + TYPEINFO(); + SdrDragCrop(SdrDragView& rNewView); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool EndSdrDrag(bool bCopy); + virtual Pointer GetSdrDragPointer() const; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#endif //_SVDDRGM1_HXX + +// eof diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx new file mode 100644 index 000000000000..d04bf8851795 --- /dev/null +++ b/svx/source/svdraw/svddrgmt.cxx @@ -0,0 +1,3652 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include "svddrgm1.hxx" +#include <math.h> + +#ifndef _MATH_H +#define _MATH_H +#endif +#include <tools/bigint.hxx> +#include <vcl/svapp.hxx> + +#include "xattr.hxx" +#include <svx/xpoly.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdmark.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdpagv.hxx> +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include <svx/svddrgv.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdograf.hxx> +#include <svx/dialogs.hrc> +#include <svx/dialmgr.hxx> +#include <svx/sdgcpitm.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <svx/sdr/overlay/overlaypolypolygon.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/sdr/overlay/overlayrollingrectangle.hxx> +#include <svx/sdrpagewindow.hxx> +#include <sdrpaintwindow.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> +#include <svx/sdr/contact/objectcontact.hxx> +#include "svditer.hxx" +#include <svx/svdopath.hxx> +#include <svx/polypolygoneditor.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx> +#include <svx/sdr/primitive2d/sdrattributecreator.hxx> +#include <svx/sdr/primitive2d/sdrdecompositiontools.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdovirt.hxx> +#include <svx/svdouno.hxx> +#include <svx/sdr/primitive2d/sdrprimitivetools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/attribute/sdrlineattribute.hxx> +#include <drawinglayer/attribute/sdrlinestartendattribute.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrDragEntry::SdrDragEntry() +: mbAddToTransparent(false) +{ +} + +SdrDragEntry::~SdrDragEntry() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrDragEntryPolyPolygon::SdrDragEntryPolyPolygon(const basegfx::B2DPolyPolygon& rOriginalPolyPolygon) +: SdrDragEntry(), + maOriginalPolyPolygon(rOriginalPolyPolygon) +{ +} + +SdrDragEntryPolyPolygon::~SdrDragEntryPolyPolygon() +{ +} + +drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPolyPolygon::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod) +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval; + + if(maOriginalPolyPolygon.count()) + { + basegfx::B2DPolyPolygon aCopy(maOriginalPolyPolygon); + const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + + rDragMethod.applyCurrentTransformationToPolyPolygon(aCopy); + basegfx::BColor aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor()); + basegfx::BColor aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor()); + const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength()); + + if(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor(); + aColB.invert(); + } + + drawinglayer::primitive2d::Primitive2DReference aPolyPolygonMarkerPrimitive2D( + new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(aCopy, aColA, aColB, fStripeLength)); + + aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aPolyPolygonMarkerPrimitive2D, 1); + } + + return aRetval; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrDragEntrySdrObject::SdrDragEntrySdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify) +: SdrDragEntry(), + maOriginal(rOriginal), + mpClone(0), + mrObjectContact(rObjectContact), + mbModify(bModify) +{ + // add SdrObject parts to transparent overlay stuff + setAddToTransparent(true); +} + +SdrDragEntrySdrObject::~SdrDragEntrySdrObject() +{ + if(mpClone) + { + SdrObject::Free(mpClone); + } +} + +drawinglayer::primitive2d::Primitive2DSequence SdrDragEntrySdrObject::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod) +{ + // for the moment, i need to re-create the clone in all cases. I need to figure + // out when clone and original have the same class, so that i can use operator= + // in those cases + + // // copy all other needed stuff + // basegfx::B2DHomMatrix aMatrix; + // basegfx::B2DPolyPolygon aPolyPolygon; + // pOleObject->TRGetBaseGeometry(aMatrix, aPolyPolygon); + // pClone->TRSetBaseGeometry(aMatrix, aPolyPolygon); + + const SdrObject* pSource = &maOriginal; + + if(mpClone) + { + SdrObject::Free(mpClone); + mpClone = 0; + } + + if(mbModify) + { + if(!mpClone) + { + mpClone = maOriginal.getFullDragClone(); + } + + // apply original transformation, implemented at the DragMethods + rDragMethod.applyCurrentTransformationToSdrObject(*mpClone); + + // choose source for geometry data + pSource = mpClone; + } + + // get VOC and Primitive2DSequence + sdr::contact::ViewContact& rVC = pSource->GetViewContact(); + sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(mrObjectContact); + sdr::contact::DisplayInfo aDisplayInfo; + + // Do not use the last ViewPort set at the OC from the last ProcessDisplay(), + // here we want the complete primitive sequence without visibility clippings + mrObjectContact.resetViewPort(); + + return rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrDragEntryPrimitive2DSequence::SdrDragEntryPrimitive2DSequence( + const drawinglayer::primitive2d::Primitive2DSequence& rSequence, + bool bAddToTransparent) +: SdrDragEntry(), + maPrimitive2DSequence(rSequence) +{ + // add parts to transparent overlay stuff eventually + setAddToTransparent(bAddToTransparent); +} + +SdrDragEntryPrimitive2DSequence::~SdrDragEntryPrimitive2DSequence() +{ +} + +drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPrimitive2DSequence::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod) +{ + drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D( + new drawinglayer::primitive2d::TransformPrimitive2D( + rDragMethod.getCurrentTransformation(), + maPrimitive2DSequence)); + + return drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrDragEntryPointGlueDrag::SdrDragEntryPointGlueDrag(const std::vector< basegfx::B2DPoint >& rPositions, bool bIsPointDrag) +: maPositions(rPositions), + mbIsPointDrag(bIsPointDrag) +{ + // add SdrObject parts to transparent overlay stuff + setAddToTransparent(true); +} + +SdrDragEntryPointGlueDrag::~SdrDragEntryPointGlueDrag() +{ +} + +drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPointGlueDrag::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod) +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval; + + if(maPositions.size()) + { + basegfx::B2DPolygon aPolygon; + sal_uInt32 a(0); + + for(a = 0; a < maPositions.size(); a++) + { + aPolygon.append(maPositions[a]); + } + + basegfx::B2DPolyPolygon aPolyPolygon(aPolygon); + + rDragMethod.applyCurrentTransformationToPolyPolygon(aPolyPolygon); + + const basegfx::B2DPolygon aTransformed(aPolyPolygon.getB2DPolygon(0)); + std::vector< basegfx::B2DPoint > aTransformedPositions; + + aTransformedPositions.reserve(aTransformed.count()); + + for(a = 0; a < aTransformed.count(); a++) + { + aTransformedPositions.push_back(aTransformed.getB2DPoint(a)); + } + + if(mbIsPointDrag) + { + const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + basegfx::BColor aColor(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor()); + + if(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + aColor = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor(); + } + + drawinglayer::primitive2d::Primitive2DReference aMarkerArrayPrimitive2D( + new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions, + drawinglayer::primitive2d::createDefaultCross_3x3(aColor))); + + aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aMarkerArrayPrimitive2D, 1); + } + else + { + const basegfx::BColor aBackPen(1.0, 1.0, 1.0); + const basegfx::BColor aRGBFrontColor(0.0, 0.0, 1.0); // COL_LIGHTBLUE + drawinglayer::primitive2d::Primitive2DReference aMarkerArrayPrimitive2D( + new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions, + drawinglayer::primitive2d::createDefaultGluepoint_7x7(aBackPen, aRGBFrontColor))); + + aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aMarkerArrayPrimitive2D, 1); + } + } + + return aRetval; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT0(SdrDragMethod); + +void SdrDragMethod::resetSdrDragEntries() +{ + // clear entries; creation is on demand + clearSdrDragEntries(); +} + +basegfx::B2DRange SdrDragMethod::getCurrentRange() const +{ + return getB2DRangeFromOverlayObjectList(); +} + +void SdrDragMethod::createSdrDragEntries() +{ + if(getSdrDragView().GetSdrPageView() && getSdrDragView().GetSdrPageView()->HasMarkedObjPageView()) + { + if(getSdrDragView().IsDraggingPoints()) + { + createSdrDragEntries_PointDrag(); + } + else if(getSdrDragView().IsDraggingGluePoints()) + { + createSdrDragEntries_GlueDrag(); + } + else + { + if(getSolidDraggingActive()) + { + createSdrDragEntries_SolidDrag(); + } + else + { + createSdrDragEntries_PolygonDrag(); + } + } + } +} + +void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify) +{ + // add full obejct drag; Clone() at the object has to work + // for this + addSdrDragEntry(new SdrDragEntrySdrObject(rOriginal, rObjectContact, bModify)); +} + +void SdrDragMethod::createSdrDragEntries_SolidDrag() +{ + const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount()); + SdrPageView* pPV = getSdrDragView().GetSdrPageView(); + + if(pPV) + { + for(sal_uInt32 a(0); a < nMarkAnz; a++) + { + SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(a); + + if(pM->GetPageView() == pPV) + { + const SdrObject* pObject = pM->GetMarkedSdrObj(); + + if(pObject) + { + if(pPV->PageWindowCount()) + { + sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact(); + SdrObjListIter aIter(*pObject); + + while(aIter.IsMore()) + { + SdrObject* pCandidate = aIter.Next(); + + if(pCandidate) + { + const bool bSuppressFullDrag(!pCandidate->supportsFullDrag()); + bool bAddWireframe(bSuppressFullDrag); + + if(!bAddWireframe && !pCandidate->HasLineStyle()) + { + // add wireframe for objects without outline + bAddWireframe = true; + } + + if(!bSuppressFullDrag) + { + // add full obejct drag; Clone() at the object has to work + // for this + createSdrDragEntryForSdrObject(*pCandidate, rOC, true); + } + + if(bAddWireframe) + { + // when dragging a 50% transparent copy of a filled or not filled object without + // outline, this is normally hard to see. Add extra wireframe in that case. This + // works nice e.g. with thext frames etc. + addSdrDragEntry(new SdrDragEntryPolyPolygon(pCandidate->TakeXorPoly())); + } + } + } + } + } + } + } + } +} + +void SdrDragMethod::createSdrDragEntries_PolygonDrag() +{ + const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount()); + bool bNoPolygons(getSdrDragView().IsNoDragXorPolys() || nMarkAnz > getSdrDragView().GetDragXorPolyLimit()); + basegfx::B2DPolyPolygon aResult; + sal_uInt32 nPointCount(0); + + for(sal_uInt32 a(0); !bNoPolygons && a < nMarkAnz; a++) + { + SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(a); + + if(pM->GetPageView() == getSdrDragView().GetSdrPageView()) + { + const basegfx::B2DPolyPolygon aNewPolyPolygon(pM->GetMarkedSdrObj()->TakeXorPoly()); + + for(sal_uInt32 b(0); b < aNewPolyPolygon.count(); b++) + { + nPointCount += aNewPolyPolygon.getB2DPolygon(b).count(); + } + + if(nPointCount > getSdrDragView().GetDragXorPointLimit()) + { + bNoPolygons = true; + } + + if(!bNoPolygons) + { + aResult.append(aNewPolyPolygon); + } + } + } + + if(bNoPolygons) + { + const Rectangle aR(getSdrDragView().GetSdrPageView()->MarkSnap()); + const basegfx::B2DRange aNewRectangle(aR.Left(), aR.Top(), aR.Right(), aR.Bottom()); + basegfx::B2DPolygon aNewPolygon(basegfx::tools::createPolygonFromRect(aNewRectangle)); + + aResult = basegfx::B2DPolyPolygon(basegfx::tools::expandToCurve(aNewPolygon)); + } + + if(aResult.count()) + { + addSdrDragEntry(new SdrDragEntryPolyPolygon(aResult)); + } +} + +void SdrDragMethod::createSdrDragEntries_PointDrag() +{ + const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount()); + std::vector< basegfx::B2DPoint > aPositions; + + for(sal_uInt32 nm(0); nm < nMarkAnz; nm++) + { + SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(nm); + + if(pM->GetPageView() == getSdrDragView().GetSdrPageView()) + { + const SdrUShortCont* pPts = pM->GetMarkedPoints(); + + if(pPts && pPts->GetCount()) + { + const SdrObject* pObj = pM->GetMarkedSdrObj(); + const SdrPathObj* pPath = dynamic_cast< const SdrPathObj* >(pObj); + + if(pPath) + { + const basegfx::B2DPolyPolygon aPathXPP = pPath->GetPathPoly(); + + if(aPathXPP.count()) + { + const sal_uInt32 nPtAnz(pPts->GetCount()); + + for(sal_uInt32 nPtNum(0); nPtNum < nPtAnz; nPtNum++) + { + sal_uInt32 nPolyNum, nPointNum; + const sal_uInt16 nObjPt(pPts->GetObject(nPtNum)); + + if(sdr::PolyPolygonEditor::GetRelativePolyPoint(aPathXPP, nObjPt, nPolyNum, nPointNum)) + { + aPositions.push_back(aPathXPP.getB2DPolygon(nPolyNum).getB2DPoint(nPointNum)); + } + } + } + } + } + } + } + + if(aPositions.size()) + { + addSdrDragEntry(new SdrDragEntryPointGlueDrag(aPositions, true)); + } +} + +void SdrDragMethod::createSdrDragEntries_GlueDrag() +{ + const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount()); + std::vector< basegfx::B2DPoint > aPositions; + + for(sal_uInt32 nm(0); nm < nMarkAnz; nm++) + { + SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(nm); + + if(pM->GetPageView() == getSdrDragView().GetSdrPageView()) + { + const SdrUShortCont* pPts = pM->GetMarkedGluePoints(); + + if(pPts && pPts->GetCount()) + { + const SdrObject* pObj = pM->GetMarkedSdrObj(); + const SdrGluePointList* pGPL = pObj->GetGluePointList(); + + if(pGPL) + { + const sal_uInt32 nPtAnz(pPts->GetCount()); + + for(sal_uInt32 nPtNum(0); nPtNum < nPtAnz; nPtNum++) + { + const sal_uInt16 nObjPt(pPts->GetObject(nPtNum)); + const sal_uInt16 nGlueNum(pGPL->FindGluePoint(nObjPt)); + + if(SDRGLUEPOINT_NOTFOUND != nGlueNum) + { + const Point aPoint((*pGPL)[nGlueNum].GetAbsolutePos(*pObj)); + aPositions.push_back(basegfx::B2DPoint(aPoint.X(), aPoint.Y())); + } + } + } + } + } + } + + if(aPositions.size()) + { + addSdrDragEntry(new SdrDragEntryPointGlueDrag(aPositions, false)); + } +} + +void SdrDragMethod::ImpTakeDescriptionStr(sal_uInt16 nStrCacheID, XubString& rStr, sal_uInt16 nVal) const +{ + sal_uInt16 nOpt=0; + if (IsDraggingPoints()) { + nOpt=IMPSDR_POINTSDESCRIPTION; + } else if (IsDraggingGluePoints()) { + nOpt=IMPSDR_GLUEPOINTSDESCRIPTION; + } + getSdrDragView().ImpTakeDescriptionStr(nStrCacheID,rStr,nVal,nOpt); +} + +SdrObject* SdrDragMethod::GetDragObj() const +{ + SdrObject* pObj=NULL; + if (getSdrDragView().pDragHdl!=NULL) pObj=getSdrDragView().pDragHdl->GetObj(); + if (pObj==NULL) pObj=getSdrDragView().pMarkedObj; + return pObj; +} + +SdrPageView* SdrDragMethod::GetDragPV() const +{ + SdrPageView* pPV=NULL; + if (getSdrDragView().pDragHdl!=NULL) pPV=getSdrDragView().pDragHdl->GetPageView(); + if (pPV==NULL) pPV=getSdrDragView().pMarkedPV; + return pPV; +} + +void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + // the original applies the transformation using TRGetBaseGeometry/TRSetBaseGeometry. + // Later this should be the only needed one for linear transforms (not for SdrDragCrook and + // SdrDragDistort, those are NOT linear). Currently, this can not yet be used since the + // special handling of rotate/mirror due to the not-being-able to handle it in the old + // drawinglayer stuff. Text would currently not correctly be mirrored in the preview. + basegfx::B2DHomMatrix aObjectTransform; + basegfx::B2DPolyPolygon aObjectPolyPolygon; + bool bPolyUsed(rTarget.TRGetBaseGeometry(aObjectTransform, aObjectPolyPolygon)); + + // apply transform to object transform + aObjectTransform *= getCurrentTransformation(); + + if(bPolyUsed) + { + // do something special since the object size is in the polygon + // break up matrix to get the scale + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate, fShearX; + aObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX); + + // get polygon's pos and size + const basegfx::B2DRange aPolyRange(aObjectPolyPolygon.getB2DRange()); + + // get the scaling factors (do not mirror, this is in the object transformation) + const double fScaleX(fabs(aScale.getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth())); + const double fScaleY(fabs(aScale.getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight())); + + // prepare transform matrix for polygon + basegfx::B2DHomMatrix aPolyTransform(basegfx::tools::createTranslateB2DHomMatrix( + -aPolyRange.getMinX(), -aPolyRange.getMinY())); + aPolyTransform.scale(fScaleX, fScaleY); + + // normally the poly should be moved back, but the translation is in the object + // transformation and thus does not need to be done + // aPolyTransform.translate(-aPolyRange.getMinX(), -aPolyRange.getMinY()); + + // transform the polygon + aObjectPolyPolygon.transform(aPolyTransform); + } + + rTarget.TRSetBaseGeometry(getCurrentTransformation() * aObjectTransform, aObjectPolyPolygon); +} + +void SdrDragMethod::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget) +{ + // original uses CurrentTransformation + rTarget.transform(getCurrentTransformation()); +} + +SdrDragMethod::SdrDragMethod(SdrDragView& rNewView) +: maSdrDragEntries(), + maOverlayObjectList(), + mrSdrDragView(rNewView), + mbMoveOnly(false), + mbSolidDraggingActive(getSdrDragView().IsSolidDragging()) +{ + if(mbSolidDraggingActive && Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + // fallback to wireframe when high contrast is used + mbSolidDraggingActive = false; + } +} + +SdrDragMethod::~SdrDragMethod() +{ + clearSdrDragEntries(); +} + +void SdrDragMethod::Show() +{ + getSdrDragView().ShowDragObj(); +} + +void SdrDragMethod::Hide() +{ + getSdrDragView().HideDragObj(); +} + +basegfx::B2DHomMatrix SdrDragMethod::getCurrentTransformation() +{ + return basegfx::B2DHomMatrix(); +} + +void SdrDragMethod::CancelSdrDrag() +{ + Hide(); +} + +void SdrDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager) +{ + // create SdrDragEntries on demand + if(!maSdrDragEntries.size()) + { + createSdrDragEntries(); + } + + // if there are entries, derive OverlayObjects from the entries, including + // modification from current interactive state + if(maSdrDragEntries.size()) + { + drawinglayer::primitive2d::Primitive2DSequence aResult; + drawinglayer::primitive2d::Primitive2DSequence aResultTransparent; + + for(sal_uInt32 a(0); a < maSdrDragEntries.size(); a++) + { + SdrDragEntry* pCandidate = maSdrDragEntries[a]; + + if(pCandidate) + { + const drawinglayer::primitive2d::Primitive2DSequence aCandidateResult(pCandidate->createPrimitive2DSequenceInCurrentState(*this)); + + if(aCandidateResult.hasElements()) + { + if(pCandidate->getAddToTransparent()) + { + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResultTransparent, aCandidateResult); + } + else + { + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResult, aCandidateResult); + } + } + } + } + + if(DoAddConnectorOverlays()) + { + const drawinglayer::primitive2d::Primitive2DSequence aConnectorOverlays(AddConnectorOverlays()); + + if(aConnectorOverlays.hasElements()) + { + // add connector overlays to transparent part + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResultTransparent, aConnectorOverlays); + } + } + + if(aResult.hasElements()) + { + sdr::overlay::OverlayObject* pNewOverlayObject = new sdr::overlay::OverlayPrimitive2DSequenceObject(aResult); + rOverlayManager.add(*pNewOverlayObject); + addToOverlayObjectList(*pNewOverlayObject); + } + + if(aResultTransparent.hasElements()) + { + drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aResultTransparent, 0.5)); + aResultTransparent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D, 1); + + sdr::overlay::OverlayObject* pNewOverlayObject = new sdr::overlay::OverlayPrimitive2DSequenceObject(aResultTransparent); + rOverlayManager.add(*pNewOverlayObject); + addToOverlayObjectList(*pNewOverlayObject); + } + } + + // evtl add DragStripes (help lines cross the page when dragging) + if(getSdrDragView().IsDragStripes()) + { + Rectangle aActionRectangle; + getSdrDragView().TakeActionRect(aActionRectangle); + + const basegfx::B2DPoint aTopLeft(aActionRectangle.Left(), aActionRectangle.Top()); + const basegfx::B2DPoint aBottomRight(aActionRectangle.Right(), aActionRectangle.Bottom()); + sdr::overlay::OverlayRollingRectangleStriped* pNew = new sdr::overlay::OverlayRollingRectangleStriped( + aTopLeft, aBottomRight, true, false); + + rOverlayManager.add(*pNew); + addToOverlayObjectList(*pNew); + } +} + +void SdrDragMethod::destroyOverlayGeometry() +{ + clearOverlayObjectList(); +} + +bool SdrDragMethod::DoAddConnectorOverlays() +{ + // these conditions are translated from SdrDragView::ImpDrawEdgeXor + const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes(); + + if(!rMarkedNodes.GetMarkCount()) + { + return false; + } + + if(!getSdrDragView().IsRubberEdgeDragging() && !getSdrDragView().IsDetailedEdgeDragging()) + { + return false; + } + + if(getSdrDragView().IsDraggingPoints() || getSdrDragView().IsDraggingGluePoints()) + { + return false; + } + + if(!getMoveOnly() && !( + IS_TYPE(SdrDragMove, this) || IS_TYPE(SdrDragResize, this) || + IS_TYPE(SdrDragRotate,this) || IS_TYPE(SdrDragMirror,this))) + { + return false; + } + + const bool bDetail(getSdrDragView().IsDetailedEdgeDragging() && getMoveOnly()); + + if(!bDetail && !getSdrDragView().IsRubberEdgeDragging()) + { + return false; + } + + // one more migrated from SdrEdgeObj::NspToggleEdgeXor + if(IS_TYPE(SdrDragObjOwn, this) || IS_TYPE(SdrDragMovHdl, this)) + { + return false; + } + + return true; +} + +drawinglayer::primitive2d::Primitive2DSequence SdrDragMethod::AddConnectorOverlays() +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval; + const bool bDetail(getSdrDragView().IsDetailedEdgeDragging() && getMoveOnly()); + const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes(); + + for(sal_uInt16 a(0); a < rMarkedNodes.GetMarkCount(); a++) + { + SdrMark* pEM = rMarkedNodes.GetMark(a); + + if(pEM && pEM->GetMarkedSdrObj()) + { + SdrEdgeObj* pEdge = dynamic_cast< SdrEdgeObj* >(pEM->GetMarkedSdrObj()); + + if(pEdge) + { + const basegfx::B2DPolygon aEdgePolygon(pEdge->ImplAddConnectorOverlay(*this, pEM->IsCon1(), pEM->IsCon2(), bDetail)); + + if(aEdgePolygon.count()) + { + // this polygon is a temporary calculated connector path, so it is not possible to fetch + // the needed primitives directly from the pEdge object which does not get changed. If full + // drag is on, use the SdrObjects ItemSet to create a adequate representation + bool bUseSolidDragging(getSolidDraggingActive()); + + if(bUseSolidDragging) + { + // switch off solid dragging if connector is not visible + if(!pEdge->HasLineStyle()) + { + bUseSolidDragging = false; + } + } + + if(bUseSolidDragging) + { + const SfxItemSet& rItemSet = pEdge->GetMergedItemSet(); + const drawinglayer::attribute::SdrLineAttribute aLine( + drawinglayer::primitive2d::createNewSdrLineAttribute(rItemSet)); + + if(!aLine.isDefault()) + { + const drawinglayer::attribute::SdrLineStartEndAttribute aLineStartEnd( + drawinglayer::primitive2d::createNewSdrLineStartEndAttribute( + rItemSet, + aLine.getWidth())); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + aRetval, drawinglayer::primitive2d::createPolygonLinePrimitive( + aEdgePolygon, + basegfx::B2DHomMatrix(), + aLine, + aLineStartEnd)); + } + } + else + { + const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + basegfx::BColor aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor()); + basegfx::BColor aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor()); + const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength()); + + if(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor(); + aColB.invert(); + } + + drawinglayer::primitive2d::Primitive2DReference aPolyPolygonMarkerPrimitive2D( + new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D( + basegfx::B2DPolyPolygon(aEdgePolygon), aColA, aColB, fStripeLength)); + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aPolyPolygonMarkerPrimitive2D); + } + } + } + } + } + + return aRetval; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragMovHdl,SdrDragMethod); + +SdrDragMovHdl::SdrDragMovHdl(SdrDragView& rNewView) +: SdrDragMethod(rNewView), + bMirrObjShown(false) +{ +} + +void SdrDragMovHdl::createSdrDragEntries() +{ + // SdrDragMovHdl does not use the default drags, + // but creates nothing +} + +void SdrDragMovHdl::TakeSdrDragComment(XubString& rStr) const +{ + rStr=ImpGetResStr(STR_DragMethMovHdl); + if (getSdrDragView().IsDragWithCopy()) rStr+=ImpGetResStr(STR_EditWithCopy); +} + +bool SdrDragMovHdl::BeginSdrDrag() +{ + DragStat().Ref1()=GetDragHdl()->GetPos(); + DragStat().SetShown(!DragStat().IsShown()); + SdrHdlKind eKind=GetDragHdl()->GetKind(); + SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1); + SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2); + + if (eKind==HDL_MIRX) + { + if (pH1==NULL || pH2==NULL) + { + DBG_ERROR("SdrDragMovHdl::BeginSdrDrag(): Verschieben der Spiegelachse: Referenzhandles nicht gefunden"); + return false; + } + + DragStat().SetActionRect(Rectangle(pH1->GetPos(),pH2->GetPos())); + } + else + { + Point aPt(GetDragHdl()->GetPos()); + DragStat().SetActionRect(Rectangle(aPt,aPt)); + } + + return true; +} + +void SdrDragMovHdl::MoveSdrDrag(const Point& rNoSnapPnt) +{ + Point aPnt(rNoSnapPnt); + + if (DragStat().CheckMinMoved(rNoSnapPnt)) + { + if (GetDragHdl()->GetKind()==HDL_MIRX) + { + SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1); + SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2); + + if (pH1==NULL || pH2==NULL) + return; + + if (!DragStat().IsNoSnap()) + { + long nBestXSnap=0; + long nBestYSnap=0; + bool bXSnapped=false; + bool bYSnapped=false; + Point aDif(aPnt-DragStat().GetStart()); + getSdrDragView().CheckSnap(Ref1()+aDif,NULL,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped); + getSdrDragView().CheckSnap(Ref2()+aDif,NULL,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped); + aPnt.X()+=nBestXSnap; + aPnt.Y()+=nBestYSnap; + } + + if (aPnt!=DragStat().GetNow()) + { + Hide(); + DragStat().NextMove(aPnt); + Point aDif(DragStat().GetNow()-DragStat().GetStart()); + pH1->SetPos(Ref1()+aDif); + pH2->SetPos(Ref2()+aDif); + + SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX); + + if(pHM) + pHM->Touch(); + + Show(); + DragStat().SetActionRect(Rectangle(pH1->GetPos(),pH2->GetPos())); + } + } + else + { + if (!DragStat().IsNoSnap()) SnapPos(aPnt); + long nSA=0; + + if (getSdrDragView().IsAngleSnapEnabled()) + nSA=getSdrDragView().GetSnapAngle(); + + if (getSdrDragView().IsMirrorAllowed(true,true)) + { // eingeschraenkt + if (!getSdrDragView().IsMirrorAllowed(false,false)) nSA=4500; + if (!getSdrDragView().IsMirrorAllowed(true,false)) nSA=9000; + } + + if (getSdrDragView().IsOrtho() && nSA!=9000) + nSA=4500; + + if (nSA!=0) + { // Winkelfang + SdrHdlKind eRef=HDL_REF1; + + if (GetDragHdl()->GetKind()==HDL_REF1) + eRef=HDL_REF2; + + SdrHdl* pH=GetHdlList().GetHdl(eRef); + + if (pH!=NULL) + { + Point aRef(pH->GetPos()); + long nWink=NormAngle360(GetAngle(aPnt-aRef)); + long nNeuWink=nWink; + nNeuWink+=nSA/2; + nNeuWink/=nSA; + nNeuWink*=nSA; + nNeuWink=NormAngle360(nNeuWink); + double a=(nNeuWink-nWink)*nPi180; + double nSin=sin(a); + double nCos=cos(a); + RotatePoint(aPnt,aRef,nSin,nCos); + + // Bei bestimmten Werten Rundungsfehler ausschliessen: + if (nSA==9000) + { + if (nNeuWink==0 || nNeuWink==18000) aPnt.Y()=aRef.Y(); + if (nNeuWink==9000 || nNeuWink==27000) aPnt.X()=aRef.X(); + } + + if (nSA==4500) + OrthoDistance8(aRef,aPnt,true); + } + } + + if (aPnt!=DragStat().GetNow()) + { + Hide(); + DragStat().NextMove(aPnt); + GetDragHdl()->SetPos(DragStat().GetNow()); + SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX); + + if(pHM) + pHM->Touch(); + + Show(); + DragStat().SetActionRect(Rectangle(aPnt,aPnt)); + } + } + } +} + +bool SdrDragMovHdl::EndSdrDrag(bool /*bCopy*/) +{ + switch (GetDragHdl()->GetKind()) + { + case HDL_REF1: + Ref1()=DragStat().GetNow(); + break; + + case HDL_REF2: + Ref2()=DragStat().GetNow(); + break; + + case HDL_MIRX: + Ref1()+=DragStat().GetNow()-DragStat().GetStart(); + Ref2()+=DragStat().GetNow()-DragStat().GetStart(); + break; + + default: break; + } + + return true; +} + +void SdrDragMovHdl::CancelSdrDrag() +{ + Hide(); + GetDragHdl()->SetPos(DragStat().GetRef1()); + SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX); + + if(pHM) + pHM->Touch(); +} + +Pointer SdrDragMovHdl::GetSdrDragPointer() const +{ + const SdrHdl* pHdl = GetDragHdl(); + + if (pHdl!=NULL) + { + return pHdl->GetPointer(); + } + + return Pointer(POINTER_REFHAND); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragObjOwn,SdrDragMethod); + +SdrDragObjOwn::SdrDragObjOwn(SdrDragView& rNewView) +: SdrDragMethod(rNewView), + mpClone(0) +{ + const SdrObject* pObj = GetDragObj(); + + if(pObj) + { + // suppress full drag for some object types + setSolidDraggingActive(pObj->supportsFullDrag()); + } +} + +SdrDragObjOwn::~SdrDragObjOwn() +{ + if(mpClone) + { + SdrObject::Free(mpClone); + } +} + +void SdrDragObjOwn::createSdrDragEntries() +{ + if(mpClone) + { + basegfx::B2DPolyPolygon aDragPolyPolygon; + bool bAddWireframe(true); + + if(getSolidDraggingActive()) + { + SdrPageView* pPV = getSdrDragView().GetSdrPageView(); + + if(pPV && pPV->PageWindowCount()) + { + sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact(); + addSdrDragEntry(new SdrDragEntrySdrObject(*mpClone, rOC, false)); + + // potentially no wireframe needed, full drag works + bAddWireframe = false; + } + } + + if(!bAddWireframe) + { + // check for extra conditions for wireframe, e.g. no border at + // objects + if(!mpClone->HasLineStyle()) + { + bAddWireframe = true; + } + } + + if(bAddWireframe) + { + // use wireframe poly when full drag is off or did not work + aDragPolyPolygon = mpClone->TakeXorPoly(); + } + + // add evtl. extra DragPolyPolygon + const basegfx::B2DPolyPolygon aSpecialDragPolyPolygon(mpClone->getSpecialDragPoly(DragStat())); + + if(aSpecialDragPolyPolygon.count()) + { + aDragPolyPolygon.append(aSpecialDragPolyPolygon); + } + + if(aDragPolyPolygon.count()) + { + addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragPolyPolygon)); + } + } +} + +void SdrDragObjOwn::TakeSdrDragComment(XubString& rStr) const +{ + // #i103058# get info string from the clone preferred, the original will + // not be changed. For security, use original as fallback + if(mpClone) + { + rStr = mpClone->getSpecialDragComment(DragStat()); + } + else + { + const SdrObject* pObj = GetDragObj(); + + if(pObj) + { + rStr = pObj->getSpecialDragComment(DragStat()); + } + } +} + +bool SdrDragObjOwn::BeginSdrDrag() +{ + if(!mpClone) + { + const SdrObject* pObj = GetDragObj(); + + if(pObj && !pObj->IsResizeProtect()) + { + if(pObj->beginSpecialDrag(DragStat())) + { + // create nitial clone to have a start visualisation + mpClone = pObj->getFullDragClone(); + mpClone->applySpecialDrag(DragStat()); + + return true; + } + } + } + + return false; +} + +void SdrDragObjOwn::MoveSdrDrag(const Point& rNoSnapPnt) +{ + const SdrObject* pObj = GetDragObj(); + + if(pObj) + { + Point aPnt(rNoSnapPnt); + SdrPageView* pPV = GetDragPV(); + + if(pPV) + { + if(!DragStat().IsNoSnap()) + { + SnapPos(aPnt); + } + + if(getSdrDragView().IsOrtho()) + { + if (DragStat().IsOrtho8Possible()) + { + OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho()); + } + else if (DragStat().IsOrtho4Possible()) + { + OrthoDistance4(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho()); + } + } + + if(DragStat().CheckMinMoved(rNoSnapPnt)) + { + if(aPnt != DragStat().GetNow()) + { + Hide(); + DragStat().NextMove(aPnt); + + // since SdrDragObjOwn currently supports no transformation of + // existing SdrDragEntries but only their recreation, a recreation + // after every move is needed in this mode. Delete existing + // SdrDragEntries here to force their recreation in the following Show(). + clearSdrDragEntries(); + + // delete current clone (after the last reference to it is deleted above) + if(mpClone) + { + SdrObject::Free(mpClone); + mpClone = 0; + } + + // create a new clone and modify to current drag state + if(!mpClone) + { + mpClone = pObj->getFullDragClone(); + mpClone->applySpecialDrag(DragStat()); + } + + Show(); + } + } + } + } +} + +bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/) +{ + Hide(); + SdrUndoAction* pUndo = NULL; + SdrUndoAction* pUndo2 = NULL; + std::vector< SdrUndoAction* > vConnectorUndoActions; + bool bRet = false; + SdrObject* pObj = GetDragObj(); + + if(pObj) + { + const bool bUndo = getSdrDragView().IsUndoEnabled(); + + if( bUndo ) + { + if(!getSdrDragView().IsInsObjPoint() && pObj->IsInserted() ) + { + if (DragStat().IsEndDragChangesAttributes()) + { + pUndo=getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj); + + if (DragStat().IsEndDragChangesGeoAndAttributes()) + { + vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj ); + pUndo2 = getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj); + } + } + else + { + vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj ); + pUndo= getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj); + } + } + + if( pUndo ) + { + getSdrDragView().BegUndo( pUndo->GetComment() ); + } + else + { + getSdrDragView().BegUndo(); + } + } + + // evtl. use opertator= for setting changed object data (do not change selection in + // view, this will destroy the interactor). This is possible since a clone is now + // directly modified by the modifiers. Only SdrTableObj is adding own UNDOs + // in it's SdrTableObj::endSpecialDrag, so currently not possible. OTOH it uses + // a CreateUndoGeoObject() so maybe setting SetEndDragChangesAttributes is okay. I + // will test this now + Rectangle aBoundRect0; + + if(pObj->GetUserCall()) + { + aBoundRect0 = pObj->GetLastBoundRect(); + } + + bRet = pObj->applySpecialDrag(DragStat()); + + if(bRet) + { + pObj->SetChanged(); + pObj->BroadcastObjectChange(); + pObj->SendUserCall( SDRUSERCALL_RESIZE, aBoundRect0 ); + } + + if(bRet) + { + if( bUndo ) + { + getSdrDragView().AddUndoActions( vConnectorUndoActions ); + + if ( pUndo ) + { + getSdrDragView().AddUndo(pUndo); + } + + if ( pUndo2 ) + { + getSdrDragView().AddUndo(pUndo2); + } + } + } + else + { + if( bUndo ) + { + std::vector< SdrUndoAction* >::iterator vConnectorUndoIter( vConnectorUndoActions.begin() ); + + while( vConnectorUndoIter != vConnectorUndoActions.end() ) + { + delete *vConnectorUndoIter++; + } + + delete pUndo; + delete pUndo2; + } + } + + if( bUndo ) + getSdrDragView().EndUndo(); + } + + return bRet; +} + +Pointer SdrDragObjOwn::GetSdrDragPointer() const +{ + const SdrHdl* pHdl=GetDragHdl(); + + if (pHdl) + { + return pHdl->GetPointer(); + } + + return Pointer(POINTER_MOVE); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragMove,SdrDragMethod); + +void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool /*bModify*/) +{ + // for SdrDragMove, use current Primitive2DSequence of SdrObject visualisation + // in given ObjectContact directly + sdr::contact::ViewContact& rVC = rOriginal.GetViewContact(); + sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rObjectContact); + sdr::contact::DisplayInfo aDisplayInfo; + + // Do not use the last ViewPort set at the OC from the last ProcessDisplay(), + // here we want the complete primitive sequence without visibility clippings + rObjectContact.resetViewPort(); + + addSdrDragEntry(new SdrDragEntryPrimitive2DSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo), true)); +} + +void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + rTarget.Move(Size(DragStat().GetDX(), DragStat().GetDY())); +} + +SdrDragMove::SdrDragMove(SdrDragView& rNewView) +: SdrDragMethod(rNewView) +{ + setMoveOnly(true); +} + +void SdrDragMove::TakeSdrDragComment(XubString& rStr) const +{ + XubString aStr; + + ImpTakeDescriptionStr(STR_DragMethMove, rStr); + rStr.AppendAscii(" (x="); + getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr); + rStr += aStr; + rStr.AppendAscii(" y="); + getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr); + rStr += aStr; + rStr += sal_Unicode(')'); + + if(getSdrDragView().IsDragWithCopy()) + { + if(!getSdrDragView().IsInsObjPoint() && !getSdrDragView().IsInsGluePoint()) + { + rStr += ImpGetResStr(STR_EditWithCopy); + } + } +} + +bool SdrDragMove::BeginSdrDrag() +{ + DragStat().SetActionRect(GetMarkedRect()); + Show(); + + return true; +} + +basegfx::B2DHomMatrix SdrDragMove::getCurrentTransformation() +{ + return basegfx::tools::createTranslateB2DHomMatrix(DragStat().GetDX(), DragStat().GetDY()); +} + +void SdrDragMove::ImpCheckSnap(const Point& rPt) +{ + Point aPt(rPt); + sal_uInt16 nRet=SnapPos(aPt); + aPt-=rPt; + + if ((nRet & SDRSNAP_XSNAPPED) !=0) + { + if (bXSnapped) + { + if (Abs(aPt.X())<Abs(nBestXSnap)) + { + nBestXSnap=aPt.X(); + } + } + else + { + nBestXSnap=aPt.X(); + bXSnapped=true; + } + } + + if ((nRet & SDRSNAP_YSNAPPED) !=0) + { + if (bYSnapped) + { + if (Abs(aPt.Y())<Abs(nBestYSnap)) + { + nBestYSnap=aPt.Y(); + } + } + else + { + nBestYSnap=aPt.Y(); + bYSnapped=true; + } + } +} + +void SdrDragMove::MoveSdrDrag(const Point& rNoSnapPnt_) +{ + nBestXSnap=0; + nBestYSnap=0; + bXSnapped=false; + bYSnapped=false; + Point aNoSnapPnt(rNoSnapPnt_); + const Rectangle& aSR=GetMarkedRect(); + long nMovedx=aNoSnapPnt.X()-DragStat().GetStart().X(); + long nMovedy=aNoSnapPnt.Y()-DragStat().GetStart().Y(); + Point aLO(aSR.TopLeft()); aLO.X()+=nMovedx; aLO.Y()+=nMovedy; + Point aRU(aSR.BottomRight()); aRU.X()+=nMovedx; aRU.Y()+=nMovedy; + Point aLU(aLO.X(),aRU.Y()); + Point aRO(aRU.X(),aLO.Y()); + ImpCheckSnap(aLO); + + if (!getSdrDragView().IsMoveSnapOnlyTopLeft()) + { + ImpCheckSnap(aRO); + ImpCheckSnap(aLU); + ImpCheckSnap(aRU); + } + + Point aPnt(aNoSnapPnt.X()+nBestXSnap,aNoSnapPnt.Y()+nBestYSnap); + bool bOrtho=getSdrDragView().IsOrtho(); + + if (bOrtho) + OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho()); + + if (DragStat().CheckMinMoved(aNoSnapPnt)) + { + Point aPt1(aPnt); + Rectangle aLR(getSdrDragView().GetWorkArea()); + bool bWorkArea=!aLR.IsEmpty(); + bool bDragLimit=IsDragLimit(); + + if (bDragLimit || bWorkArea) + { + Rectangle aSR2(GetMarkedRect()); + Point aD(aPt1-DragStat().GetStart()); + + if (bDragLimit) + { + Rectangle aR2(GetDragLimitRect()); + + if (bWorkArea) + aLR.Intersection(aR2); + else + aLR=aR2; + } + + if (aSR2.Left()>aLR.Left() || aSR2.Right()<aLR.Right()) + { // ist ueberhaupt Platz zum verschieben? + aSR2.Move(aD.X(),0); + + if (aSR2.Left()<aLR.Left()) + { + aPt1.X()-=aSR2.Left()-aLR.Left(); + } + else if (aSR2.Right()>aLR.Right()) + { + aPt1.X()-=aSR2.Right()-aLR.Right(); + } + } + else + aPt1.X()=DragStat().GetStart().X(); // kein Platz zum verschieben + + if (aSR2.Top()>aLR.Top() || aSR2.Bottom()<aLR.Bottom()) + { // ist ueberhaupt Platz zum verschieben? + aSR2.Move(0,aD.Y()); + + if (aSR2.Top()<aLR.Top()) + { + aPt1.Y()-=aSR2.Top()-aLR.Top(); + } + else if (aSR2.Bottom()>aLR.Bottom()) + { + aPt1.Y()-=aSR2.Bottom()-aLR.Bottom(); + } + } + else + aPt1.Y()=DragStat().GetStart().Y(); // kein Platz zum verschieben + } + + if (getSdrDragView().IsDraggingGluePoints()) + { // Klebepunkte aufs BoundRect des Obj limitieren + aPt1-=DragStat().GetStart(); + const SdrMarkList& rML=GetMarkedObjectList(); + ULONG nMarkAnz=rML.GetMarkCount(); + + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) + { + const SdrMark* pM=rML.GetMark(nMarkNum); + const SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + ULONG nPtAnz=pPts==NULL ? 0 : pPts->GetCount(); + + if (nPtAnz!=0) + { + const SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + Rectangle aBound(pObj->GetCurrentBoundRect()); + + for (ULONG nPtNum=0; nPtNum<nPtAnz; nPtNum++) + { + sal_uInt16 nId=pPts->GetObject(nPtNum); + sal_uInt16 nGlueNum=pGPL->FindGluePoint(nId); + + if (nGlueNum!=SDRGLUEPOINT_NOTFOUND) + { + Point aPt((*pGPL)[nGlueNum].GetAbsolutePos(*pObj)); + aPt+=aPt1; // soviel soll verschoben werden + if (aPt.X()<aBound.Left() ) aPt1.X()-=aPt.X()-aBound.Left() ; + if (aPt.X()>aBound.Right() ) aPt1.X()-=aPt.X()-aBound.Right() ; + if (aPt.Y()<aBound.Top() ) aPt1.Y()-=aPt.Y()-aBound.Top() ; + if (aPt.Y()>aBound.Bottom()) aPt1.Y()-=aPt.Y()-aBound.Bottom(); + } + } + } + } + + aPt1+=DragStat().GetStart(); + } + + if (bOrtho) + OrthoDistance8(DragStat().GetStart(),aPt1,false); + + if (aPt1!=DragStat().GetNow()) + { + Hide(); + DragStat().NextMove(aPt1); + Rectangle aAction(GetMarkedRect()); + aAction.Move(DragStat().GetDX(),DragStat().GetDY()); + DragStat().SetActionRect(aAction); + Show(); + } + } +} + +bool SdrDragMove::EndSdrDrag(bool bCopy) +{ + Hide(); + + if (getSdrDragView().IsInsObjPoint() || getSdrDragView().IsInsGluePoint()) + bCopy=false; + + if (IsDraggingPoints()) + { + getSdrDragView().MoveMarkedPoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy); + } + else if (IsDraggingGluePoints()) + { + getSdrDragView().MoveMarkedGluePoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy); + } + else + { + getSdrDragView().MoveMarkedObj(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy); + } + + return true; +} + +Pointer SdrDragMove::GetSdrDragPointer() const +{ + if (IsDraggingPoints() || IsDraggingGluePoints()) + { + return Pointer(POINTER_MOVEPOINT); + } + else + { + return Pointer(POINTER_MOVE); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragResize,SdrDragMethod); + +SdrDragResize::SdrDragResize(SdrDragView& rNewView) +: SdrDragMethod(rNewView), + aXFact(1,1), + aYFact(1,1) +{ +} + +void SdrDragResize::TakeSdrDragComment(XubString& rStr) const +{ + ImpTakeDescriptionStr(STR_DragMethResize, rStr); + bool bEqual(aXFact == aYFact); + Fraction aFact1(1,1); + Point aStart(DragStat().GetStart()); + Point aRef(DragStat().GetRef1()); + INT32 nXDiv(aStart.X() - aRef.X()); + + if(!nXDiv) + nXDiv = 1; + + INT32 nYDiv(aStart.Y() - aRef.Y()); + + if(!nYDiv) + nYDiv = 1; + + bool bX(aXFact != aFact1 && Abs(nXDiv) > 1); + bool bY(aYFact != aFact1 && Abs(nYDiv) > 1); + + if(bX || bY) + { + XubString aStr; + + rStr.AppendAscii(" ("); + + if(bX) + { + if(!bEqual) + rStr.AppendAscii("x="); + + getSdrDragView().GetModel()->TakePercentStr(aXFact, aStr); + rStr += aStr; + } + + if(bY && !bEqual) + { + if(bX) + rStr += sal_Unicode(' '); + + rStr.AppendAscii("y="); + getSdrDragView().GetModel()->TakePercentStr(aYFact, aStr); + rStr += aStr; + } + + rStr += sal_Unicode(')'); + } + + if(getSdrDragView().IsDragWithCopy()) + rStr += ImpGetResStr(STR_EditWithCopy); +} + +bool SdrDragResize::BeginSdrDrag() +{ + SdrHdlKind eRefHdl=HDL_MOVE; + SdrHdl* pRefHdl=NULL; + + switch (GetDragHdlKind()) + { + case HDL_UPLFT: eRefHdl=HDL_LWRGT; break; + case HDL_UPPER: eRefHdl=HDL_LOWER; DragStat().SetHorFixed(true); break; + case HDL_UPRGT: eRefHdl=HDL_LWLFT; break; + case HDL_LEFT : eRefHdl=HDL_RIGHT; DragStat().SetVerFixed(true); break; + case HDL_RIGHT: eRefHdl=HDL_LEFT ; DragStat().SetVerFixed(true); break; + case HDL_LWLFT: eRefHdl=HDL_UPRGT; break; + case HDL_LOWER: eRefHdl=HDL_UPPER; DragStat().SetHorFixed(true); break; + case HDL_LWRGT: eRefHdl=HDL_UPLFT; break; + default: break; + } + + if (eRefHdl!=HDL_MOVE) + pRefHdl=GetHdlList().GetHdl(eRefHdl); + + if (pRefHdl!=NULL && !getSdrDragView().IsResizeAtCenter()) + { + DragStat().Ref1()=pRefHdl->GetPos(); + } + else + { + SdrHdl* pRef1=GetHdlList().GetHdl(HDL_UPLFT); + SdrHdl* pRef2=GetHdlList().GetHdl(HDL_LWRGT); + + if (pRef1!=NULL && pRef2!=NULL) + { + DragStat().Ref1()=Rectangle(pRef1->GetPos(),pRef2->GetPos()).Center(); + } + else + { + DragStat().Ref1()=GetMarkedRect().Center(); + } + } + + Show(); + + return true; +} + +basegfx::B2DHomMatrix SdrDragResize::getCurrentTransformation() +{ + basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix( + -DragStat().Ref1().X(), -DragStat().Ref1().Y())); + aRetval.scale(aXFact, aYFact); + aRetval.translate(DragStat().Ref1().X(), DragStat().Ref1().Y()); + + return aRetval; +} + +void SdrDragResize::MoveSdrDrag(const Point& rNoSnapPnt) +{ + Point aPnt(GetSnapPos(rNoSnapPnt)); + Point aStart(DragStat().GetStart()); + Point aRef(DragStat().GetRef1()); + Fraction aMaxFact(0x7FFFFFFF,1); + Rectangle aLR(getSdrDragView().GetWorkArea()); + bool bWorkArea=!aLR.IsEmpty(); + bool bDragLimit=IsDragLimit(); + + if (bDragLimit || bWorkArea) + { + Rectangle aSR(GetMarkedRect()); + + if (bDragLimit) + { + Rectangle aR2(GetDragLimitRect()); + + if (bWorkArea) + aLR.Intersection(aR2); + else + aLR=aR2; + } + + if (aPnt.X()<aLR.Left()) + aPnt.X()=aLR.Left(); + else if (aPnt.X()>aLR.Right()) + aPnt.X()=aLR.Right(); + + if (aPnt.Y()<aLR.Top()) + aPnt.Y()=aLR.Top(); + else if (aPnt.Y()>aLR.Bottom()) + aPnt.Y()=aLR.Bottom(); + + if (aRef.X()>aSR.Left()) + { + Fraction aMax(aRef.X()-aLR.Left(),aRef.X()-aSR.Left()); + + if (aMax<aMaxFact) + aMaxFact=aMax; + } + + if (aRef.X()<aSR.Right()) + { + Fraction aMax(aLR.Right()-aRef.X(),aSR.Right()-aRef.X()); + + if (aMax<aMaxFact) + aMaxFact=aMax; + } + + if (aRef.Y()>aSR.Top()) + { + Fraction aMax(aRef.Y()-aLR.Top(),aRef.Y()-aSR.Top()); + + if (aMax<aMaxFact) + aMaxFact=aMax; + } + + if (aRef.Y()<aSR.Bottom()) + { + Fraction aMax(aLR.Bottom()-aRef.Y(),aSR.Bottom()-aRef.Y()); + + if (aMax<aMaxFact) + aMaxFact=aMax; + } + } + + long nXDiv=aStart.X()-aRef.X(); if (nXDiv==0) nXDiv=1; + long nYDiv=aStart.Y()-aRef.Y(); if (nYDiv==0) nYDiv=1; + long nXMul=aPnt.X()-aRef.X(); + long nYMul=aPnt.Y()-aRef.Y(); + + if (nXDiv<0) + { + nXDiv=-nXDiv; + nXMul=-nXMul; + } + + if (nYDiv<0) + { + nYDiv=-nYDiv; + nYMul=-nYMul; + } + + bool bXNeg=nXMul<0; if (bXNeg) nXMul=-nXMul; + bool bYNeg=nYMul<0; if (bYNeg) nYMul=-nYMul; + bool bOrtho=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed(false); + + if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed()) + { + if (Abs(nXDiv)<=1 || Abs(nYDiv)<=1) + bOrtho=false; + + if (bOrtho) + { + if ((Fraction(nXMul,nXDiv)>Fraction(nYMul,nYDiv)) !=getSdrDragView().IsBigOrtho()) + { + nXMul=nYMul; + nXDiv=nYDiv; + } + else + { + nYMul=nXMul; + nYDiv=nXDiv; + } + } + } + else + { + if (bOrtho) + { + if (DragStat().IsHorFixed()) + { + bXNeg=false; + nXMul=nYMul; + nXDiv=nYDiv; + } + + if (DragStat().IsVerFixed()) + { + bYNeg=false; + nYMul=nXMul; + nYDiv=nXDiv; + } + } + else + { + if (DragStat().IsHorFixed()) + { + bXNeg=false; + nXMul=1; + nXDiv=1; + } + + if (DragStat().IsVerFixed()) + { + bYNeg=false; + nYMul=1; + nYDiv=1; + } + } + } + + Fraction aNeuXFact(nXMul,nXDiv); + Fraction aNeuYFact(nYMul,nYDiv); + + if (bOrtho) + { + if (aNeuXFact>aMaxFact) + { + aNeuXFact=aMaxFact; + aNeuYFact=aMaxFact; + } + + if (aNeuYFact>aMaxFact) + { + aNeuXFact=aMaxFact; + aNeuYFact=aMaxFact; + } + } + + if (bXNeg) + aNeuXFact=Fraction(-aNeuXFact.GetNumerator(),aNeuXFact.GetDenominator()); + + if (bYNeg) + aNeuYFact=Fraction(-aNeuYFact.GetNumerator(),aNeuYFact.GetDenominator()); + + if (DragStat().CheckMinMoved(aPnt)) + { + if ((!DragStat().IsHorFixed() && aPnt.X()!=DragStat().GetNow().X()) || + (!DragStat().IsVerFixed() && aPnt.Y()!=DragStat().GetNow().Y())) + { + Hide(); + DragStat().NextMove(aPnt); + aXFact=aNeuXFact; + aYFact=aNeuYFact; + Show(); + } + } +} + +void SdrDragResize::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + rTarget.Resize(DragStat().Ref1(),aXFact,aYFact); +} + +bool SdrDragResize::EndSdrDrag(bool bCopy) +{ + Hide(); + + if (IsDraggingPoints()) + { + getSdrDragView().ResizeMarkedPoints(DragStat().Ref1(),aXFact,aYFact,bCopy); + } + else if (IsDraggingGluePoints()) + { + getSdrDragView().ResizeMarkedGluePoints(DragStat().Ref1(),aXFact,aYFact,bCopy); + } + else + { + getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy); + } + + return true; +} + +Pointer SdrDragResize::GetSdrDragPointer() const +{ + const SdrHdl* pHdl=GetDragHdl(); + + if (pHdl!=NULL) + { + return pHdl->GetPointer(); + } + + return Pointer(POINTER_MOVE); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragRotate,SdrDragMethod); + +void SdrDragRotate::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + rTarget.Rotate(DragStat().GetRef1(), nWink, sin(nWink*nPi180), cos(nWink*nPi180)); +} + +SdrDragRotate::SdrDragRotate(SdrDragView& rNewView) +: SdrDragMethod(rNewView), + nSin(0.0), + nCos(1.0), + nWink0(0), + nWink(0), + bRight(false) +{ +} + +void SdrDragRotate::TakeSdrDragComment(XubString& rStr) const +{ + ImpTakeDescriptionStr(STR_DragMethRotate, rStr); + rStr.AppendAscii(" ("); + XubString aStr; + INT32 nTmpWink(NormAngle360(nWink)); + + if(bRight && nWink) + { + nTmpWink -= 36000; + } + + getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr); + rStr += aStr; + rStr += sal_Unicode(')'); + + if(getSdrDragView().IsDragWithCopy()) + rStr += ImpGetResStr(STR_EditWithCopy); +} + +bool SdrDragRotate::BeginSdrDrag() +{ + SdrHdl* pH=GetHdlList().GetHdl(HDL_REF1); + + if (pH!=NULL) + { + Show(); + DragStat().Ref1()=pH->GetPos(); + nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1()); + return true; + } + else + { + DBG_ERROR("SdrDragRotate::BeginSdrDrag(): Kein Referenzpunkt-Handle gefunden"); + return false; + } +} + +basegfx::B2DHomMatrix SdrDragRotate::getCurrentTransformation() +{ + return basegfx::tools::createRotateAroundPoint( + DragStat().GetRef1().X(), DragStat().GetRef1().Y(), + -atan2(nSin, nCos)); +} + +void SdrDragRotate::MoveSdrDrag(const Point& rPnt_) +{ + Point aPnt(rPnt_); + if (DragStat().CheckMinMoved(aPnt)) + { + long nNeuWink=NormAngle360(GetAngle(aPnt-DragStat().GetRef1())-nWink0); + long nSA=0; + + if (getSdrDragView().IsAngleSnapEnabled()) + nSA=getSdrDragView().GetSnapAngle(); + + if (!getSdrDragView().IsRotateAllowed(false)) + nSA=9000; + + if (nSA!=0) + { // Winkelfang + nNeuWink+=nSA/2; + nNeuWink/=nSA; + nNeuWink*=nSA; + } + + nNeuWink=NormAngle180(nNeuWink); + + if (nWink!=nNeuWink) + { + sal_uInt16 nSekt0=GetAngleSector(nWink); + sal_uInt16 nSekt1=GetAngleSector(nNeuWink); + + if (nSekt0==0 && nSekt1==3) + bRight=true; + + if (nSekt0==3 && nSekt1==0) + bRight=false; + + nWink=nNeuWink; + double a=nWink*nPi180; + double nSin1=sin(a); // schonmal berechnen, damit mgl. wenig Zeit + double nCos1=cos(a); // zwischen Hide() und Show() vergeht + Hide(); + nSin=nSin1; + nCos=nCos1; + DragStat().NextMove(aPnt); + Show(); + } + } +} + +bool SdrDragRotate::EndSdrDrag(bool bCopy) +{ + Hide(); + + if (nWink!=0) + { + if (IsDraggingPoints()) + { + getSdrDragView().RotateMarkedPoints(DragStat().GetRef1(),nWink,bCopy); + } + else if (IsDraggingGluePoints()) + { + getSdrDragView().RotateMarkedGluePoints(DragStat().GetRef1(),nWink,bCopy); + } + else + { + getSdrDragView().RotateMarkedObj(DragStat().GetRef1(),nWink,bCopy); + } + } + return true; +} + +Pointer SdrDragRotate::GetSdrDragPointer() const +{ + return Pointer(POINTER_ROTATE); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragShear,SdrDragMethod); + +SdrDragShear::SdrDragShear(SdrDragView& rNewView, bool bSlant1) +: SdrDragMethod(rNewView), + aFact(1,1), + nWink0(0), + nWink(0), + nTan(0.0), + bVertical(false), + bResize(false), + bUpSideDown(false), + bSlant(bSlant1) +{ +} + +void SdrDragShear::TakeSdrDragComment(XubString& rStr) const +{ + ImpTakeDescriptionStr(STR_DragMethShear, rStr); + rStr.AppendAscii(" ("); + + INT32 nTmpWink(nWink); + + if(bUpSideDown) + nTmpWink += 18000; + + nTmpWink = NormAngle180(nTmpWink); + + XubString aStr; + + getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr); + rStr += aStr; + rStr += sal_Unicode(')'); + + if(getSdrDragView().IsDragWithCopy()) + rStr += ImpGetResStr(STR_EditWithCopy); +} + +bool SdrDragShear::BeginSdrDrag() +{ + SdrHdlKind eRefHdl=HDL_MOVE; + SdrHdl* pRefHdl=NULL; + + switch (GetDragHdlKind()) + { + case HDL_UPPER: eRefHdl=HDL_LOWER; break; + case HDL_LOWER: eRefHdl=HDL_UPPER; break; + case HDL_LEFT : eRefHdl=HDL_RIGHT; bVertical=true; break; + case HDL_RIGHT: eRefHdl=HDL_LEFT ; bVertical=true; break; + default: break; + } + + if (eRefHdl!=HDL_MOVE) + pRefHdl=GetHdlList().GetHdl(eRefHdl); + + if (pRefHdl!=NULL) + { + DragStat().Ref1()=pRefHdl->GetPos(); + nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1()); + } + else + { + DBG_ERROR("SdrDragShear::BeginSdrDrag(): Kein Referenzpunkt-Handle fuer Shear gefunden"); + return false; + } + + Show(); + return true; +} + +basegfx::B2DHomMatrix SdrDragShear::getCurrentTransformation() +{ + basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix( + -DragStat().GetRef1().X(), -DragStat().GetRef1().Y())); + + if (bResize) + { + if (bVertical) + { + aRetval.scale(aFact, 1.0); + aRetval.shearY(-nTan); + } + else + { + aRetval.scale(1.0, aFact); + aRetval.shearX(-nTan); + } + } + + aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y()); + + return aRetval; +} + +void SdrDragShear::MoveSdrDrag(const Point& rPnt) +{ + if (DragStat().CheckMinMoved(rPnt)) + { + bResize=!getSdrDragView().IsOrtho(); + long nSA=0; + + if (getSdrDragView().IsAngleSnapEnabled()) + nSA=getSdrDragView().GetSnapAngle(); + + Point aP0(DragStat().GetStart()); + Point aPnt(rPnt); + Fraction aNeuFact(1,1); + + // Wenn kein Winkelfang, dann ggf. Rasterfang (ausser bei Slant) + if (nSA==0 && !bSlant) + aPnt=GetSnapPos(aPnt); + + if (!bSlant && !bResize) + { // Shear ohne Resize + if (bVertical) + aPnt.X()=aP0.X(); + else + aPnt.Y()=aP0.Y(); + } + + Point aRef(DragStat().GetRef1()); + Point aDif(aPnt-aRef); + + long nNeuWink=0; + + if (bSlant) + { + nNeuWink=NormAngle180(-(GetAngle(aDif)-nWink0)); + + if (bVertical) + nNeuWink=NormAngle180(-nNeuWink); + } + else + { + if (bVertical) + nNeuWink=NormAngle180(GetAngle(aDif)); + else + nNeuWink=NormAngle180(-(GetAngle(aDif)-9000)); + + if (nNeuWink<-9000 || nNeuWink>9000) + nNeuWink=NormAngle180(nNeuWink+18000); + + if (bResize) + { + Point aPt2(aPnt); + + if (nSA!=0) + aPt2=GetSnapPos(aPnt); // den also in jedem Falle fangen + + if (bVertical) + { + aNeuFact=Fraction(aPt2.X()-aRef.X(),aP0.X()-aRef.X()); + } + else + { + aNeuFact=Fraction(aPt2.Y()-aRef.Y(),aP0.Y()-aRef.Y()); + } + } + } + + bool bNeg=nNeuWink<0; + + if (bNeg) + nNeuWink=-nNeuWink; + + if (nSA!=0) + { // Winkelfang + nNeuWink+=nSA/2; + nNeuWink/=nSA; + nNeuWink*=nSA; + } + + nNeuWink=NormAngle360(nNeuWink); + bUpSideDown=nNeuWink>9000 && nNeuWink<27000; + + if (bSlant) + { // Resize fuer Slant berechnen + // Mit Winkelfang jedoch ohne 89deg Begrenzung + long nTmpWink=nNeuWink; + if (bUpSideDown) nNeuWink-=18000; + if (bNeg) nTmpWink=-nTmpWink; + bResize=true; + double nCos=cos(nTmpWink*nPi180); + aNeuFact=nCos; + Kuerzen(aFact,10); // 3 Dezimalstellen sollten reichen + } + + if (nNeuWink>8900) + nNeuWink=8900; + + if (bNeg) + nNeuWink=-nNeuWink; + + if (nWink!=nNeuWink || aFact!=aNeuFact) + { + nWink=nNeuWink; + aFact=aNeuFact; + double a=nWink*nPi180; + double nTan1=0.0; + nTan1=tan(a); // schonmal berechnen, damit mgl. wenig Zeit zwischen Hide() und Show() vergeht + Hide(); + nTan=nTan1; + DragStat().NextMove(rPnt); + Show(); + } + } +} + +void SdrDragShear::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + if (bResize) + { + if (bVertical) + { + rTarget.Resize(DragStat().GetRef1(),aFact,Fraction(1,1)); + } + else + { + rTarget.Resize(DragStat().GetRef1(),Fraction(1,1),aFact); + } + } + + if (nWink!=0) + { + rTarget.Shear(DragStat().GetRef1(),nWink,tan(nWink*nPi180),bVertical); + } +} + +bool SdrDragShear::EndSdrDrag(bool bCopy) +{ + Hide(); + + if (bResize && aFact==Fraction(1,1)) + bResize=false; + + if (nWink!=0 || bResize) + { + if (nWink!=0 && bResize) + { + XubString aStr; + ImpTakeDescriptionStr(STR_EditShear,aStr); + + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + + getSdrDragView().BegUndo(aStr); + } + + if (bResize) + { + if (bVertical) + { + getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aFact,Fraction(1,1),bCopy); + } + else + { + getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),Fraction(1,1),aFact,bCopy); + } + + bCopy=false; + } + + if (nWink!=0) + { + getSdrDragView().ShearMarkedObj(DragStat().GetRef1(),nWink,bVertical,bCopy); + } + + if (nWink!=0 && bResize) + getSdrDragView().EndUndo(); + + return true; + } + + return false; +} + +Pointer SdrDragShear::GetSdrDragPointer() const +{ + if (bVertical) + return Pointer(POINTER_VSHEAR); + else + return Pointer(POINTER_HSHEAR); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragMirror,SdrDragMethod); + +void SdrDragMirror::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + if(bMirrored) + { + rTarget.Mirror(DragStat().GetRef1(), DragStat().GetRef2()); + } +} + +SdrDragMirror::SdrDragMirror(SdrDragView& rNewView) +: SdrDragMethod(rNewView), + nWink(0), + bMirrored(false), + bSide0(false) +{ +} + +bool SdrDragMirror::ImpCheckSide(const Point& rPnt) const +{ + long nWink1=GetAngle(rPnt-DragStat().GetRef1()); + nWink1-=nWink; + nWink1=NormAngle360(nWink1); + + return nWink1<18000; +} + +void SdrDragMirror::TakeSdrDragComment(XubString& rStr) const +{ + if (aDif.X()==0) + ImpTakeDescriptionStr(STR_DragMethMirrorHori,rStr); + else if (aDif.Y()==0) + ImpTakeDescriptionStr(STR_DragMethMirrorVert,rStr); + else if (Abs(aDif.X())==Abs(aDif.Y())) + ImpTakeDescriptionStr(STR_DragMethMirrorDiag,rStr); + else + ImpTakeDescriptionStr(STR_DragMethMirrorFree,rStr); + + if (getSdrDragView().IsDragWithCopy()) + rStr+=ImpGetResStr(STR_EditWithCopy); +} + +bool SdrDragMirror::BeginSdrDrag() +{ + SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1); + SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2); + + if (pH1!=NULL && pH2!=NULL) + { + DragStat().Ref1()=pH1->GetPos(); + DragStat().Ref2()=pH2->GetPos(); + Ref1()=pH1->GetPos(); + Ref2()=pH2->GetPos(); + aDif=pH2->GetPos()-pH1->GetPos(); + bool b90=(aDif.X()==0) || aDif.Y()==0; + bool b45=b90 || (Abs(aDif.X())==Abs(aDif.Y())); + nWink=NormAngle360(GetAngle(aDif)); + + if (!getSdrDragView().IsMirrorAllowed(false,false) && !b45) + return false; // freier Achsenwinkel nicht erlaubt + + if (!getSdrDragView().IsMirrorAllowed(true,false) && !b90) + return false; // 45deg auch nicht erlaubt + + bSide0=ImpCheckSide(DragStat().GetStart()); + Show(); + return true; + } + else + { + DBG_ERROR("SdrDragMirror::BeginSdrDrag(): Spiegelachse nicht gefunden"); + return false; + } +} + +basegfx::B2DHomMatrix SdrDragMirror::getCurrentTransformation() +{ + basegfx::B2DHomMatrix aRetval; + + if (bMirrored) + { + const double fDeltaX(DragStat().GetRef2().X() - DragStat().GetRef1().X()); + const double fDeltaY(DragStat().GetRef2().Y() - DragStat().GetRef1().Y()); + const double fRotation(atan2(fDeltaY, fDeltaX)); + + aRetval = basegfx::tools::createTranslateB2DHomMatrix(-DragStat().GetRef1().X(), -DragStat().GetRef1().Y()); + aRetval.rotate(-fRotation); + aRetval.scale(1.0, -1.0); + aRetval.rotate(fRotation); + aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y()); + } + + return aRetval; +} + +void SdrDragMirror::MoveSdrDrag(const Point& rPnt) +{ + if (DragStat().CheckMinMoved(rPnt)) + { + bool bNeuSide=ImpCheckSide(rPnt); + bool bNeuMirr=bSide0!=bNeuSide; + + if (bMirrored!=bNeuMirr) + { + Hide(); + bMirrored=bNeuMirr; + DragStat().NextMove(rPnt); + Show(); + } + } +} + +bool SdrDragMirror::EndSdrDrag(bool bCopy) +{ + Hide(); + + if (bMirrored) + { + getSdrDragView().MirrorMarkedObj(DragStat().GetRef1(),DragStat().GetRef2(),bCopy); + } + + return true; +} + +Pointer SdrDragMirror::GetSdrDragPointer() const +{ + return Pointer(POINTER_MIRROR); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragGradient, SdrDragMethod); + +SdrDragGradient::SdrDragGradient(SdrDragView& rNewView, bool bGrad) +: SdrDragMethod(rNewView), + pIAOHandle(NULL), + bIsGradient(bGrad) +{ +} + +void SdrDragGradient::TakeSdrDragComment(XubString& rStr) const +{ + if(IsGradient()) + ImpTakeDescriptionStr(STR_DragMethGradient, rStr); + else + ImpTakeDescriptionStr(STR_DragMethTransparence, rStr); +} + +bool SdrDragGradient::BeginSdrDrag() +{ + bool bRetval(false); + + pIAOHandle = (SdrHdlGradient*)GetHdlList().GetHdl(IsGradient() ? HDL_GRAD : HDL_TRNS); + + if(pIAOHandle) + { + // save old values + DragStat().Ref1() = pIAOHandle->GetPos(); + DragStat().Ref2() = pIAOHandle->Get2ndPos(); + + // what was hit? + bool bHit(false); + SdrHdlColor* pColHdl = pIAOHandle->GetColorHdl1(); + + // init handling flags + pIAOHandle->SetMoveSingleHandle(false); + pIAOHandle->SetMoveFirstHandle(false); + + // test first color handle + if(pColHdl) + { + basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y()); + + if(pColHdl->getOverlayObjectList().isHitLogic(aPosition)) + { + bHit = true; + pIAOHandle->SetMoveSingleHandle(true); + pIAOHandle->SetMoveFirstHandle(true); + } + } + + // test second color handle + pColHdl = pIAOHandle->GetColorHdl2(); + + if(!bHit && pColHdl) + { + basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y()); + + if(pColHdl->getOverlayObjectList().isHitLogic(aPosition)) + { + bHit = true; + pIAOHandle->SetMoveSingleHandle(true); + } + } + + // test gradient handle itself + if(!bHit) + { + basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y()); + + if(pIAOHandle->getOverlayObjectList().isHitLogic(aPosition)) + { + bHit = true; + } + } + + // everything up and running :o} + bRetval = bHit; + } + else + { + DBG_ERROR("SdrDragGradient::BeginSdrDrag(): IAOGradient nicht gefunden"); + } + + return bRetval; +} + +void SdrDragGradient::MoveSdrDrag(const Point& rPnt) +{ + if(pIAOHandle && DragStat().CheckMinMoved(rPnt)) + { + DragStat().NextMove(rPnt); + + // Do the Move here!!! DragStat().GetStart() + Point aMoveDiff = rPnt - DragStat().GetStart(); + + if(pIAOHandle->IsMoveSingleHandle()) + { + if(pIAOHandle->IsMoveFirstHandle()) + { + pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff); + if(pIAOHandle->GetColorHdl1()) + pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff); + } + else + { + pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff); + if(pIAOHandle->GetColorHdl2()) + pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff); + } + } + else + { + pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff); + pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff); + + if(pIAOHandle->GetColorHdl1()) + pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff); + + if(pIAOHandle->GetColorHdl2()) + pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff); + } + + // new state + pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), false, false); + } +} + +bool SdrDragGradient::EndSdrDrag(bool /*bCopy*/) +{ + // here the result is clear, do something with the values + Ref1() = pIAOHandle->GetPos(); + Ref2() = pIAOHandle->Get2ndPos(); + + // new state + pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, true); + + return true; +} + +void SdrDragGradient::CancelSdrDrag() +{ + // restore old values + pIAOHandle->SetPos(DragStat().Ref1()); + pIAOHandle->Set2ndPos(DragStat().Ref2()); + + if(pIAOHandle->GetColorHdl1()) + pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1()); + + if(pIAOHandle->GetColorHdl2()) + pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2()); + + // new state + pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, false); +} + +Pointer SdrDragGradient::GetSdrDragPointer() const +{ + return Pointer(POINTER_REFHAND); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragCrook,SdrDragMethod); + +SdrDragCrook::SdrDragCrook(SdrDragView& rNewView) +: SdrDragMethod(rNewView), + aFact(1,1), + bContortionAllowed(false), + bNoContortionAllowed(false), + bContortion(false), + bResizeAllowed(false), + bResize(false), + bRotateAllowed(false), + bRotate(false), + bVertical(false), + bValid(false), + bLft(false), + bRgt(false), + bUpr(false), + bLwr(false), + bAtCenter(false), + nWink(0), + nMarkSize(0), + eMode(SDRCROOK_ROTATE) +{ +} + +void SdrDragCrook::TakeSdrDragComment(XubString& rStr) const +{ + ImpTakeDescriptionStr(!bContortion ? STR_DragMethCrook : STR_DragMethCrookContortion, rStr); + + if(bValid) + { + rStr.AppendAscii(" ("); + + XubString aStr; + INT32 nVal(nWink); + + if(bAtCenter) + nVal *= 2; + + nVal = Abs(nVal); + getSdrDragView().GetModel()->TakeWinkStr(nVal, aStr); + rStr += aStr; + rStr += sal_Unicode(')'); + } + + if(getSdrDragView().IsDragWithCopy()) + rStr += ImpGetResStr(STR_EditWithCopy); +} + +// #96920# These defines parametrise the created raster +// for interactions +#define DRAG_CROOK_RASTER_MINIMUM (4) +#define DRAG_CROOK_RASTER_MAXIMUM (15) +#define DRAG_CROOK_RASTER_DISTANCE (30) + +basegfx::B2DPolyPolygon impCreateDragRaster(SdrPageView& rPageView, const Rectangle& rMarkRect) +{ + basegfx::B2DPolyPolygon aRetval; + + if(rPageView.PageWindowCount()) + { + OutputDevice& rOut = (rPageView.GetPageWindow(0)->GetPaintWindow().GetOutputDevice()); + Rectangle aPixelSize = rOut.LogicToPixel(rMarkRect); + sal_uInt32 nHorDiv(aPixelSize.GetWidth() / DRAG_CROOK_RASTER_DISTANCE); + sal_uInt32 nVerDiv(aPixelSize.GetHeight() / DRAG_CROOK_RASTER_DISTANCE); + + if(nHorDiv > DRAG_CROOK_RASTER_MAXIMUM) + nHorDiv = DRAG_CROOK_RASTER_MAXIMUM; + if(nHorDiv < DRAG_CROOK_RASTER_MINIMUM) + nHorDiv = DRAG_CROOK_RASTER_MINIMUM; + + if(nVerDiv > DRAG_CROOK_RASTER_MAXIMUM) + nVerDiv = DRAG_CROOK_RASTER_MAXIMUM; + if(nVerDiv < DRAG_CROOK_RASTER_MINIMUM) + nVerDiv = DRAG_CROOK_RASTER_MINIMUM; + + const double fXLen(rMarkRect.GetWidth() / (double)nHorDiv); + const double fYLen(rMarkRect.GetHeight() / (double)nVerDiv); + double fYPos(rMarkRect.Top()); + sal_uInt32 a, b; + + for(a = 0; a <= nVerDiv; a++) + { + // hor lines + for(b = 0; b < nHorDiv; b++) + { + basegfx::B2DPolygon aHorLineSegment; + + const double fNewX(rMarkRect.Left() + (b * fXLen)); + aHorLineSegment.append(basegfx::B2DPoint(fNewX, fYPos)); + aHorLineSegment.appendBezierSegment( + basegfx::B2DPoint(fNewX + (fXLen * (1.0 / 3.0)), fYPos), + basegfx::B2DPoint(fNewX + (fXLen * (2.0 / 3.0)), fYPos), + basegfx::B2DPoint(fNewX + fXLen, fYPos)); + aRetval.append(aHorLineSegment); + } + + // increments + fYPos += fYLen; + } + + double fXPos(rMarkRect.Left()); + + for(a = 0; a <= nHorDiv; a++) + { + // ver lines + for(b = 0; b < nVerDiv; b++) + { + basegfx::B2DPolygon aVerLineSegment; + + const double fNewY(rMarkRect.Top() + (b * fYLen)); + aVerLineSegment.append(basegfx::B2DPoint(fXPos, fNewY)); + aVerLineSegment.appendBezierSegment( + basegfx::B2DPoint(fXPos, fNewY + (fYLen * (1.0 / 3.0))), + basegfx::B2DPoint(fXPos, fNewY + (fYLen * (2.0 / 3.0))), + basegfx::B2DPoint(fXPos, fNewY + fYLen)); + aRetval.append(aVerLineSegment); + } + + // increments + fXPos += fXLen; + } + } + + return aRetval; +} + +void SdrDragCrook::createSdrDragEntries() +{ + // Add extended frame raster first, so it will be behind objects + if(getSdrDragView().GetSdrPageView()) + { + const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect())); + + if(aDragRaster.count()) + { + addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster)); + } + } + + // call parent + SdrDragMethod::createSdrDragEntries(); +} + +bool SdrDragCrook::BeginSdrDrag() +{ + bContortionAllowed=getSdrDragView().IsCrookAllowed(false); + bNoContortionAllowed=getSdrDragView().IsCrookAllowed(true); + bResizeAllowed=getSdrDragView().IsResizeAllowed(false); + bRotateAllowed=getSdrDragView().IsRotateAllowed(false); + + if (bContortionAllowed || bNoContortionAllowed) + { + bVertical=(GetDragHdlKind()==HDL_LOWER || GetDragHdlKind()==HDL_UPPER); + aMarkRect=GetMarkedRect(); + aMarkCenter=aMarkRect.Center(); + nMarkSize=bVertical ? (aMarkRect.GetHeight()-1) : (aMarkRect.GetWidth()-1); + aCenter=aMarkCenter; + aStart=DragStat().GetStart(); + Show(); + return true; + } + else + { + return false; + } +} + +void SdrDragCrook::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget) +{ + SdrPageView* pPV = getSdrDragView().GetSdrPageView(); + + if(pPV) + { + XPolyPolygon aTempPolyPoly(rTarget); + + if (pPV->HasMarkedObjPageView()) + { + sal_uInt16 nPolyAnz=aTempPolyPoly.Count(); + + if (!bContortion && !getSdrDragView().IsNoDragXorPolys()) + { + sal_uInt16 n1st=0,nLast=0; + Point aC(aCenter); + + while (n1st<nPolyAnz) + { + nLast=n1st; + while (nLast<nPolyAnz && aTempPolyPoly[nLast].GetPointCount()!=0) nLast++; + Rectangle aBound(aTempPolyPoly[n1st].GetBoundRect()); + sal_uInt16 i; + + for (i=n1st+1; i<nLast; i++) + { + aBound.Union(aTempPolyPoly[n1st].GetBoundRect()); + } + + Point aCtr0(aBound.Center()); + Point aCtr1(aCtr0); + + if (bResize) + { + Fraction aFact1(1,1); + + if (bVertical) + { + ResizePoint(aCtr1,aC,aFact1,aFact); + } + else + { + ResizePoint(aCtr1,aC,aFact,aFact1); + } + } + + bool bRotOk=false; + double nSin=0,nCos=0; + + if (aRad.X()!=0 && aRad.Y()!=0) + { + bRotOk=bRotate; + + switch (eMode) + { + case SDRCROOK_ROTATE : CrookRotateXPoint (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical); break; + case SDRCROOK_SLANT : CrookSlantXPoint (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical); break; + case SDRCROOK_STRETCH: CrookStretchXPoint(aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical,aMarkRect); break; + } // switch + } + + aCtr1-=aCtr0; + + for (i=n1st; i<nLast; i++) + { + if (bRotOk) + { + RotateXPoly(aTempPolyPoly[i],aCtr0,nSin,nCos); + } + + aTempPolyPoly[i].Move(aCtr1.X(),aCtr1.Y()); + } + + n1st=nLast+1; + } + } + else + { + sal_uInt16 i,j; + + for (j=0; j<nPolyAnz; j++) + { + XPolygon& aPol=aTempPolyPoly[j]; + sal_uInt16 nPtAnz=aPol.GetPointCount(); + i=0; + + while (i<nPtAnz) + { + Point* pPnt=&aPol[i]; + Point* pC1=NULL; + Point* pC2=NULL; + + if (i+1<nPtAnz && aPol.IsControl(i)) + { // Kontrollpunkt links + pC1=pPnt; + i++; + pPnt=&aPol[i]; + } + + i++; + + if (i<nPtAnz && aPol.IsControl(i)) + { // Kontrollpunkt rechts + pC2=&aPol[i]; + i++; + } + + _MovCrookPoint(*pPnt,pC1,pC2); + } + } + } + } + + rTarget = aTempPolyPoly.getB2DPolyPolygon(); + } +} + +void SdrDragCrook::_MovCrookPoint(Point& rPnt, Point* pC1, Point* pC2) +{ + bool bVert=bVertical; + bool bC1=pC1!=NULL; + bool bC2=pC2!=NULL; + Point aC(aCenter); + + if (bResize) + { + Fraction aFact1(1,1); + + if (bVert) + { + ResizePoint(rPnt,aC,aFact1,aFact); + + if (bC1) + ResizePoint(*pC1,aC,aFact1,aFact); + + if (bC2) + ResizePoint(*pC2,aC,aFact1,aFact); + } + else + { + ResizePoint(rPnt,aC,aFact,aFact1); + + if (bC1) + ResizePoint(*pC1,aC,aFact,aFact1); + + if (bC2) + ResizePoint(*pC2,aC,aFact,aFact1); + } + } + + if (aRad.X()!=0 && aRad.Y()!=0) + { + double nSin,nCos; + + switch (eMode) + { + case SDRCROOK_ROTATE : CrookRotateXPoint (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert); break; + case SDRCROOK_SLANT : CrookSlantXPoint (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert); break; + case SDRCROOK_STRETCH: CrookStretchXPoint(rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert,aMarkRect); break; + } // switch + } +} + +void SdrDragCrook::MoveSdrDrag(const Point& rPnt) +{ + if (DragStat().CheckMinMoved(rPnt)) + { + Point aPnt(rPnt); + bool bNeuMoveOnly=getSdrDragView().IsMoveOnlyDragging(); + bAtCenter=false; + SdrCrookMode eNeuMode=getSdrDragView().GetCrookMode(); + bool bNeuContortion=!bNeuMoveOnly && ((bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed); + bResize=!getSdrDragView().IsOrtho() && bResizeAllowed && !bNeuMoveOnly; + bool bNeuRotate=bRotateAllowed && !bNeuContortion && !bNeuMoveOnly && eNeuMode==SDRCROOK_ROTATE; + long nSA=0; + + if (nSA==0) + aPnt=GetSnapPos(aPnt); + + Point aNeuCenter(aMarkCenter.X(),aStart.Y()); + + if (bVertical) + { + aNeuCenter.X()=aStart.X(); + aNeuCenter.Y()=aMarkCenter.Y(); + } + + if (!getSdrDragView().IsCrookAtCenter()) + { + switch (GetDragHdlKind()) + { + case HDL_UPLFT: aNeuCenter.X()=aMarkRect.Right(); bLft=true; break; + case HDL_UPPER: aNeuCenter.Y()=aMarkRect.Bottom(); bUpr=true; break; + case HDL_UPRGT: aNeuCenter.X()=aMarkRect.Left(); bRgt=true; break; + case HDL_LEFT : aNeuCenter.X()=aMarkRect.Right(); bLft=true; break; + case HDL_RIGHT: aNeuCenter.X()=aMarkRect.Left(); bRgt=true; break; + case HDL_LWLFT: aNeuCenter.X()=aMarkRect.Right(); bLft=true; break; + case HDL_LOWER: aNeuCenter.Y()=aMarkRect.Top(); bLwr=true; break; + case HDL_LWRGT: aNeuCenter.X()=aMarkRect.Left(); bRgt=true; break; + default: bAtCenter=true; + } + } + else + bAtCenter=true; + + Fraction aNeuFact(1,1); + long dx1=aPnt.X()-aNeuCenter.X(); + long dy1=aPnt.Y()-aNeuCenter.Y(); + bValid=bVertical ? dx1!=0 : dy1!=0; + + if (bValid) + { + if (bVertical) + bValid=Abs(dx1)*100>Abs(dy1); + else + bValid=Abs(dy1)*100>Abs(dx1); + } + + long nNeuRad=0; + nWink=0; + + if (bValid) + { + double a=0; // Steigung des Radius + long nPntWink=0; + + if (bVertical) + { + a=((double)dy1)/((double)dx1); // Steigung des Radius + nNeuRad=((long)(dy1*a)+dx1) /2; + aNeuCenter.X()+=nNeuRad; + nPntWink=GetAngle(aPnt-aNeuCenter); + } + else + { + a=((double)dx1)/((double)dy1); // Steigung des Radius + nNeuRad=((long)(dx1*a)+dy1) /2; + aNeuCenter.Y()+=nNeuRad; + nPntWink=GetAngle(aPnt-aNeuCenter)-9000; + } + + if (!bAtCenter) + { + if (nNeuRad<0) + { + if (bRgt) nPntWink+=18000; + if (bLft) nPntWink=18000-nPntWink; + if (bLwr) nPntWink=-nPntWink; + } + else + { + if (bRgt) nPntWink=-nPntWink; + if (bUpr) nPntWink=18000-nPntWink; + if (bLwr) nPntWink+=18000; + } + + nPntWink=NormAngle360(nPntWink); + } + else + { + if (nNeuRad<0) nPntWink+=18000; + if (bVertical) nPntWink=18000-nPntWink; + nPntWink=NormAngle180(nPntWink); + nPntWink=Abs(nPntWink); + } + + double nUmfang=2*Abs(nNeuRad)*nPi; + + if (bResize) + { + if (nSA!=0) + { // Winkelfang + long nWink0=nPntWink; + nPntWink+=nSA/2; + nPntWink/=nSA; + nPntWink*=nSA; + BigInt a2(nNeuRad); + a2*=BigInt(nWink); + a2/=BigInt(nWink0); + nNeuRad=long(a2); + + if (bVertical) + aNeuCenter.X()=aStart.X()+nNeuRad; + else + aNeuCenter.Y()=aStart.Y()+nNeuRad; + } + + long nMul=(long)(nUmfang*NormAngle360(nPntWink)/36000); + + if (bAtCenter) + nMul*=2; + + aNeuFact=Fraction(nMul,nMarkSize); + nWink=nPntWink; + } + else + { + nWink=(long)((nMarkSize*360/nUmfang)*100)/2; + + if (nWink==0) + bValid=false; + + if (bValid && nSA!=0) + { // Winkelfang + long nWink0=nWink; + nWink+=nSA/2; + nWink/=nSA; + nWink*=nSA; + BigInt a2(nNeuRad); + a2*=BigInt(nWink); + a2/=BigInt(nWink0); + nNeuRad=long(a2); + + if (bVertical) + aNeuCenter.X()=aStart.X()+nNeuRad; + else + aNeuCenter.Y()=aStart.Y()+nNeuRad; + } + } + } + + if (nWink==0 || nNeuRad==0) + bValid=false; + + if (!bValid) + nNeuRad=0; + + if (!bValid && bResize) + { + long nMul=bVertical ? dy1 : dx1; + + if (bLft || bUpr) + nMul=-nMul; + + long nDiv=nMarkSize; + + if (bAtCenter) + { + nMul*=2; + nMul=Abs(nMul); + } + + aNeuFact=Fraction(nMul,nDiv); + } + + if (aNeuCenter!=aCenter || bNeuContortion!=bContortion || aNeuFact!=aFact || + bNeuMoveOnly != getMoveOnly() || bNeuRotate!=bRotate || eNeuMode!=eMode) + { + Hide(); + setMoveOnly(bNeuMoveOnly); + bRotate=bNeuRotate; + eMode=eNeuMode; + bContortion=bNeuContortion; + aCenter=aNeuCenter; + aFact=aNeuFact; + aRad=Point(nNeuRad,nNeuRad); + bResize=aFact!=Fraction(1,1) && aFact.GetDenominator()!=0 && aFact.IsValid(); + DragStat().NextMove(aPnt); + Show(); + } + } +} + +void SdrDragCrook::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + const bool bDoResize(aFact!=Fraction(1,1)); + const bool bDoCrook(aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0); + + if (bDoCrook || bDoResize) + { + if (bDoResize) + { + Fraction aFact1(1,1); + + if (bContortion) + { + if (bVertical) + { + rTarget.Resize(aCenter,aFact1,aFact); + } + else + { + rTarget.Resize(aCenter,aFact,aFact1); + } + } + else + { + Point aCtr0(rTarget.GetSnapRect().Center()); + Point aCtr1(aCtr0); + + if (bVertical) + { + ResizePoint(aCtr1,aCenter,aFact1,aFact); + } + else + { + ResizePoint(aCtr1,aCenter,aFact,aFact1); + } + + Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y()); + + rTarget.Move(aSiz); + } + } + + if (bDoCrook) + { + const Rectangle aLocalMarkRect(getSdrDragView().GetMarkedObjRect()); + const bool bLocalRotate(!bContortion && eMode == SDRCROOK_ROTATE && getSdrDragView().IsRotateAllowed(false)); + + getSdrDragView().ImpCrookObj(&rTarget,aCenter,aRad,eMode,bVertical,!bContortion,bLocalRotate,aLocalMarkRect); + } + } +} + +void SdrDragCrook::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget) +{ + // use helper derived from old stuff + _MovAllPoints(rTarget); +} + +bool SdrDragCrook::EndSdrDrag(bool bCopy) +{ + Hide(); + + if (bResize && aFact==Fraction(1,1)) + bResize=false; + + const bool bUndo = getSdrDragView().IsUndoEnabled(); + + bool bDoCrook=aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0; + + if (bDoCrook || bResize) + { + if (bResize && bUndo) + { + XubString aStr; + ImpTakeDescriptionStr(!bContortion?STR_EditCrook:STR_EditCrookContortion,aStr); + + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + + getSdrDragView().BegUndo(aStr); + } + + if (bResize) + { + Fraction aFact1(1,1); + + if (bContortion) + { + if (bVertical) + getSdrDragView().ResizeMarkedObj(aCenter,aFact1,aFact,bCopy); + else + getSdrDragView().ResizeMarkedObj(aCenter,aFact,aFact1,bCopy); + } + else + { + if (bCopy) + getSdrDragView().CopyMarkedObj(); + + ULONG nMarkAnz=getSdrDragView().GetMarkedObjectList().GetMarkCount(); + + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=getSdrDragView().GetMarkedObjectList().GetMark(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + Point aCtr0(pO->GetSnapRect().Center()); + Point aCtr1(aCtr0); + + if (bVertical) + ResizePoint(aCtr1,aCenter,aFact1,aFact); + else + ResizePoint(aCtr1,aCenter,aFact,aFact1); + + Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y()); + if( bUndo ) + AddUndo(getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,aSiz)); + pO->Move(aSiz); + } + } + + bCopy=false; + } + + if (bDoCrook) + { + getSdrDragView().CrookMarkedObj(aCenter,aRad,eMode,bVertical,!bContortion,bCopy); + getSdrDragView().SetLastCrookCenter(aCenter); + } + + if (bResize && bUndo) + getSdrDragView().EndUndo(); + + return true; + } + + return false; +} + +Pointer SdrDragCrook::GetSdrDragPointer() const +{ + return Pointer(POINTER_CROOK); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragDistort,SdrDragMethod); + +SdrDragDistort::SdrDragDistort(SdrDragView& rNewView) +: SdrDragMethod(rNewView), + nPolyPt(0), + bContortionAllowed(false), + bNoContortionAllowed(false), + bContortion(false) +{ +} + +void SdrDragDistort::TakeSdrDragComment(XubString& rStr) const +{ + ImpTakeDescriptionStr(STR_DragMethDistort, rStr); + + XubString aStr; + + rStr.AppendAscii(" (x="); + getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr); + rStr += aStr; + rStr.AppendAscii(" y="); + getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr); + rStr += aStr; + rStr += sal_Unicode(')'); + + if(getSdrDragView().IsDragWithCopy()) + rStr += ImpGetResStr(STR_EditWithCopy); +} + +void SdrDragDistort::createSdrDragEntries() +{ + // Add extended frame raster first, so it will be behind objects + if(getSdrDragView().GetSdrPageView()) + { + const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect())); + + if(aDragRaster.count()) + { + addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster)); + } + } + + // call parent + SdrDragMethod::createSdrDragEntries(); +} + +bool SdrDragDistort::BeginSdrDrag() +{ + bContortionAllowed=getSdrDragView().IsDistortAllowed(false); + bNoContortionAllowed=getSdrDragView().IsDistortAllowed(true); + + if (bContortionAllowed || bNoContortionAllowed) + { + SdrHdlKind eKind=GetDragHdlKind(); + nPolyPt=0xFFFF; + + if (eKind==HDL_UPLFT) nPolyPt=0; + if (eKind==HDL_UPRGT) nPolyPt=1; + if (eKind==HDL_LWRGT) nPolyPt=2; + if (eKind==HDL_LWLFT) nPolyPt=3; + if (nPolyPt>3) return false; + + aMarkRect=GetMarkedRect(); + aDistortedRect=XPolygon(aMarkRect); + Show(); + return true; + } + else + { + return false; + } +} + +void SdrDragDistort::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget) +{ + if (bContortion) + { + SdrPageView* pPV = getSdrDragView().GetSdrPageView(); + + if(pPV) + { + if (pPV->HasMarkedObjPageView()) + { + basegfx::B2DPolyPolygon aDragPolygon(rTarget); + const basegfx::B2DRange aOriginalRange(aMarkRect.Left(), aMarkRect.Top(), aMarkRect.Right(), aMarkRect.Bottom()); + const basegfx::B2DPoint aTopLeft(aDistortedRect[0].X(), aDistortedRect[0].Y()); + const basegfx::B2DPoint aTopRight(aDistortedRect[1].X(), aDistortedRect[1].Y()); + const basegfx::B2DPoint aBottomLeft(aDistortedRect[3].X(), aDistortedRect[3].Y()); + const basegfx::B2DPoint aBottomRight(aDistortedRect[2].X(), aDistortedRect[2].Y()); + + aDragPolygon = basegfx::tools::distort(aDragPolygon, aOriginalRange, aTopLeft, aTopRight, aBottomLeft, aBottomRight); + rTarget = aDragPolygon; + } + } + } +} + +void SdrDragDistort::MoveSdrDrag(const Point& rPnt) +{ + if (DragStat().CheckMinMoved(rPnt)) + { + Point aPnt(GetSnapPos(rPnt)); + + if (getSdrDragView().IsOrtho()) + OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho()); + + bool bNeuContortion=(bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed; + + if (bNeuContortion!=bContortion || aDistortedRect[nPolyPt]!=aPnt) + { + Hide(); + aDistortedRect[nPolyPt]=aPnt; + bContortion=bNeuContortion; + DragStat().NextMove(aPnt); + Show(); + } + } +} + +bool SdrDragDistort::EndSdrDrag(bool bCopy) +{ + Hide(); + bool bDoDistort=DragStat().GetDX()!=0 || DragStat().GetDY()!=0; + + if (bDoDistort) + { + getSdrDragView().DistortMarkedObj(aMarkRect,aDistortedRect,!bContortion,bCopy); + return true; + } + + return false; +} + +Pointer SdrDragDistort::GetSdrDragPointer() const +{ + return Pointer(POINTER_REFHAND); +} + +void SdrDragDistort::applyCurrentTransformationToSdrObject(SdrObject& rTarget) +{ + const bool bDoDistort(DragStat().GetDX()!=0 || DragStat().GetDY()!=0); + + if (bDoDistort) + { + getSdrDragView().ImpDistortObj(&rTarget, aMarkRect, aDistortedRect, !bContortion); + } +} + +void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget) +{ + // use helper derived from old stuff + _MovAllPoints(rTarget); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrDragCrop,SdrDragResize); + +SdrDragCrop::SdrDragCrop(SdrDragView& rNewView) +: SdrDragResize(rNewView) +{ + // switch off solid dragging for crop; it just makes no sense since showing + // a 50% transparent object above the original will not be visible + setSolidDraggingActive(false); +} + +void SdrDragCrop::TakeSdrDragComment(XubString& rStr) const +{ + ImpTakeDescriptionStr(STR_DragMethCrop, rStr); + + XubString aStr; + + rStr.AppendAscii(" (x="); + getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr); + rStr += aStr; + rStr.AppendAscii(" y="); + getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr); + rStr += aStr; + rStr += sal_Unicode(')'); + + if(getSdrDragView().IsDragWithCopy()) + rStr += ImpGetResStr(STR_EditWithCopy); +} + +bool SdrDragCrop::EndSdrDrag(bool bCopy) +{ + Hide(); + + if( DragStat().GetDX()==0 && DragStat().GetDY()==0 ) + return false; + + const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList(); + + if( rMarkList.GetMarkCount() != 1 ) + return false; + + SdrGrafObj* pObj = dynamic_cast<SdrGrafObj*>( rMarkList.GetMark( 0 )->GetMarkedSdrObj() ); + + if( !pObj || (pObj->GetGraphicType() == GRAPHIC_NONE) || (pObj->GetGraphicType() == GRAPHIC_DEFAULT) ) + return false; + + const GraphicObject& rGraphicObject = pObj->GetGraphicObject(); + const MapMode aMapMode100thmm(MAP_100TH_MM); + Size aGraphicSize(rGraphicObject.GetPrefSize()); + + if( MAP_PIXEL == rGraphicObject.GetPrefMapMode().GetMapUnit() ) + aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphicSize, aMapMode100thmm ); + else + aGraphicSize = Application::GetDefaultDevice()->LogicToLogic( aGraphicSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm); + + if( aGraphicSize.nA == 0 || aGraphicSize.nB == 0 ) + return false; + + const SdrGrafCropItem& rOldCrop = (const SdrGrafCropItem&)pObj->GetMergedItem(SDRATTR_GRAFCROP); + + const bool bUndo = getSdrDragView().IsUndoEnabled(); + + if( bUndo ) + { + String aUndoStr; + ImpTakeDescriptionStr(STR_DragMethCrop, aUndoStr); + + getSdrDragView().BegUndo( aUndoStr ); + getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) ); + } + + Rectangle aOldRect( pObj->GetLogicRect() ); + getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy); + Rectangle aNewRect( pObj->GetLogicRect() ); + + double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth(); + double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight(); + + sal_Int32 nDiffLeft = aNewRect.nLeft - aOldRect.nLeft; + sal_Int32 nDiffTop = aNewRect.nTop - aOldRect.nTop; + sal_Int32 nDiffRight = aNewRect.nRight - aOldRect.nRight; + sal_Int32 nDiffBottom = aNewRect.nBottom - aOldRect.nBottom; + + sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX ); + sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY ); + sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX ); + sal_Int32 nBottomCrop = static_cast<sal_Int32>( rOldCrop.GetBottom() - nDiffBottom * fScaleY ); + + SfxItemPool& rPool = getSdrDragView().GetModel()->GetItemPool(); + SfxItemSet aSet( rPool, SDRATTR_GRAFCROP, SDRATTR_GRAFCROP ); + aSet.Put( SdrGrafCropItem( nLeftCrop, nTopCrop, nRightCrop, nBottomCrop ) ); + getSdrDragView().SetAttributes( aSet, false ); + + if( bUndo ) + getSdrDragView().EndUndo(); + + return true; +} + +Pointer SdrDragCrop::GetSdrDragPointer() const +{ + return Pointer(POINTER_CROP); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svddrgv.cxx b/svx/source/svdraw/svddrgv.cxx new file mode 100644 index 000000000000..f1b84ac5f98e --- /dev/null +++ b/svx/source/svdraw/svddrgv.cxx @@ -0,0 +1,1006 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svddrgv.hxx> +#include "xattr.hxx" +#include <svx/xpoly.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdoedge.hxx> +#include "svdstr.hrc" +#include "svdglob.hxx" +#include "svddrgm1.hxx" +#include <svx/obj3d.hxx> +#include <svx/svdoashp.hxx> +#include <sdrpaintwindow.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <svx/polypolygoneditor.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> + +using namespace sdr; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@ @@@@@ @@@@ @@@@ @@ @@ @@ @@@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ +// @@ @@ @@@@@ @@@@@@ @@ @@@ @@@@@ @@ @@@@ @@@@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ +// @@@@@ @@ @@ @@ @@ @@@@@ @ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrDragView::ImpClearVars() +{ + bFramDrag=FALSE; + eDragMode=SDRDRAG_MOVE; + bDragLimit=FALSE; + bMarkedHitMovesAlways=FALSE; + eDragHdl=HDL_MOVE; + pDragHdl=NULL; + bDragHdl=FALSE; + bDragSpecial=FALSE; + mpCurrentSdrDragMethod=NULL; + bDragStripes=FALSE; + bMirrRefDragObj=TRUE; + bDragWithCopy=FALSE; + pInsPointUndo=NULL; + bInsGluePoint=FALSE; + bInsObjPointMode=FALSE; + bInsGluePointMode=FALSE; + nDragXorPolyLimit=100; + nDragXorPointLimit=500; + bNoDragXorPolys=FALSE; + bAutoVertexCon=TRUE; + bAutoCornerCon=FALSE; + bRubberEdgeDragging=TRUE; + nRubberEdgeDraggingLimit=100; + bDetailedEdgeDragging=TRUE; + nDetailedEdgeDraggingLimit=10; + bResizeAtCenter=FALSE; + bCrookAtCenter=FALSE; + bMouseHideWhileDraggingPoints=FALSE; + + // init using default + mbSolidDragging = getOptionsDrawinglayer().IsSolidDragCreate(); +} + +void SdrDragView::ImpMakeDragAttr() +{ + ImpDelDragAttr(); +} + +SdrDragView::SdrDragView(SdrModel* pModel1, OutputDevice* pOut) +: SdrExchangeView(pModel1,pOut) +{ + ImpClearVars(); + ImpMakeDragAttr(); +} + +SdrDragView::~SdrDragView() +{ + ImpDelDragAttr(); +} + +void SdrDragView::ImpDelDragAttr() +{ +} + +BOOL SdrDragView::IsAction() const +{ + return (mpCurrentSdrDragMethod || SdrExchangeView::IsAction()); +} + +void SdrDragView::MovAction(const Point& rPnt) +{ + SdrExchangeView::MovAction(rPnt); + if (mpCurrentSdrDragMethod) + { + MovDragObj(rPnt); + } +} + +void SdrDragView::EndAction() +{ + if (mpCurrentSdrDragMethod) + { + EndDragObj(FALSE); + } + SdrExchangeView::EndAction(); +} + +void SdrDragView::BckAction() +{ + SdrExchangeView::BckAction(); + BrkDragObj(); +} + +void SdrDragView::BrkAction() +{ + SdrExchangeView::BrkAction(); + BrkDragObj(); +} + +void SdrDragView::TakeActionRect(Rectangle& rRect) const +{ + if (mpCurrentSdrDragMethod) + { + rRect=aDragStat.GetActionRect(); + if (rRect.IsEmpty()) + { + SdrPageView* pPV = GetSdrPageView(); + + if(pPV&& pPV->HasMarkedObjPageView()) + { + // #i95646# is this used..? + const basegfx::B2DRange aBoundRange(mpCurrentSdrDragMethod->getCurrentRange()); + rRect = Rectangle( + basegfx::fround(aBoundRange.getMinX()), basegfx::fround(aBoundRange.getMinY()), + basegfx::fround(aBoundRange.getMaxX()), basegfx::fround(aBoundRange.getMaxY())); + } + } + if (rRect.IsEmpty()) + { + rRect=Rectangle(aDragStat.GetNow(),aDragStat.GetNow()); + } + } + else + { + SdrExchangeView::TakeActionRect(rRect); + } +} + +BOOL SdrDragView::TakeDragObjAnchorPos(Point& rPos, BOOL bTR ) const +{ + Rectangle aR; + TakeActionRect(aR); + rPos = bTR ? aR.TopRight() : aR.TopLeft(); + if (GetMarkedObjectCount()==1 && IsDragObj() && // nur bei Einzelselektion + !IsDraggingPoints() && !IsDraggingGluePoints() && // nicht beim Punkteschieben + !mpCurrentSdrDragMethod->ISA(SdrDragMovHdl)) // nicht beim Handlesschieben + { + SdrObject* pObj=GetMarkedObjectByIndex(0); + if (pObj->ISA(SdrCaptionObj)) + { + Point aPt(((SdrCaptionObj*)pObj)->GetTailPos()); + BOOL bTail=eDragHdl==HDL_POLY; // Schwanz wird gedraggt (nicht so ganz feine Abfrage hier) + BOOL bOwn=mpCurrentSdrDragMethod->ISA(SdrDragObjOwn); // Objektspeziefisch + if (!bTail) + { // bei bTail liefert TakeActionRect schon das richtige + if (bOwn) + { // bOwn kann sein MoveTextFrame, ResizeTextFrame aber eben nicht mehr DragTail + rPos=aPt; + } + else + { + // drag the whole Object (Move, Resize, ...) + const basegfx::B2DPoint aTransformed(mpCurrentSdrDragMethod->getCurrentTransformation() * basegfx::B2DPoint(aPt.X(), aPt.Y())); + rPos.X() = basegfx::fround(aTransformed.getX()); + rPos.Y() = basegfx::fround(aTransformed.getY()); + } + } + } + return TRUE; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrDragView::TakeDragLimit(SdrDragMode /*eMode*/, Rectangle& /*rRect*/) const +{ + return FALSE; +} + +BOOL SdrDragView::BegDragObj(const Point& rPnt, OutputDevice* pOut, SdrHdl* pHdl, short nMinMov, SdrDragMethod* pForcedMeth) +{ + BrkAction(); + + bool bRet=false; + { + SetDragWithCopy(FALSE); + //ForceEdgesOfMarkedNodes(); + //TODO: aAni.Reset(); + mpCurrentSdrDragMethod=NULL; + bDragSpecial=FALSE; + bDragLimit=FALSE; + SdrDragMode eTmpMode=eDragMode; + if (eTmpMode==SDRDRAG_MOVE && pHdl!=NULL && pHdl->GetKind()!=HDL_MOVE) { + eTmpMode=SDRDRAG_RESIZE; + } + bDragLimit=TakeDragLimit(eTmpMode,aDragLimit); + bFramDrag=ImpIsFrameHandles(); + if (!bFramDrag && + (pMarkedObj==NULL || !pMarkedObj->hasSpecialDrag()) && + (pHdl==NULL || pHdl->GetObj()==NULL)) { + bFramDrag=TRUE; + } + + Point aPnt(rPnt); + if(pHdl == NULL + || pHdl->GetKind() == HDL_MOVE + || pHdl->GetKind() == HDL_MIRX + || pHdl->GetKind() == HDL_TRNS + || pHdl->GetKind() == HDL_GRAD) + { + aDragStat.Reset(aPnt); + } + else + { + aDragStat.Reset(pHdl->GetPos()); + } + + aDragStat.SetView((SdrView*)this); + aDragStat.SetPageView(pMarkedPV); // <<-- hier muss die DragPV rein!!! + aDragStat.SetMinMove(ImpGetMinMovLogic(nMinMov,pOut)); + aDragStat.SetHdl(pHdl); + aDragStat.NextPoint(); + pDragWin=pOut; + pDragHdl=pHdl; + eDragHdl= pHdl==NULL ? HDL_MOVE : pHdl->GetKind(); + bDragHdl=eDragHdl==HDL_REF1 || eDragHdl==HDL_REF2 || eDragHdl==HDL_MIRX; + + // #103894# Expand test for HDL_ANCHOR_TR + BOOL bNotDraggable = (HDL_ANCHOR == eDragHdl || HDL_ANCHOR_TR == eDragHdl); + + if(pHdl && (pHdl->GetKind() == HDL_SMARTTAG) && pForcedMeth ) + { + // just use the forced method for smart tags + } + else if(bDragHdl) + { + mpCurrentSdrDragMethod = new SdrDragMovHdl(*this); + } + else if(!bNotDraggable) + { + switch (eDragMode) + { + case SDRDRAG_ROTATE: case SDRDRAG_SHEAR: case SDRDRAG_DISTORT: + { + switch (eDragHdl) + { + case HDL_LEFT: case HDL_RIGHT: + case HDL_UPPER: case HDL_LOWER: + { + // Sind 3D-Objekte selektiert? + BOOL b3DObjSelected = FALSE; + for(UINT32 a=0;!b3DObjSelected && a<GetMarkedObjectCount();a++) + { + SdrObject* pObj = GetMarkedObjectByIndex(a); + if(pObj && pObj->ISA(E3dObject)) + b3DObjSelected = TRUE; + } + // Falls ja, Shear auch bei !IsShearAllowed zulassen, + // da es sich bei 3D-Objekten um eingeschraenkte + // Rotationen handelt + if (!b3DObjSelected && !IsShearAllowed()) + return FALSE; + mpCurrentSdrDragMethod = new SdrDragShear(*this,eDragMode==SDRDRAG_ROTATE); + } break; + case HDL_UPLFT: case HDL_UPRGT: + case HDL_LWLFT: case HDL_LWRGT: + { + if (eDragMode==SDRDRAG_SHEAR || eDragMode==SDRDRAG_DISTORT) + { + if (!IsDistortAllowed(TRUE) && !IsDistortAllowed(FALSE)) return FALSE; + mpCurrentSdrDragMethod = new SdrDragDistort(*this); + } + else + { + if (!IsRotateAllowed(TRUE)) return FALSE; + mpCurrentSdrDragMethod = new SdrDragRotate(*this); + } + } break; + default: + { + if (IsMarkedHitMovesAlways() && eDragHdl==HDL_MOVE) + { // HDL_MOVE ist auch wenn Obj direkt getroffen + if (!IsMoveAllowed()) return FALSE; + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if (!IsRotateAllowed(TRUE)) return FALSE; + mpCurrentSdrDragMethod = new SdrDragRotate(*this); + } + } + } + } break; + case SDRDRAG_MIRROR: + { + if (eDragHdl==HDL_MOVE && IsMarkedHitMovesAlways()) + { + if (!IsMoveAllowed()) return FALSE; + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if (!IsMirrorAllowed(TRUE,TRUE)) return FALSE; + mpCurrentSdrDragMethod = new SdrDragMirror(*this); + } + } break; + + case SDRDRAG_CROP: + { + if (eDragHdl==HDL_MOVE && IsMarkedHitMovesAlways()) + { + if (!IsMoveAllowed()) + return FALSE; + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if (!IsCrookAllowed(TRUE) && !IsCrookAllowed(FALSE)) + return FALSE; + mpCurrentSdrDragMethod = new SdrDragCrop(*this); + } + } + break; + + case SDRDRAG_TRANSPARENCE: + { + if(eDragHdl == HDL_MOVE && IsMarkedHitMovesAlways()) + { + if(!IsMoveAllowed()) + return FALSE; + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if(!IsTransparenceAllowed()) + return FALSE; + + mpCurrentSdrDragMethod = new SdrDragGradient(*this, FALSE); + } + break; + } + case SDRDRAG_GRADIENT: + { + if(eDragHdl == HDL_MOVE && IsMarkedHitMovesAlways()) + { + if(!IsMoveAllowed()) + return FALSE; + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if(!IsGradientAllowed()) + return FALSE; + + mpCurrentSdrDragMethod = new SdrDragGradient(*this); + } + break; + } + + case SDRDRAG_CROOK : + { + if (eDragHdl==HDL_MOVE && IsMarkedHitMovesAlways()) + { + if (!IsMoveAllowed()) return FALSE; + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if (!IsCrookAllowed(TRUE) && !IsCrookAllowed(FALSE)) return FALSE; + mpCurrentSdrDragMethod = new SdrDragCrook(*this); + } + } break; + + default: + { + // SDRDRAG_MOVE + if((eDragHdl == HDL_MOVE) && !IsMoveAllowed()) + { + return FALSE; + } + else if(eDragHdl == HDL_GLUE) + { + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if(bFramDrag) + { + if(eDragHdl == HDL_MOVE) + { + mpCurrentSdrDragMethod = new SdrDragMove(*this); + } + else + { + if(!IsResizeAllowed(TRUE)) + { + return FALSE; + } + + sal_Bool bSingleTextObjMark = sal_False; // SJ: #i100490# + if ( GetMarkedObjectCount() == 1 ) + { + pMarkedObj=GetMarkedObjectByIndex(0); + if ( pMarkedObj && + pMarkedObj->ISA( SdrTextObj ) && + static_cast<SdrTextObj*>(pMarkedObj)->IsTextFrame() ) + bSingleTextObjMark = sal_True; + } + if ( bSingleTextObjMark ) + mpCurrentSdrDragMethod = new SdrDragObjOwn(*this); + else + mpCurrentSdrDragMethod = new SdrDragResize(*this); + } + } + else + { + if(HDL_MOVE == eDragHdl) + { + const bool bCustomShapeSelected(1 == GetMarkedObjectCount() && GetMarkedObjectByIndex(0)->ISA(SdrObjCustomShape)); + + if(bCustomShapeSelected) + { + mpCurrentSdrDragMethod = new SdrDragMove( *this ); + } + } + else if(HDL_POLY == eDragHdl) + { + const bool bConnectorSelected(1 == GetMarkedObjectCount() && GetMarkedObjectByIndex(0)->ISA(SdrEdgeObj)); + + if(bConnectorSelected) + { + // #i97784# + // fallback to old behaviour for connectors (see + // text in task description for more details) + } + else if(!IsMoveAllowed() || !IsResizeAllowed()) + { + // #i77187# + // do not allow move of polygon points if object is move or size protected + return FALSE; + } + } + + if(!mpCurrentSdrDragMethod) + { + // fallback to DragSpecial if no interaction defined + bDragSpecial = TRUE; + mpCurrentSdrDragMethod = new SdrDragObjOwn(*this); + } + } + } + } + } + } + if (pForcedMeth!=NULL) + { + delete mpCurrentSdrDragMethod; + mpCurrentSdrDragMethod = pForcedMeth; + } + aDragStat.SetDragMethod(mpCurrentSdrDragMethod); + if (mpCurrentSdrDragMethod) + { + bRet = mpCurrentSdrDragMethod->BeginSdrDrag(); + if (!bRet) + { + if (pHdl==NULL && IS_TYPE(SdrDragObjOwn,mpCurrentSdrDragMethod)) + { + // Aha, Obj kann nicht Move SpecialDrag, also MoveFrameDrag versuchen + delete mpCurrentSdrDragMethod; + mpCurrentSdrDragMethod = 0; + bDragSpecial=FALSE; + + if (!IsMoveAllowed()) + return FALSE; + + bFramDrag=TRUE; + mpCurrentSdrDragMethod = new SdrDragMove(*this); + aDragStat.SetDragMethod(mpCurrentSdrDragMethod); + bRet = mpCurrentSdrDragMethod->BeginSdrDrag(); + } + } + if (!bRet) + { + delete mpCurrentSdrDragMethod; + mpCurrentSdrDragMethod = 0; + aDragStat.SetDragMethod(mpCurrentSdrDragMethod); + } + } + } + + return bRet; +} + +void SdrDragView::MovDragObj(const Point& rPnt) +{ + if (mpCurrentSdrDragMethod) + { + Point aPnt(rPnt); + ImpLimitToWorkArea(aPnt); + mpCurrentSdrDragMethod->MoveSdrDrag(aPnt); // this call already makes a Hide()/Show combination + } +} + +BOOL SdrDragView::EndDragObj(BOOL bCopy) +{ + bool bRet(false); + + // #i73341# If insert GluePoint, do not insist on last points being different + if(mpCurrentSdrDragMethod && aDragStat.IsMinMoved() && (IsInsertGluePoint() || aDragStat.GetNow() != aDragStat.GetPrev())) + { + ULONG nHdlAnzMerk=0; + + if (bEliminatePolyPoints) + { // IBM Special + nHdlAnzMerk=GetMarkablePointCount(); + } + + const bool bUndo = IsUndoEnabled(); + if (IsInsertGluePoint() && bUndo) + { + BegUndo(aInsPointUndoStr); + AddUndo(pInsPointUndo); + } + + bRet = mpCurrentSdrDragMethod->EndSdrDrag(bCopy); + + if( IsInsertGluePoint() && bUndo) + EndUndo(); + + delete mpCurrentSdrDragMethod; + mpCurrentSdrDragMethod = 0; + + if (bEliminatePolyPoints) + { // IBM Special + if (nHdlAnzMerk!=GetMarkablePointCount()) + { + UnmarkAllPoints(); + } + } + + if (bInsPolyPoint) + { + SetMarkHandles(); + bInsPolyPoint=FALSE; + if( bUndo ) + { + BegUndo(aInsPointUndoStr); + AddUndo(pInsPointUndo); + EndUndo(); + } + } + + eDragHdl=HDL_MOVE; + pDragHdl=NULL; + + if (!bSomeObjChgdFlag) + { + // Aha, Obj hat nicht gebroadcastet (z.B. Writer FlyFrames) + if(!bDragHdl) + { + AdjustMarkHdl(); + } + } + } + else + { + BrkDragObj(); + } + + bInsPolyPoint=FALSE; + SetInsertGluePoint(FALSE); + + return bRet; +} + +void SdrDragView::BrkDragObj() +{ + if (mpCurrentSdrDragMethod) + { + mpCurrentSdrDragMethod->CancelSdrDrag(); + + delete mpCurrentSdrDragMethod; + mpCurrentSdrDragMethod = 0; + + if (bInsPolyPoint) + { + pInsPointUndo->Undo(); // Den eingefuegten Punkt wieder raus + delete pInsPointUndo; + pInsPointUndo=NULL; + SetMarkHandles(); + bInsPolyPoint=FALSE; + } + + if (IsInsertGluePoint()) + { + pInsPointUndo->Undo(); // Den eingefuegten Klebepunkt wieder raus + delete pInsPointUndo; + pInsPointUndo=NULL; + SetInsertGluePoint(FALSE); + } + + eDragHdl=HDL_MOVE; + pDragHdl=NULL; + } +} + +BOOL SdrDragView::IsInsObjPointPossible() const +{ + return pMarkedObj!=NULL && pMarkedObj->IsPolyObj(); +} + +sal_Bool SdrDragView::ImpBegInsObjPoint(sal_Bool bIdxZwang, sal_uInt32 nIdx, const Point& rPnt, sal_Bool bNewObj, OutputDevice* pOut) +{ + sal_Bool bRet(sal_False); + + if(pMarkedObj && pMarkedObj->ISA(SdrPathObj)) + { + SdrPathObj* pMarkedPath = (SdrPathObj*)pMarkedObj; + BrkAction(); + pInsPointUndo = dynamic_cast< SdrUndoGeoObj* >( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pMarkedObj) ); + DBG_ASSERT( pInsPointUndo, "svx::SdrDragView::BegInsObjPoint(), could not create correct undo object!" ); + + XubString aStr(ImpGetResStr(STR_DragInsertPoint)); + XubString aName; + pMarkedObj->TakeObjNameSingul(aName); + xub_StrLen nPos(aStr.SearchAscii("%1")); + + if(STRING_NOTFOUND != nPos) + { + aStr.Erase(nPos, 2); + aStr.Insert(aName, nPos); + } + + aInsPointUndoStr = aStr; + Point aPt(rPnt); + + if(bNewObj) + aPt = GetSnapPos(aPt,pMarkedPV); + + sal_Bool bClosed0(pMarkedPath->IsClosedObj()); + + if(bIdxZwang) + { + mnInsPointNum = pMarkedPath->NbcInsPoint(nIdx, aPt, bNewObj, sal_True); + } + else + { + mnInsPointNum = pMarkedPath->NbcInsPointOld(aPt, bNewObj, sal_True); + } + + if(bClosed0 != pMarkedPath->IsClosedObj()) + { + // Obj was closed implicit + // object changed + pMarkedPath->SetChanged(); + pMarkedPath->BroadcastObjectChange(); + } + + if(0xffffffff != mnInsPointNum) + { + bInsPolyPoint = sal_True; + UnmarkAllPoints(); + AdjustMarkHdl(); + + bRet = BegDragObj(rPnt, pOut, aHdl.GetHdl(mnInsPointNum), 0); + + if (bRet) + { + aDragStat.SetMinMoved(); + MovDragObj(rPnt); + } + } + else + { + delete pInsPointUndo; + pInsPointUndo = NULL; + } + } + + return bRet; +} + +BOOL SdrDragView::EndInsObjPoint(SdrCreateCmd eCmd) +{ + if(IsInsObjPoint()) + { + sal_uInt32 nNextPnt(mnInsPointNum); + Point aPnt(aDragStat.GetNow()); + BOOL bOk=EndDragObj(FALSE); + if (bOk==TRUE && eCmd!=SDRCREATE_FORCEEND) + { + // Ret=True bedeutet: Action ist vorbei. + bOk=!(ImpBegInsObjPoint(sal_True, nNextPnt, aPnt, eCmd == SDRCREATE_NEXTOBJECT, pDragWin)); + } + + return bOk; + } else return FALSE; +} + +BOOL SdrDragView::IsInsGluePointPossible() const +{ + BOOL bRet=FALSE; + if (IsInsGluePointMode() && AreObjectsMarked()) + { + if (GetMarkedObjectCount()==1) + { + // FALSE liefern, wenn 1 Objekt und dieses ein Verbinder ist. + const SdrObject* pObj=GetMarkedObjectByIndex(0); + if (!HAS_BASE(SdrEdgeObj,pObj)) + { + bRet=TRUE; + } + } + else + { + bRet=TRUE; + } + } + return bRet; +} + +BOOL SdrDragView::BegInsGluePoint(const Point& rPnt) +{ + BOOL bRet=FALSE; + SdrObject* pObj; + SdrPageView* pPV; + ULONG nMarkNum; + if (PickMarkedObj(rPnt,pObj,pPV,&nMarkNum,SDRSEARCH_PASS2BOUND)) + { + BrkAction(); + UnmarkAllGluePoints(); + pInsPointUndo= dynamic_cast< SdrUndoGeoObj* >( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj) ); + DBG_ASSERT( pInsPointUndo, "svx::SdrDragView::BegInsObjPoint(), could not create correct undo object!" ); + XubString aStr(ImpGetResStr(STR_DragInsertGluePoint)); + XubString aName; pObj->TakeObjNameSingul(aName); + + aStr.SearchAndReplaceAscii("%1", aName); + + aInsPointUndoStr=aStr; + SdrGluePointList* pGPL=pObj->ForceGluePointList(); + if (pGPL!=NULL) + { + USHORT nGlueIdx=pGPL->Insert(SdrGluePoint()); + SdrGluePoint& rGP=(*pGPL)[nGlueIdx]; + USHORT nGlueId=rGP.GetId(); + rGP.SetAbsolutePos(rPnt,*pObj); + + SdrHdl* pHdl=NULL; + if (MarkGluePoint(pObj,nGlueId,pPV)) + { + pHdl=GetGluePointHdl(pObj,nGlueId); + } + if (pHdl!=NULL && pHdl->GetKind()==HDL_GLUE && pHdl->GetObj()==pObj && pHdl->GetObjHdlNum()==nGlueId) + { + SetInsertGluePoint(TRUE); + bRet=BegDragObj(rPnt,NULL,pHdl,0); + if (bRet) + { + aDragStat.SetMinMoved(); + MovDragObj(rPnt); + } + else + { + SetInsertGluePoint(FALSE); + delete pInsPointUndo; + pInsPointUndo=NULL; + } + } + else + { + DBG_ERROR("BegInsGluePoint(): GluePoint-Handle nicht gefunden"); + } + } + else + { + // Keine Klebepunkte moeglich bei diesem Objekt (z.B. Edge) + SetInsertGluePoint(FALSE); + delete pInsPointUndo; + pInsPointUndo=NULL; + } + } + + return bRet; +} + +void SdrDragView::ShowDragObj() +{ + if(mpCurrentSdrDragMethod && !aDragStat.IsShown()) + { + for(sal_uInt32 a(0); a < PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = GetPaintWindow(a); + sdr::overlay::OverlayManager* pOverlayManager = pCandidate->GetOverlayManager(); + + if(pOverlayManager) + { + mpCurrentSdrDragMethod->CreateOverlayGeometry(*pOverlayManager); + + // #i101679# Force changed overlay to be shown + pOverlayManager->flush(); + } + } + + aDragStat.SetShown(TRUE); + } +} + +void SdrDragView::HideDragObj() +{ + if(mpCurrentSdrDragMethod && aDragStat.IsShown()) + { + mpCurrentSdrDragMethod->destroyOverlayGeometry(); + aDragStat.SetShown(FALSE); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrDragView::SetNoDragXorPolys(BOOL bOn) +{ + if (IsNoDragXorPolys()!=bOn) + { + const bool bDragging(mpCurrentSdrDragMethod); + const bool bShown(bDragging && aDragStat.IsShown()); + + if(bShown) + { + HideDragObj(); + } + + bNoDragXorPolys = bOn; + + if(bDragging) + { + // force recreation of drag content + mpCurrentSdrDragMethod->resetSdrDragEntries(); + } + + if(bShown) + { + ShowDragObj(); + } + } +} + +void SdrDragView::SetDragStripes(BOOL bOn) +{ + if (mpCurrentSdrDragMethod && aDragStat.IsShown()) + { + HideDragObj(); + bDragStripes=bOn; + ShowDragObj(); + } + else + { + bDragStripes=bOn; + } +} + +BOOL SdrDragView::IsOrthoDesired() const +{ + if(mpCurrentSdrDragMethod && (IS_TYPE(SdrDragObjOwn, mpCurrentSdrDragMethod) || IS_TYPE(SdrDragResize, mpCurrentSdrDragMethod))) + { + return bOrthoDesiredOnMarked; + } + + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrDragView::SetRubberEdgeDragging(BOOL bOn) +{ + if (bOn!=IsRubberEdgeDragging()) + { + ULONG nAnz = GetEdgesOfMarkedNodes().GetMarkCount(); + BOOL bShowHide=nAnz!=0 && IsDragObj() && + (nRubberEdgeDraggingLimit>=nAnz); + if (bShowHide) + HideDragObj(); + bRubberEdgeDragging=bOn; + if (bShowHide) + ShowDragObj(); + } +} + +void SdrDragView::SetRubberEdgeDraggingLimit(USHORT nEdgeObjAnz) +{ + if (nEdgeObjAnz!=nRubberEdgeDraggingLimit) + { + ULONG nAnz = GetEdgesOfMarkedNodes().GetMarkCount(); + BOOL bShowHide=IsRubberEdgeDragging() && nAnz!=0 && IsDragObj() && + (nEdgeObjAnz>=nAnz)!=(nRubberEdgeDraggingLimit>=nAnz); + if (bShowHide) + HideDragObj(); + nRubberEdgeDraggingLimit=nEdgeObjAnz; + if (bShowHide) + ShowDragObj(); + } +} + +void SdrDragView::SetDetailedEdgeDragging(BOOL bOn) +{ + if (bOn!=IsDetailedEdgeDragging()) + { + ULONG nAnz = GetEdgesOfMarkedNodes().GetMarkCount(); + BOOL bShowHide=nAnz!=0 && IsDragObj() && + (nDetailedEdgeDraggingLimit>=nAnz); + if (bShowHide) + HideDragObj(); + bDetailedEdgeDragging=bOn; + if (bShowHide) + ShowDragObj(); + } +} + +void SdrDragView::SetDetailedEdgeDraggingLimit(USHORT nEdgeObjAnz) +{ + if (nEdgeObjAnz!=nDetailedEdgeDraggingLimit) + { + ULONG nAnz = GetEdgesOfMarkedNodes().GetMarkCount(); + BOOL bShowHide=IsDetailedEdgeDragging() && nAnz!=0 && IsDragObj() && + (nEdgeObjAnz>=nAnz)!=(nDetailedEdgeDraggingLimit>=nAnz); + if (bShowHide) + HideDragObj(); + nDetailedEdgeDraggingLimit=nEdgeObjAnz; + if (bShowHide) + ShowDragObj(); + } +} + +void SdrDragView::SetMarkHandles() +{ + if( pDragHdl ) + pDragHdl = 0; + + SdrExchangeView::SetMarkHandles(); +} + +void SdrDragView::SetSolidDragging(bool bOn) +{ + if((bool)mbSolidDragging != bOn) + { + mbSolidDragging = bOn; + } +} + +bool SdrDragView::IsSolidDragging() const +{ + // allow each user to disable by having a local setting, but using AND for + // checking allowance + return mbSolidDragging && getOptionsDrawinglayer().IsSolidDragCreate(); +} + +// eof diff --git a/svx/source/svdraw/svdedtv.cxx b/svx/source/svdraw/svdedtv.cxx new file mode 100644 index 000000000000..5eae04dbbc87 --- /dev/null +++ b/svx/source/svdraw/svdedtv.cxx @@ -0,0 +1,1086 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <vcl/metaact.hxx> +#include <svx/svdedtv.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdograf.hxx> // fuer Possibilities +#include <svx/svdopath.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdopage.hxx> +#include <svx/svdoedge.hxx> +#include <svx/svdlayer.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpoev.hxx> // fuer die PolyPossiblities +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include <svx/e3dsceneupdater.hxx> + +// #i13033# +#include <clonelist.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@ @@@@@ @@ @@@@@@ @@ @@ @@ @@@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ +// @@@@ @@ @@ @@ @@ @@@@@ @@ @@@@ @@@@@@@ +// @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@ +// @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ +// @@@@@ @@@@@ @@ @@ @ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEditView::ImpResetPossibilityFlags() +{ + bReadOnly =FALSE; + + bGroupPossible =FALSE; + bUnGroupPossible =FALSE; + bGrpEnterPossible =FALSE; + bDeletePossible =FALSE; + bToTopPossible =FALSE; + bToBtmPossible =FALSE; + bReverseOrderPossible =FALSE; + + bImportMtfPossible =FALSE; + bCombinePossible =FALSE; + bDismantlePossible =FALSE; + bCombineNoPolyPolyPossible =FALSE; + bDismantleMakeLinesPossible=FALSE; + bOrthoDesiredOnMarked =FALSE; + + bMoreThanOneNotMovable =FALSE; + bOneOrMoreMovable =FALSE; + bMoreThanOneNoMovRot =FALSE; + bContortionPossible =FALSE; + bAllPolys =FALSE; + bOneOrMorePolys =FALSE; + bMoveAllowed =FALSE; + bResizeFreeAllowed =FALSE; + bResizePropAllowed =FALSE; + bRotateFreeAllowed =FALSE; + bRotate90Allowed =FALSE; + bMirrorFreeAllowed =FALSE; + bMirror45Allowed =FALSE; + bMirror90Allowed =FALSE; + bTransparenceAllowed =FALSE; + bGradientAllowed =FALSE; + bShearAllowed =FALSE; + bEdgeRadiusAllowed =FALSE; + bCanConvToPath =FALSE; + bCanConvToPoly =FALSE; + bCanConvToContour =FALSE; + bCanConvToPathLineToArea=FALSE; + bCanConvToPolyLineToArea=FALSE; + bMoveProtect =FALSE; + bResizeProtect =FALSE; +} + +void SdrEditView::ImpClearVars() +{ + ImpResetPossibilityFlags(); + bPossibilitiesDirty=TRUE; // << war von Purify angemeckert + bBundleVirtObj=FALSE; +} + +SdrEditView::SdrEditView(SdrModel* pModel1, OutputDevice* pOut): + SdrMarkView(pModel1,pOut) +{ + ImpClearVars(); +} + +SdrEditView::~SdrEditView() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrLayer* SdrEditView::InsertNewLayer(const XubString& rName, USHORT nPos) +{ + SdrLayerAdmin& rLA=pMod->GetLayerAdmin(); + USHORT nMax=rLA.GetLayerCount(); + if (nPos>nMax) nPos=nMax; + SdrLayer* pNewLayer=rLA.NewLayer(rName,nPos); + + if( GetModel()->IsUndoEnabled() ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewLayer(nPos,rLA,*pMod)); + + pMod->SetChanged(); + return pNewLayer; +} + +#include <svx/svdogrp.hxx> +#include <svx/scene3d.hxx> + +BOOL SdrEditView::ImpDelLayerCheck(SdrObjList* pOL, SdrLayerID nDelID) const +{ + sal_Bool bDelAll(sal_True); + sal_uInt32 nObjAnz(pOL->GetObjCount()); + + for(sal_uInt32 nObjNum(nObjAnz); nObjNum > 0 && bDelAll;) + { + nObjNum--; + SdrObject* pObj = pOL->GetObj(nObjNum); + SdrObjList* pSubOL = pObj->GetSubList(); + + // #104809# Test explicitely for group objects and 3d scenes + if(pSubOL && (pObj->ISA(SdrObjGroup) || pObj->ISA(E3dScene))) + { + if(!ImpDelLayerCheck(pSubOL, nDelID)) + { + // Rekursion + bDelAll = sal_False; + } + } + else + { + if(pObj->GetLayer() != nDelID) + { + bDelAll = sal_False; + } + } + } + + return bDelAll; +} + +void SdrEditView::ImpDelLayerDelObjs(SdrObjList* pOL, SdrLayerID nDelID) +{ + sal_uInt32 nObjAnz(pOL->GetObjCount()); + // make sure OrdNums are correct + pOL->GetObj(0)->GetOrdNum(); + + const bool bUndo = GetModel()->IsUndoEnabled(); + + for(sal_uInt32 nObjNum(nObjAnz); nObjNum > 0;) + { + nObjNum--; + SdrObject* pObj = pOL->GetObj(nObjNum); + SdrObjList* pSubOL = pObj->GetSubList(); + + + // #104809# Test explicitely for group objects and 3d scenes + if(pSubOL && (pObj->ISA(SdrObjGroup) || pObj->ISA(E3dScene))) + { + if(ImpDelLayerCheck(pSubOL, nDelID)) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true)); + pOL->RemoveObject(nObjNum); + + if( !bUndo ) + SdrObject::Free( pObj ); + } + else + { + ImpDelLayerDelObjs(pSubOL, nDelID); + } + } + else + { + if(pObj->GetLayer() == nDelID) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true)); + pOL->RemoveObject(nObjNum); + if( !bUndo ) + SdrObject::Free( pObj ); + } + } + } +} + +void SdrEditView::DeleteLayer(const XubString& rName) +{ + SdrLayerAdmin& rLA = pMod->GetLayerAdmin(); + SdrLayer* pLayer = rLA.GetLayer(rName, TRUE); + sal_uInt16 nLayerNum(rLA.GetLayerPos(pLayer)); + + if(SDRLAYER_NOTFOUND != nLayerNum) + { + + SdrLayerID nDelID = pLayer->GetID(); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(ImpGetResStr(STR_UndoDelLayer)); + + sal_Bool bMaPg(sal_True); + + for(sal_uInt16 nPageKind(0); nPageKind < 2; nPageKind++) + { + // MasterPages and DrawPages + sal_uInt16 nPgAnz(bMaPg ? pMod->GetMasterPageCount() : pMod->GetPageCount()); + + for(sal_uInt16 nPgNum(0); nPgNum < nPgAnz; nPgNum++) + { + // over all pages + SdrPage* pPage = (bMaPg) ? pMod->GetMasterPage(nPgNum) : pMod->GetPage(nPgNum); + sal_uInt32 nObjAnz(pPage->GetObjCount()); + + // make sure OrdNums are correct + if(nObjAnz) + pPage->GetObj(0)->GetOrdNum(); + + for(sal_uInt32 nObjNum(nObjAnz); nObjNum > 0;) + { + nObjNum--; + SdrObject* pObj = pPage->GetObj(nObjNum); + SdrObjList* pSubOL = pObj->GetSubList(); + + // #104809# Test explicitely for group objects and 3d scenes + if(pSubOL && (pObj->ISA(SdrObjGroup) || pObj->ISA(E3dScene))) + { + if(ImpDelLayerCheck(pSubOL, nDelID)) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true)); + pPage->RemoveObject(nObjNum); + if( !bUndo ) + SdrObject::Free(pObj); + } + else + { + ImpDelLayerDelObjs(pSubOL, nDelID); + } + } + else + { + if(pObj->GetLayer() == nDelID) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true)); + pPage->RemoveObject(nObjNum); + if( !bUndo ) + SdrObject::Free(pObj); + } + } + } + } + bMaPg = sal_False; + } + + if( bUndo ) + { + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteLayer(nLayerNum, rLA, *pMod)); + rLA.RemoveLayer(nLayerNum); + EndUndo(); + } + else + { + delete rLA.RemoveLayer(nLayerNum); + } + + pMod->SetChanged(); + } +} + +void SdrEditView::MoveLayer(const XubString& rName, USHORT nNewPos) +{ + SdrLayerAdmin& rLA=pMod->GetLayerAdmin(); + SdrLayer* pLayer=rLA.GetLayer(rName,TRUE); + USHORT nLayerNum=rLA.GetLayerPos(pLayer); + if (nLayerNum!=SDRLAYER_NOTFOUND) + { + if( IsUndoEnabled() ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveLayer(nLayerNum,rLA,*pMod,nNewPos)); + rLA.MoveLayer(nLayerNum,nNewPos); + pMod->SetChanged(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEditView::EndUndo() +{ + // #i13033# + // Comparison changed to 1L since EndUndo() is called later now + // and EndUndo WILL change count to count-1 + if(1L == pMod->GetUndoBracketLevel()) + { + ImpBroadcastEdgesOfMarkedNodes(); + } + + // #i13033# + // moved to bottom to still have access to UNDOs inside of + // ImpBroadcastEdgesOfMarkedNodes() + pMod->EndUndo(); +} + +void SdrEditView::ImpBroadcastEdgesOfMarkedNodes() +{ + const List& rAllMarkedObjects = GetTransitiveHullOfMarkedObjects(); + + // #i13033# + // New mechanism to search for necessary disconnections for + // changed connectors inside the transitive hull of all at + // the beginning of UNDO selected objects + for(sal_uInt32 a(0L); a < rAllMarkedObjects.Count(); a++) + { + SdrEdgeObj* pEdge = PTR_CAST(SdrEdgeObj, (SdrObject*)rAllMarkedObjects.GetObject(a)); + + if(pEdge) + { + SdrObject* pObj1 = pEdge->GetConnectedNode(sal_False); + SdrObject* pObj2 = pEdge->GetConnectedNode(sal_True); + + if(pObj1 + && LIST_ENTRY_NOTFOUND == rAllMarkedObjects.GetPos(pObj1) + && !pEdge->CheckNodeConnection(sal_False)) + { + if( IsUndoEnabled() ) + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pEdge)); + pEdge->DisconnectFromNode(sal_False); + } + + if(pObj2 + && LIST_ENTRY_NOTFOUND == rAllMarkedObjects.GetPos(pObj2) + && !pEdge->CheckNodeConnection(sal_True)) + { + if( IsUndoEnabled() ) + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pEdge)); + pEdge->DisconnectFromNode(sal_True); + } + } + } + + ULONG nMarkedEdgeAnz = GetMarkedEdgesOfMarkedNodes().GetMarkCount(); + USHORT i; + + for (i=0; i<nMarkedEdgeAnz; i++) { + SdrMark* pEM = GetMarkedEdgesOfMarkedNodes().GetMark(i); + SdrObject* pEdgeTmp=pEM->GetMarkedSdrObj(); + SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pEdgeTmp); + if (pEdge!=NULL) { + pEdge->SetEdgeTrackDirty(); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// #### ### #### #### # #### # # # ##### # ##### #### +// # # # # # # # # # # # # # # # # +// #### # # ### ### # #### # # # # # #### ### +// # # # # # # # # # # # # # # # +// # ### #### #### # #### # #### # # # ##### #### +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEditView::MarkListHasChanged() +{ + SdrMarkView::MarkListHasChanged(); + bPossibilitiesDirty=TRUE; +} + +void SdrEditView::ModelHasChanged() +{ + SdrMarkView::ModelHasChanged(); + bPossibilitiesDirty=TRUE; +} + +BOOL SdrEditView::IsResizeAllowed(BOOL bProp) const +{ + ForcePossibilities(); + if (bResizeProtect) return FALSE; + if (bProp) return bResizePropAllowed; + return bResizeFreeAllowed; +} + +BOOL SdrEditView::IsRotateAllowed(BOOL b90Deg) const +{ + ForcePossibilities(); + if (bMoveProtect) return FALSE; + if (b90Deg) return bRotate90Allowed; + return bRotateFreeAllowed; +} + +BOOL SdrEditView::IsMirrorAllowed(BOOL b45Deg, BOOL b90Deg) const +{ + ForcePossibilities(); + if (bMoveProtect) return FALSE; + if (b90Deg) return bMirror90Allowed; + if (b45Deg) return bMirror45Allowed; + return bMirrorFreeAllowed && !bMoveProtect; +} + +BOOL SdrEditView::IsTransparenceAllowed() const +{ + ForcePossibilities(); + return bTransparenceAllowed; +} + +BOOL SdrEditView::IsGradientAllowed() const +{ + ForcePossibilities(); + return bGradientAllowed; +} + +BOOL SdrEditView::IsShearAllowed() const +{ + ForcePossibilities(); + if (bResizeProtect) return FALSE; + return bShearAllowed; +} + +BOOL SdrEditView::IsEdgeRadiusAllowed() const +{ + ForcePossibilities(); + return bEdgeRadiusAllowed; +} + +BOOL SdrEditView::IsCrookAllowed(BOOL bNoContortion) const +{ + // CrookMode fehlt hier (weil kein Rotate bei Shear ...) + ForcePossibilities(); + if (bNoContortion) { + if (!bRotateFreeAllowed) return FALSE; // Crook is nich + return !bMoveProtect && bMoveAllowed; + } else { + return !bResizeProtect && bContortionPossible; + } +} + +BOOL SdrEditView::IsDistortAllowed(BOOL bNoContortion) const +{ + ForcePossibilities(); + if (bNoContortion) { + return FALSE; + } else { + return !bResizeProtect && bContortionPossible; + } +} + +BOOL SdrEditView::IsCombinePossible(BOOL bNoPolyPoly) const +{ + ForcePossibilities(); + if (bNoPolyPoly) return bCombineNoPolyPolyPossible; + else return bCombinePossible; +} + +BOOL SdrEditView::IsDismantlePossible(BOOL bMakeLines) const +{ + ForcePossibilities(); + if (bMakeLines) return bDismantleMakeLinesPossible; + else return bDismantlePossible; +} + +void SdrEditView::CheckPossibilities() +{ + if (bSomeObjChgdFlag) bPossibilitiesDirty=TRUE; + + if(bSomeObjChgdFlag) + { + // This call IS necessary to correct the MarkList, in which + // no longer to the model belonging objects still can reside. + // These ones nned to be removed. + CheckMarked(); + } + + if (bPossibilitiesDirty) { + ImpResetPossibilityFlags(); + SortMarkedObjects(); + ULONG nMarkAnz=GetMarkedObjectCount(); + if (nMarkAnz!=0) { + bReverseOrderPossible=nMarkAnz>=2; + + ULONG nMovableCount=0; + bGroupPossible=nMarkAnz>=2; + bCombinePossible=nMarkAnz>=2; + if (nMarkAnz==1) { + // bCombinePossible gruendlicher checken + // fehlt noch ... + const SdrObject* pObj=GetMarkedObjectByIndex(0); + //const SdrPathObj* pPath=PTR_CAST(SdrPathObj,pObj); + BOOL bGroup=pObj->GetSubList()!=NULL; + BOOL bHasText=pObj->GetOutlinerParaObject()!=NULL; + if (bGroup || bHasText) { + bCombinePossible=TRUE; + } + } + bCombineNoPolyPolyPossible=bCombinePossible; + bDeletePossible=TRUE; + // Zu den Transformationen erstmal ja sagen + bMoveAllowed =TRUE; + bResizeFreeAllowed=TRUE; + bResizePropAllowed=TRUE; + bRotateFreeAllowed=TRUE; + bRotate90Allowed =TRUE; + bMirrorFreeAllowed=TRUE; + bMirror45Allowed =TRUE; + bMirror90Allowed =TRUE; + bShearAllowed =TRUE; + bEdgeRadiusAllowed=FALSE; + bContortionPossible=TRUE; + bCanConvToContour = TRUE; + + // these ones are only allowed when single object is selected + bTransparenceAllowed = (nMarkAnz == 1); + bGradientAllowed = (nMarkAnz == 1); + if(bGradientAllowed) + { + // gradient depends on fillstyle + const SdrMark* pM = GetSdrMarkByIndex(0); + const SdrObject* pObj = pM->GetMarkedSdrObj(); + + // maybe group object, so get merged ItemSet + const SfxItemSet& rSet = pObj->GetMergedItemSet(); + SfxItemState eState = rSet.GetItemState(XATTR_FILLSTYLE, FALSE); + + if(SFX_ITEM_DONTCARE != eState) + { + // If state is not DONTCARE, test the item + XFillStyle eFillStyle = ((XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue(); + + if(eFillStyle != XFILL_GRADIENT) + { + bGradientAllowed = FALSE; + } + } + } + + BOOL bNoMovRotFound=FALSE; + const SdrPageView* pPV0=NULL; + + for (ULONG nm=0; nm<nMarkAnz; nm++) { + const SdrMark* pM=GetSdrMarkByIndex(nm); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrPageView* pPV=pM->GetPageView(); + if (pPV!=pPV0) { + if (pPV->IsReadOnly()) bReadOnly=TRUE; + pPV0=pPV; + } + + SdrObjTransformInfoRec aInfo; + pObj->TakeObjInfo(aInfo); + BOOL bMovPrt=pObj->IsMoveProtect(); + BOOL bSizPrt=pObj->IsResizeProtect(); + if (!bMovPrt && aInfo.bMoveAllowed) nMovableCount++; // Menge der MovableObjs zaehlen + if (bMovPrt) bMoveProtect=TRUE; + if (bSizPrt) bResizeProtect=TRUE; + + // not allowed when not allowed at one object + if(!aInfo.bTransparenceAllowed) + bTransparenceAllowed = FALSE; + + // Wenn einer was nicht kann, duerfen's alle nicht + if (!aInfo.bMoveAllowed ) bMoveAllowed =FALSE; + if (!aInfo.bResizeFreeAllowed) bResizeFreeAllowed=FALSE; + if (!aInfo.bResizePropAllowed) bResizePropAllowed=FALSE; + if (!aInfo.bRotateFreeAllowed) bRotateFreeAllowed=FALSE; + if (!aInfo.bRotate90Allowed ) bRotate90Allowed =FALSE; + if (!aInfo.bMirrorFreeAllowed) bMirrorFreeAllowed=FALSE; + if (!aInfo.bMirror45Allowed ) bMirror45Allowed =FALSE; + if (!aInfo.bMirror90Allowed ) bMirror90Allowed =FALSE; + if (!aInfo.bShearAllowed ) bShearAllowed =FALSE; + if (aInfo.bEdgeRadiusAllowed) bEdgeRadiusAllowed=TRUE; + if (aInfo.bNoContortion ) bContortionPossible=FALSE; + // Fuer Crook mit Contortion: Alle Objekte muessen + // Movable und Rotatable sein, ausser maximal 1 + if (!bMoreThanOneNoMovRot) { + if (!aInfo.bMoveAllowed || !aInfo.bResizeFreeAllowed) { + bMoreThanOneNoMovRot=bNoMovRotFound; + bNoMovRotFound=TRUE; + } + } + + // when one member cannot be converted, no conversion is possible + if(!aInfo.bCanConvToContour) + bCanConvToContour = FALSE; + + // Ungroup + if (!bUnGroupPossible) bUnGroupPossible=pObj->GetSubList()!=NULL; + // ConvertToCurve: Wenn mind. einer konvertiert werden kann ist das ok. + if (aInfo.bCanConvToPath ) bCanConvToPath =TRUE; + if (aInfo.bCanConvToPoly ) bCanConvToPoly =TRUE; + if (aInfo.bCanConvToPathLineToArea) bCanConvToPathLineToArea=TRUE; + if (aInfo.bCanConvToPolyLineToArea) bCanConvToPolyLineToArea=TRUE; + + // Combine/Dismantle + if(bCombinePossible) + { + bCombinePossible = ImpCanConvertForCombine(pObj); + bCombineNoPolyPolyPossible = bCombinePossible; + } + + if (!bDismantlePossible) bDismantlePossible = ImpCanDismantle(pObj, sal_False); + if (!bDismantleMakeLinesPossible) bDismantleMakeLinesPossible = ImpCanDismantle(pObj, sal_True); + // OrthoDesiredOnMarked checken + if (!bOrthoDesiredOnMarked && !aInfo.bNoOrthoDesired) bOrthoDesiredOnMarked=TRUE; + // ImportMtf checken + + if (!bImportMtfPossible) { + BOOL bGraf=HAS_BASE(SdrGrafObj,pObj); + BOOL bOle2=HAS_BASE(SdrOle2Obj,pObj); + + if( bGraf && ((SdrGrafObj*)pObj)->HasGDIMetaFile() && !((SdrGrafObj*)pObj)->IsEPS() ) + bImportMtfPossible = TRUE; + + if (bOle2) + bImportMtfPossible=((SdrOle2Obj*)pObj)->GetObjRef().is(); + } + } + + bMoreThanOneNotMovable=nMovableCount<nMarkAnz-1; + bOneOrMoreMovable=nMovableCount!=0; + bGrpEnterPossible=bUnGroupPossible; + } + ImpCheckToTopBtmPossible(); + ((SdrPolyEditView*)this)->ImpCheckPolyPossibilities(); + bPossibilitiesDirty=FALSE; + + if (bReadOnly) { + BOOL bMerker1=bGrpEnterPossible; + ImpResetPossibilityFlags(); + bReadOnly=TRUE; + bGrpEnterPossible=bMerker1; + } + if (bMoveAllowed) { + // Verschieben von angeklebten Verbindern unterbinden + // Derzeit nur fuer Einfachselektion implementiert. + if (nMarkAnz==1) { + SdrObject* pObj=GetMarkedObjectByIndex(0); + SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pObj); + if (pEdge!=NULL) { + SdrObject* pNode1=pEdge->GetConnectedNode(TRUE); + SdrObject* pNode2=pEdge->GetConnectedNode(FALSE); + if (pNode1!=NULL || pNode2!=NULL) bMoveAllowed=FALSE; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEditView::ForceMarkedObjToAnotherPage() +{ + BOOL bFlg=FALSE; + for (ULONG nm=0; nm<GetMarkedObjectCount(); nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + Rectangle aObjRect(pObj->GetCurrentBoundRect()); + Rectangle aPgRect(pM->GetPageView()->GetPageRect()); + if (!aObjRect.IsOver(aPgRect)) { + BOOL bFnd=FALSE; + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + bFnd = aObjRect.IsOver(pPV->GetPageRect()); + } + + if(bFnd) + { + pM->GetPageView()->GetObjList()->RemoveObject(pObj->GetOrdNum()); + SdrInsertReason aReason(SDRREASON_VIEWCALL); + pPV->GetObjList()->InsertObject(pObj,CONTAINER_APPEND,&aReason); + pM->SetPageView(pPV); + InvalidateAllWin(aObjRect); + bFlg=TRUE; + } + } + } + if (bFlg) { + MarkListHasChanged(); + } +} + +void SdrEditView::DeleteMarkedList(const SdrMarkList& rMark) +{ + if (rMark.GetMarkCount()!=0) + { + rMark.ForceSort(); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(); + const sal_uInt32 nMarkAnz(rMark.GetMarkCount()); + + if(nMarkAnz) + { + sal_uInt32 nm(0); + std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters; + + if( bUndo ) + { + for(nm = nMarkAnz; nm > 0;) + { + nm--; + SdrMark* pM = rMark.GetMark(nm); + SdrObject* pObj = pM->GetMarkedSdrObj(); + + // extra undo actions for changed connector which now may hold it's layouted path (SJ) + std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) ); + AddUndoActions( vConnectorUndoActions ); + + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj)); + } + } + + // Sicherstellen, dass die OrderNums stimmen: + rMark.GetMark(0)->GetMarkedSdrObj()->GetOrdNum(); + + std::vector< SdrObject* > aRemoved3DObjects; + + for(nm = nMarkAnz; nm > 0;) + { + nm--; + SdrMark* pM = rMark.GetMark(nm); + SdrObject* pObj = pM->GetMarkedSdrObj(); + SdrObjList* pOL = pObj->GetObjList(); //#52680# + const sal_uInt32 nOrdNum(pObj->GetOrdNumDirect()); + + bool bIs3D = dynamic_cast< E3dObject* >(pObj); + // set up a scene updater if object is a 3d object + if(bIs3D) + { + aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj)); + } + + pOL->RemoveObject(nOrdNum); + + if( !bUndo ) + { + if( bIs3D ) + aRemoved3DObjects.push_back( pObj ); // may be needed later + else + SdrObject::Free(pObj); + } + } + + // fire scene updaters + while(aUpdaters.size()) + { + delete aUpdaters.back(); + aUpdaters.pop_back(); + } + + if( !bUndo ) + { + // now delete removed scene objects + while(aRemoved3DObjects.size()) + { + SdrObject::Free( aRemoved3DObjects.back() ); + aRemoved3DObjects.pop_back(); + } + } + } + + if( bUndo ) + EndUndo(); + } +} + +void SdrEditView::DeleteMarkedObj() +{ + // #i110981# return when nothing is to be done at all + if(!GetMarkedObjectCount()) + { + return; + } + + // moved breaking action and undo start outside loop + BrkAction(); + BegUndo(ImpGetResStr(STR_EditDelete),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_DELETE); + + // remove as long as something is selected. This allows to schedule objects for + // removal for a next run as needed + while(GetMarkedObjectCount()) + { + // vector to remember the parents which may be empty after object removal + std::vector< SdrObject* > aParents; + + { + const SdrMarkList& rMarkList = GetMarkedObjectList(); + const sal_uInt32 nCount(rMarkList.GetMarkCount()); + sal_uInt32 a(0); + + for(a = 0; a < nCount; a++) + { + // in the first run, add all found parents, but only once + SdrMark* pMark = rMarkList.GetMark(a); + SdrObject* pObject = pMark->GetMarkedSdrObj(); + SdrObject* pParent = pObject->GetObjList()->GetOwnerObj(); + + if(pParent) + { + if(aParents.size()) + { + std::vector< SdrObject* >::iterator aFindResult = + std::find(aParents.begin(), aParents.end(), pParent); + + if(aFindResult == aParents.end()) + { + aParents.push_back(pParent); + } + } + else + { + aParents.push_back(pParent); + } + } + } + + if(aParents.size()) + { + // in a 2nd run, remove all objects which may already be scheduled for + // removal. I am not sure if this can happen, but theoretically + // a to-be-removed object may already be the group/3DScene itself + for(a = 0; a < nCount; a++) + { + SdrMark* pMark = rMarkList.GetMark(a); + SdrObject* pObject = pMark->GetMarkedSdrObj(); + + std::vector< SdrObject* >::iterator aFindResult = + std::find(aParents.begin(), aParents.end(), pObject); + + if(aFindResult != aParents.end()) + { + aParents.erase(aFindResult); + } + } + } + } + + // original stuff: remove selected objects. Handle clear will + // do something only once + DeleteMarkedList(GetMarkedObjectList()); + GetMarkedObjectListWriteAccess().Clear(); + aHdl.Clear(); + + while(aParents.size() && !GetMarkedObjectCount()) + { + // iterate over remembered parents + SdrObject* pParent = aParents.back(); + aParents.pop_back(); + + if(pParent->GetSubList() && 0 == pParent->GetSubList()->GetObjCount()) + { + // we detected an empty parent, a candidate to leave group/3DScene + // if entered + if(GetSdrPageView()->GetAktGroup() + && GetSdrPageView()->GetAktGroup() == pParent) + { + GetSdrPageView()->LeaveOneGroup(); + } + + // schedule empty parent for removal + GetMarkedObjectListWriteAccess().InsertEntry( + SdrMark(pParent, GetSdrPageView())); + } + } + } + + // end undo and change messaging moved at the end + EndUndo(); + MarkListHasChanged(); +} + +void SdrEditView::CopyMarkedObj() +{ + SortMarkedObjects(); + + SdrMarkList aSourceObjectsForCopy(GetMarkedObjectList()); + // Folgende Schleife Anstatt MarkList::Merge(), damit + // ich jeweils mein Flag an die MarkEntries setzen kann. + ULONG nEdgeAnz = GetEdgesOfMarkedNodes().GetMarkCount(); + for (ULONG nEdgeNum=0; nEdgeNum<nEdgeAnz; nEdgeNum++) { + SdrMark aM(*GetEdgesOfMarkedNodes().GetMark(nEdgeNum)); + aM.SetUser(1); + aSourceObjectsForCopy.InsertEntry(aM); + } + aSourceObjectsForCopy.ForceSort(); + + // #i13033# + // New mechanism to re-create the connections of cloned connectors + CloneList aCloneList; + + const bool bUndo = IsUndoEnabled(); + + GetMarkedObjectListWriteAccess().Clear(); + ULONG nCloneErrCnt=0; + ULONG nMarkAnz=aSourceObjectsForCopy.GetMarkCount(); + ULONG nm; + for (nm=0; nm<nMarkAnz; nm++) { + SdrMark* pM=aSourceObjectsForCopy.GetMark(nm); + SdrObject* pO=pM->GetMarkedSdrObj()->Clone(); + if (pO!=NULL) { + SdrInsertReason aReason(SDRREASON_VIEWCALL); + pM->GetPageView()->GetObjList()->InsertObject(pO,CONTAINER_APPEND,&aReason); + + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoCopyObject(*pO)); + + SdrMark aME(*pM); + aME.SetMarkedSdrObj(pO); + aCloneList.AddPair(pM->GetMarkedSdrObj(), pO); + + if (pM->GetUser()==0) + { + // Sonst war's nur eine mitzukierende Edge + GetMarkedObjectListWriteAccess().InsertEntry(aME); + } + } else { + nCloneErrCnt++; + } + } + + // #i13033# + // New mechanism to re-create the connections of cloned connectors + aCloneList.CopyConnections(); + + if(0L != nCloneErrCnt) + { +#ifdef DBG_UTIL + ByteString aStr("SdrEditView::CopyMarkedObj(): Fehler beim Clonen "); + + if(nCloneErrCnt == 1) + { + aStr += "eines Zeichenobjekts."; + } + else + { + aStr += "von "; + aStr += ByteString::CreateFromInt32( nCloneErrCnt ); + aStr += " Zeichenobjekten."; + } + + aStr += " Objektverbindungen werden nicht mitkopiert."; + DBG_ERROR(aStr.GetBuffer()); +#endif + } + MarkListHasChanged(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrEditView::InsertObjectAtView(SdrObject* pObj, SdrPageView& rPV, ULONG nOptions) +{ + if ((nOptions & SDRINSERT_SETDEFLAYER)!=0) { + SdrLayerID nLayer=rPV.GetPage()->GetLayerAdmin().GetLayerID(aAktLayer,TRUE); + if (nLayer==SDRLAYER_NOTFOUND) nLayer=0; + if (rPV.GetLockedLayers().IsSet(nLayer) || !rPV.GetVisibleLayers().IsSet(nLayer)) { + SdrObject::Free( pObj ); // Layer gesperrt oder nicht sichtbar + return FALSE; + } + pObj->NbcSetLayer(nLayer); + } + if ((nOptions & SDRINSERT_SETDEFATTR)!=0) { + if (pDefaultStyleSheet!=NULL) pObj->NbcSetStyleSheet(pDefaultStyleSheet, sal_False); + pObj->SetMergedItemSet(aDefaultAttr); + } + if (!pObj->IsInserted()) { + SdrInsertReason aReason(SDRREASON_VIEWCALL); + if ((nOptions & SDRINSERT_NOBROADCAST)!=0) { + rPV.GetObjList()->NbcInsertObject(pObj,CONTAINER_APPEND,&aReason); + } else { + rPV.GetObjList()->InsertObject(pObj,CONTAINER_APPEND,&aReason); + } + } + if( IsUndoEnabled() ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pObj)); + + if ((nOptions & SDRINSERT_DONTMARK)==0) { + if ((nOptions & SDRINSERT_ADDMARK)==0) UnmarkAllObj(); + MarkObj(pObj,&rPV); + } + return TRUE; +} + +void SdrEditView::ReplaceObjectAtView(SdrObject* pOldObj, SdrPageView& rPV, SdrObject* pNewObj, BOOL bMark) +{ + SdrObjList* pOL=pOldObj->GetObjList(); + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pOldObj,*pNewObj)); + + if( IsObjMarked( pOldObj ) ) + MarkObj( pOldObj, &rPV, TRUE /*unmark!*/ ); + + pOL->ReplaceObject(pNewObj,pOldObj->GetOrdNum()); + + if( !bUndo ) + SdrObject::Free( pOldObj ); + + if (bMark) MarkObj(pNewObj,&rPV); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef WIN +void SdrEditView::BegUndo() // Undo-Klammerung auf +{ + pMod->BegUndo(); +} + +void SdrEditView::BegUndo(const String& rComment) // Undo-Klammerung auf +{ + pMod->BegUndo(rComment); +} + +void SdrEditView::BegUndo(const String& rComment, const String& rObjDescr, + SdrRepeatFunc eFunc) // Undo-Klammerung auf +{ + pMod->BegUndo(rComment,rObjDescr,eFunc); +} + +void SdrEditView::BegUndo(SdrUndoGroup* pUndoGrp) // Undo-Klammerung auf +{ + pMod->BegUndo(pUndoGrp); +} + +void SdrEditView::AddUndo(SdrUndoAction* pUndo) // Action hinzufuegen +{ + pMod->AddUndo(pUndo); +} + // nur nach dem 1. BegUndo oder vor dem letzten EndUndo: +void SdrEditView::SetUndoComment(const String& rComment) +{ + pMod->SetUndoComment(rComment); +} + + +void SdrEditView::SetUndoComment(const String& rComment, + const String& rObjDescr) +{ + pMod->SetUndoComment(rComment,rObjDescr); +} +#endif + +bool SdrEditView::IsUndoEnabled() const +{ + return pMod->IsUndoEnabled(); +} + diff --git a/svx/source/svdraw/svdedtv1.cxx b/svx/source/svdraw/svdedtv1.cxx new file mode 100644 index 000000000000..1ac6d0b89945 --- /dev/null +++ b/svx/source/svdraw/svdedtv1.cxx @@ -0,0 +1,1784 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdedtv.hxx> +#include <math.h> + +#ifndef _MATH_H +#define _MATH_H +#endif +#include <tools/bigint.hxx> +#include <svl/itemiter.hxx> +#include <vcl/msgbox.hxx> +#include <svx/rectenum.hxx> +#include <svx/svxids.hrc> // fuer SID_ATTR_TRANSFORM_... +#include <svx/svdattr.hxx> // fuer Get/SetGeoAttr +#include "svditext.hxx" +#include "svditer.hxx" +#include <svx/svdtrans.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdlayer.hxx> // fuer MergeNotPersistAttr +#include <svx/svdattrx.hxx> // fuer MergeNotPersistAttr +#include <svx/svdetc.hxx> // fuer SearchOutlinerItems +#include <svx/svdopath.hxx> // fuer Crook +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include <editeng/eeitem.hxx> +#include <svl/aeitem.hxx> +#include <svl/whiter.hxx> +#include <svx/sdr/contact/objectcontact.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/e3dsceneupdater.hxx> +#include <svx/obj3d.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@ @@@@@ @@ @@@@@@ @@ @@ @@ @@@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ +// @@@@ @@ @@ @@ @@ @@@@@ @@ @@@@ @@@@@@@ +// @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@ +// @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ +// @@@@@ @@@@@ @@ @@ @ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEditView::SetMarkedObjRect(const Rectangle& rRect, BOOL bCopy) +{ + DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() mit leerem Rect mach keinen Sinn"); + if (rRect.IsEmpty()) return; + ULONG nAnz=GetMarkedObjectCount(); + if (nAnz==0) return; + Rectangle aR0(GetMarkedObjRect()); + DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() ist leer"); + if (aR0.IsEmpty()) return; + long x0=aR0.Left(); + long y0=aR0.Top(); + long w0=aR0.Right()-x0; + long h0=aR0.Bottom()-y0; + long x1=rRect.Left(); + long y1=rRect.Top(); + long w1=rRect.Right()-x1; + long h1=rRect.Bottom()-y1; + XubString aStr; + ImpTakeDescriptionStr(STR_EditPosSize,aStr); + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(aStr); + + if (bCopy) + CopyMarkedObj(); + + for (ULONG nm=0; nm<nAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + if( bUndo ) + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + + Rectangle aR1(pO->GetSnapRect()); + if (!aR1.IsEmpty()) + { + if (aR1==aR0) + { + aR1=rRect; + } + else + { // aR1 von aR0 nach rRect transformieren + aR1.Move(-x0,-y0); + BigInt l(aR1.Left()); + BigInt r(aR1.Right()); + BigInt t(aR1.Top()); + BigInt b(aR1.Bottom()); + if (w0!=0) { + l*=w1; l/=w0; + r*=w1; r/=w0; + } else { + l=0; r=w1; + } + if (h0!=0) { + t*=h1; t/=h0; + b*=h1; b/=h0; + } else { + t=0; b=h1; + } + aR1.Left ()=long(l); + aR1.Right ()=long(r); + aR1.Top ()=long(t); + aR1.Bottom()=long(b); + aR1.Move(x1,y1); + } + pO->SetSnapRect(aR1); + } else { + DBG_ERROR("SetMarkedObjRect(): pObj->GetSnapRect() liefert leeres Rect"); + } + } + if( bUndo ) + EndUndo(); +} + +std::vector< SdrUndoAction* > SdrEditView::CreateConnectorUndo( SdrObject& rO ) +{ + std::vector< SdrUndoAction* > vUndoActions; + + if ( rO.GetBroadcaster() ) + { + const SdrPage* pPage = rO.GetPage(); + if ( pPage ) + { + SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); + while( aIter.IsMore() ) + { + SdrObject* pPartObj = aIter.Next(); + if ( pPartObj->ISA( SdrEdgeObj ) ) + { + if ( ( pPartObj->GetConnectedNode( sal_False ) == &rO ) || + ( pPartObj->GetConnectedNode( sal_True ) == &rO ) ) + { + vUndoActions.push_back( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pPartObj ) ); + } + } + } + } + } + return vUndoActions; +} + +void SdrEditView::AddUndoActions( std::vector< SdrUndoAction* >& rUndoActions ) +{ + std::vector< SdrUndoAction* >::iterator aUndoActionIter( rUndoActions.begin() ); + while( aUndoActionIter != rUndoActions.end() ) + AddUndo( *aUndoActionIter++ ); +} + +void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy) +{ + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + { + XubString aStr(ImpGetResStr(STR_EditMove)); + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + // benoetigt eigene UndoGroup wegen Parameter + BegUndo(aStr,GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVE); + } + + if (bCopy) + CopyMarkedObj(); + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + if( bUndo ) + { + std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) ); + AddUndoActions( vConnectorUndoActions ); + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz)); + } + pO->Move(rSiz); + } + + if( bUndo ) + EndUndo(); +} + +void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy) +{ + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + { + XubString aStr; + ImpTakeDescriptionStr(STR_EditResize,aStr); + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr); + } + + if (bCopy) + CopyMarkedObj(); + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + if( bUndo ) + { + std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) ); + AddUndoActions( vConnectorUndoActions ); + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + } + pO->Resize(rRef,xFact,yFact); + } + + if( bUndo ) + EndUndo(); +} + +long SdrEditView::GetMarkedObjRotate() const +{ + BOOL b1st=TRUE; + BOOL bOk=TRUE; + long nWink=0; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz && bOk; nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + long nWink2=pO->GetRotateAngle(); + if (b1st) nWink=nWink2; + else if (nWink2!=nWink) bOk=FALSE; + b1st=FALSE; + } + if (!bOk) nWink=0; + return nWink; +} + +void SdrEditView::RotateMarkedObj(const Point& rRef, long nWink, bool bCopy) +{ + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + { + XubString aStr; + ImpTakeDescriptionStr(STR_EditRotate,aStr); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr); + } + + if (bCopy) + CopyMarkedObj(); + + double nSin=sin(nWink*nPi180); + double nCos=cos(nWink*nPi180); + const sal_uInt32 nMarkAnz(GetMarkedObjectCount()); + + if(nMarkAnz) + { + std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters; + + for(sal_uInt32 nm(0); nm < nMarkAnz; nm++) + { + SdrMark* pM = GetSdrMarkByIndex(nm); + SdrObject* pO = pM->GetMarkedSdrObj(); + + if( bUndo ) + { + // extra undo actions for changed connector which now may hold it's layouted path (SJ) + std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) ); + AddUndoActions( vConnectorUndoActions ); + + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + } + + // set up a scene updater if object is a 3d object + if(dynamic_cast< E3dObject* >(pO)) + { + aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO)); + } + + pO->Rotate(rRef,nWink,nSin,nCos); + } + + // fire scene updaters + while(aUpdaters.size()) + { + delete aUpdaters.back(); + aUpdaters.pop_back(); + } + } + + if( bUndo ) + EndUndo(); +} + +void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy) +{ + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + { + XubString aStr; + Point aDif(rRef2-rRef1); + if (aDif.X()==0) ImpTakeDescriptionStr(STR_EditMirrorHori,aStr); + else if (aDif.Y()==0) ImpTakeDescriptionStr(STR_EditMirrorVert,aStr); + else if (Abs(aDif.X())==Abs(aDif.Y())) ImpTakeDescriptionStr(STR_EditMirrorDiag,aStr); + else ImpTakeDescriptionStr(STR_EditMirrorFree,aStr); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr); + } + + if (bCopy) + CopyMarkedObj(); + + const sal_uInt32 nMarkAnz(GetMarkedObjectCount()); + + if(nMarkAnz) + { + std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters; + + for(sal_uInt32 nm(0); nm < nMarkAnz; nm++) + { + SdrMark* pM = GetSdrMarkByIndex(nm); + SdrObject* pO = pM->GetMarkedSdrObj(); + + if( bUndo ) + { + // extra undo actions for changed connector which now may hold it's layouted path (SJ) + std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) ); + AddUndoActions( vConnectorUndoActions ); + + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + } + + // set up a scene updater if object is a 3d object + if(dynamic_cast< E3dObject* >(pO)) + { + aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO)); + } + + pO->Mirror(rRef1,rRef2); + } + + // fire scene updaters + while(aUpdaters.size()) + { + delete aUpdaters.back(); + aUpdaters.pop_back(); + } + } + + if( bUndo ) + EndUndo(); +} + +void SdrEditView::MirrorMarkedObjHorizontal(BOOL bCopy) +{ + Point aCenter(GetMarkedObjRect().Center()); + Point aPt2(aCenter); + aPt2.Y()++; + MirrorMarkedObj(aCenter,aPt2,bCopy); +} + +void SdrEditView::MirrorMarkedObjVertical(BOOL bCopy) +{ + Point aCenter(GetMarkedObjRect().Center()); + Point aPt2(aCenter); + aPt2.X()++; + MirrorMarkedObj(aCenter,aPt2,bCopy); +} + +long SdrEditView::GetMarkedObjShear() const +{ + BOOL b1st=TRUE; + BOOL bOk=TRUE; + long nWink=0; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz && bOk; nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + long nWink2=pO->GetShearAngle(); + if (b1st) nWink=nWink2; + else if (nWink2!=nWink) bOk=FALSE; + b1st=FALSE; + } + if (nWink>SDRMAXSHEAR) nWink=SDRMAXSHEAR; + if (nWink<-SDRMAXSHEAR) nWink=-SDRMAXSHEAR; + if (!bOk) nWink=0; + return nWink; +} + +void SdrEditView::ShearMarkedObj(const Point& rRef, long nWink, bool bVShear, bool bCopy) +{ + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + { + XubString aStr; + ImpTakeDescriptionStr(STR_EditShear,aStr); + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr); + } + + if (bCopy) + CopyMarkedObj(); + + double nTan=tan(nWink*nPi180); + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + if( bUndo ) + { + std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) ); + AddUndoActions( vConnectorUndoActions ); + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + } + pO->Shear(rRef,nWink,nTan,bVShear); + } + + if( bUndo ) + EndUndo(); +} + +void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad, + SdrCrookMode eMode, BOOL bVertical, BOOL bNoContortion, BOOL bRotate, const Rectangle& rMarkRect) +{ + SdrPathObj* pPath=PTR_CAST(SdrPathObj,pO); + BOOL bDone = FALSE; + + if(pPath!=NULL && !bNoContortion) + { + XPolyPolygon aXPP(pPath->GetPathPoly()); + switch (eMode) { + case SDRCROOK_ROTATE : CrookRotatePoly (aXPP,rRef,rRad,bVertical); break; + case SDRCROOK_SLANT : CrookSlantPoly (aXPP,rRef,rRad,bVertical); break; + case SDRCROOK_STRETCH: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break; + } // switch + pPath->SetPathPoly(aXPP.getB2DPolyPolygon()); + bDone = TRUE; + } + + if(!bDone && !pPath && pO->IsPolyObj() && 0L != pO->GetPointCount()) + { + // FuerPolyObj's, aber NICHT fuer SdrPathObj's, z.B. fuer's Bemassungsobjekt + sal_uInt32 nPtAnz(pO->GetPointCount()); + XPolygon aXP((sal_uInt16)nPtAnz); + sal_uInt32 nPtNum; + + for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++) + { + Point aPt(pO->GetPoint(nPtNum)); + aXP[(sal_uInt16)nPtNum]=aPt; + } + + switch (eMode) + { + case SDRCROOK_ROTATE : CrookRotatePoly (aXP,rRef,rRad,bVertical); break; + case SDRCROOK_SLANT : CrookSlantPoly (aXP,rRef,rRad,bVertical); break; + case SDRCROOK_STRETCH: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break; + } + + for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++) + { + // hier koennte man vieleicht auch mal das Broadcasting optimieren + // ist aber z.Zt. bei den 2 Punkten des Bemassungsobjekts noch nicht so tragisch + pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum); + } + + bDone = TRUE; + } + + if(!bDone) + { + // Fuer alle anderen oder wenn bNoContortion + Point aCtr0(pO->GetSnapRect().Center()); + Point aCtr1(aCtr0); + sal_Bool bRotOk(sal_False); + double nSin(0.0), nCos(1.0); + double nWink(0.0); + + if(0 != rRad.X() && 0 != rRad.Y()) + { + bRotOk = bRotate; + + switch (eMode) + { + case SDRCROOK_ROTATE : nWink=CrookRotateXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break; + case SDRCROOK_SLANT : nWink=CrookSlantXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); break; + case SDRCROOK_STRETCH: nWink=CrookStretchXPoint(aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break; + } + } + + aCtr1 -= aCtr0; + + if(bRotOk) + pO->Rotate(aCtr0, Round(nWink/nPi180), nSin, nCos); + + pO->Move(Size(aCtr1.X(),aCtr1.Y())); + } +} + +void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode, + bool bVertical, bool bNoContortion, bool bCopy) +{ + Rectangle aMarkRect(GetMarkedObjRect()); + const bool bUndo = IsUndoEnabled(); + + bool bRotate=bNoContortion && eMode==SDRCROOK_ROTATE && IsRotateAllowed(FALSE); + + if( bUndo ) + { + XubString aStr; + ImpTakeDescriptionStr(bNoContortion?STR_EditCrook:STR_EditCrookContortion,aStr); + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr); + } + + if (bCopy) + CopyMarkedObj(); + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + if( bUndo ) + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + + const SdrObjList* pOL=pO->GetSubList(); + if (bNoContortion || pOL==NULL) { + ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect); + } else { + SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS); + while (aIter.IsMore()) { + SdrObject* pO1=aIter.Next(); + ImpCrookObj(pO1,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect); + } + } + } + + if( bUndo ) + EndUndo(); +} + +void SdrEditView::ImpDistortObj(SdrObject* pO, const Rectangle& rRef, const XPolygon& rDistortedRect, BOOL bNoContortion) +{ + SdrPathObj* pPath = PTR_CAST(SdrPathObj, pO); + + if(!bNoContortion && pPath) + { + XPolyPolygon aXPP(pPath->GetPathPoly()); + aXPP.Distort(rRef, rDistortedRect); + pPath->SetPathPoly(aXPP.getB2DPolyPolygon()); + } + else if(pO->IsPolyObj()) + { + // z.B. fuer's Bemassungsobjekt + sal_uInt32 nPtAnz(pO->GetPointCount()); + XPolygon aXP((sal_uInt16)nPtAnz); + sal_uInt32 nPtNum; + + for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++) + { + Point aPt(pO->GetPoint(nPtNum)); + aXP[(sal_uInt16)nPtNum]=aPt; + } + + aXP.Distort(rRef, rDistortedRect); + + for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++) + { + // hier koennte man vieleicht auch mal das Broadcasting optimieren + // ist aber z.Zt. bei den 2 Punkten des Bemassungsobjekts noch nicht so tragisch + pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum); + } + } +} + +void SdrEditView::DistortMarkedObj(const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy) +{ + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + { + XubString aStr; + ImpTakeDescriptionStr(STR_EditDistort,aStr); + if (bCopy) + aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr); + } + + if (bCopy) + CopyMarkedObj(); + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + if( bUndo ) + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + + Rectangle aRefRect(rRef); + XPolygon aRefPoly(rDistortedRect); + const SdrObjList* pOL=pO->GetSubList(); + if (bNoContortion || pOL==NULL) { + ImpDistortObj(pO,aRefRect,aRefPoly,bNoContortion); + } else { + SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS); + while (aIter.IsMore()) { + SdrObject* pO1=aIter.Next(); + ImpDistortObj(pO1,aRefRect,aRefPoly,bNoContortion); + } + } + } + if( bUndo ) + EndUndo(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr, BOOL /*bReplaceAll*/) +{ + // bReplaceAll hat hier keinerlei Wirkung + Rectangle aAllSnapRect(GetMarkedObjRect()); + const SfxPoolItem *pPoolItem=NULL; + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrTransformRef1XItem*)pPoolItem)->GetValue(); + SetRef1(Point(n,GetRef1().Y())); + } + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrTransformRef1YItem*)pPoolItem)->GetValue(); + SetRef1(Point(GetRef1().X(),n)); + } + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrTransformRef2XItem*)pPoolItem)->GetValue(); + SetRef2(Point(n,GetRef2().Y())); + } + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrTransformRef2YItem*)pPoolItem)->GetValue(); + SetRef2(Point(GetRef2().X(),n)); + } + long nAllPosX=0; BOOL bAllPosX=FALSE; + long nAllPosY=0; BOOL bAllPosY=FALSE; + long nAllWdt=0; BOOL bAllWdt=FALSE; + long nAllHgt=0; BOOL bAllHgt=FALSE; + BOOL bDoIt=FALSE; + if (rAttr.GetItemState(SDRATTR_ALLPOSITIONX,TRUE,&pPoolItem)==SFX_ITEM_SET) { + nAllPosX=((const SdrAllPositionXItem*)pPoolItem)->GetValue(); + bAllPosX=TRUE; bDoIt=TRUE; + } + if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,TRUE,&pPoolItem)==SFX_ITEM_SET) { + nAllPosY=((const SdrAllPositionYItem*)pPoolItem)->GetValue(); + bAllPosY=TRUE; bDoIt=TRUE; + } + if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,TRUE,&pPoolItem)==SFX_ITEM_SET) { + nAllWdt=((const SdrAllSizeWidthItem*)pPoolItem)->GetValue(); + bAllWdt=TRUE; bDoIt=TRUE; + } + if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,TRUE,&pPoolItem)==SFX_ITEM_SET) { + nAllHgt=((const SdrAllSizeHeightItem*)pPoolItem)->GetValue(); + bAllHgt=TRUE; bDoIt=TRUE; + } + if (bDoIt) { + Rectangle aRect(aAllSnapRect); // !!! fuer PolyPt's und GluePt's aber bitte noch aendern !!! + if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0); + if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top()); + if (bAllWdt) aRect.Right()=aAllSnapRect.Left()+nAllWdt; + if (bAllHgt) aRect.Bottom()=aAllSnapRect.Top()+nAllHgt; + SetMarkedObjRect(aRect); + } + if (rAttr.GetItemState(SDRATTR_RESIZEXALL,TRUE,&pPoolItem)==SFX_ITEM_SET) { + Fraction aXFact=((const SdrResizeXAllItem*)pPoolItem)->GetValue(); + ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1)); + } + if (rAttr.GetItemState(SDRATTR_RESIZEYALL,TRUE,&pPoolItem)==SFX_ITEM_SET) { + Fraction aYFact=((const SdrResizeYAllItem*)pPoolItem)->GetValue(); + ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact); + } + if (rAttr.GetItemState(SDRATTR_ROTATEALL,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long nAngle=((const SdrRotateAllItem*)pPoolItem)->GetValue(); + RotateMarkedObj(aAllSnapRect.Center(),nAngle); + } + if (rAttr.GetItemState(SDRATTR_HORZSHEARALL,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long nAngle=((const SdrHorzShearAllItem*)pPoolItem)->GetValue(); + ShearMarkedObj(aAllSnapRect.Center(),nAngle,FALSE); + } + if (rAttr.GetItemState(SDRATTR_VERTSHEARALL,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long nAngle=((const SdrVertShearAllItem*)pPoolItem)->GetValue(); + ShearMarkedObj(aAllSnapRect.Center(),nAngle,TRUE); + } + + const bool bUndo = IsUndoEnabled(); + + // Todo: WhichRange nach Notwendigkeit ueberpruefen. + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + const SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + //const SdrPageView* pPV=pM->GetPageView(); + if( bUndo ) + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + + pObj->ApplyNotPersistAttr(rAttr); + } +} + +void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr, BOOL /*bOnlyHardAttr*/) const +{ + // bOnlyHardAttr hat hier keinerlei Wirkung + // Hier muss ausserdem noch der Nullpunkt und + // die PvPos berueksichtigt werden. + Rectangle aAllSnapRect(GetMarkedObjRect()); // !!! fuer PolyPt's und GluePt's aber bitte noch aendern !!! + long nAllSnapPosX=aAllSnapRect.Left(); + long nAllSnapPosY=aAllSnapRect.Top(); + long nAllSnapWdt=aAllSnapRect.GetWidth()-1; + long nAllSnapHgt=aAllSnapRect.GetHeight()-1; + // koennte mal zu CheckPossibilities mit rein + BOOL bMovProtect=FALSE,bMovProtectDC=FALSE; + BOOL bSizProtect=FALSE,bSizProtectDC=FALSE; + BOOL bPrintable =TRUE ,bPrintableDC=FALSE; + BOOL bVisible = TRUE, bVisibleDC=FALSE; + SdrLayerID nLayerId=0; BOOL bLayerDC=FALSE; + XubString aObjName; BOOL bObjNameDC=FALSE,bObjNameSet=FALSE; + long nSnapPosX=0; BOOL bSnapPosXDC=FALSE; + long nSnapPosY=0; BOOL bSnapPosYDC=FALSE; + long nSnapWdt=0; BOOL bSnapWdtDC=FALSE; + long nSnapHgt=0; BOOL bSnapHgtDC=FALSE; + long nLogicWdt=0; BOOL bLogicWdtDC=FALSE,bLogicWdtDiff=FALSE; + long nLogicHgt=0; BOOL bLogicHgtDC=FALSE,bLogicHgtDiff=FALSE; + long nRotAngle=0; BOOL bRotAngleDC=FALSE; + long nShrAngle=0; BOOL bShrAngleDC=FALSE; + Rectangle aSnapRect; + Rectangle aLogicRect; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) { + const SdrMark* pM=GetSdrMarkByIndex(nm); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + if (nm==0) { + nLayerId=pObj->GetLayer(); + bMovProtect=pObj->IsMoveProtect(); + bSizProtect=pObj->IsResizeProtect(); + bPrintable =pObj->IsPrintable(); + bVisible = pObj->IsVisible(); + Rectangle aSnapRect2(pObj->GetSnapRect()); + Rectangle aLogicRect2(pObj->GetLogicRect()); + nSnapPosX=aSnapRect2.Left(); + nSnapPosY=aSnapRect2.Top(); + nSnapWdt=aSnapRect2.GetWidth()-1; + nSnapHgt=aSnapRect2.GetHeight()-1; + nLogicWdt=aLogicRect2.GetWidth()-1; + nLogicHgt=aLogicRect2.GetHeight()-1; + bLogicWdtDiff=nLogicWdt!=nSnapWdt; + bLogicHgtDiff=nLogicHgt!=nSnapHgt; + nRotAngle=pObj->GetRotateAngle(); + nShrAngle=pObj->GetShearAngle(); + } else { + if (!bLayerDC && nLayerId !=pObj->GetLayer()) bLayerDC=TRUE; + if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect()) bMovProtectDC=TRUE; + if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC=TRUE; + if (!bPrintableDC && bPrintable !=pObj->IsPrintable()) bPrintableDC=TRUE; + if (!bVisibleDC && bVisible !=pObj->IsVisible()) bVisibleDC=TRUE; + if (!bRotAngleDC && nRotAngle !=pObj->GetRotateAngle()) bRotAngleDC=TRUE; + if (!bShrAngleDC && nShrAngle !=pObj->GetShearAngle()) bShrAngleDC=TRUE; + if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) { + aSnapRect=pObj->GetSnapRect(); + if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=TRUE; + if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=TRUE; + if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=TRUE; + if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=TRUE; + } + if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) { + aLogicRect=pObj->GetLogicRect(); + if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=TRUE; + if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=TRUE; + if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=TRUE; + if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=TRUE; + } + } + if (!bObjNameDC ) { + if (!bObjNameSet) { + aObjName=pObj->GetName(); + } else { + if (aObjName!=pObj->GetName()) bObjNameDC=TRUE; + } + } + } + + if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX)); + if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY)); + if (bSnapWdtDC || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt)); + if (bSnapHgtDC || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt)); + + // Items fuer reine Transformationen + rAttr.Put(SdrMoveXItem()); + rAttr.Put(SdrMoveYItem()); + rAttr.Put(SdrResizeXOneItem()); + rAttr.Put(SdrResizeYOneItem()); + rAttr.Put(SdrRotateOneItem()); + rAttr.Put(SdrHorzShearOneItem()); + rAttr.Put(SdrVertShearOneItem()); + + if (nMarkAnz>1) { + rAttr.Put(SdrResizeXAllItem()); + rAttr.Put(SdrResizeYAllItem()); + rAttr.Put(SdrRotateAllItem()); + rAttr.Put(SdrHorzShearAllItem()); + rAttr.Put(SdrVertShearAllItem()); + } + + if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR) + { + rAttr.Put(SdrTransformRef1XItem(GetRef1().X())); + rAttr.Put(SdrTransformRef1YItem(GetRef1().Y())); + } + + if(eDragMode == SDRDRAG_MIRROR) + { + rAttr.Put(SdrTransformRef2XItem(GetRef2().X())); + rAttr.Put(SdrTransformRef2YItem(GetRef2().Y())); + } +} + +SfxItemSet SdrEditView::GetAttrFromMarked(BOOL bOnlyHardAttr) const +{ + SfxItemSet aSet(pMod->GetItemPool()); + MergeAttrFromMarked(aSet,bOnlyHardAttr); + //the EE_FEATURE items should not be set with SetAttrToMarked (see error message there) + //so we do not set them here + // #i32448# + // Do not disable, but clear the items. + aSet.ClearItem(EE_FEATURE_TAB); + aSet.ClearItem(EE_FEATURE_LINEBR); + aSet.ClearItem(EE_FEATURE_NOTCONV); + aSet.ClearItem(EE_FEATURE_FIELD); + return aSet; +} + +void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, BOOL bOnlyHardAttr) const +{ + sal_uInt32 nMarkAnz(GetMarkedObjectCount()); + + for(sal_uInt32 a(0); a < nMarkAnz; a++) + { + // #80277# merging was done wrong in the prev version + //const SfxItemSet& rSet = GetMarkedObjectByIndex()->GetItemSet(); + const SfxItemSet& rSet = GetMarkedObjectByIndex(a)->GetMergedItemSet(); + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich(aIter.FirstWhich()); + + while(nWhich) + { + if(!bOnlyHardAttr) + { + if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, FALSE)) + rAttr.InvalidateItem(nWhich); + else + rAttr.MergeValue(rSet.Get(nWhich), TRUE); + } + else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, FALSE)) + { + const SfxPoolItem& rItem = rSet.Get(nWhich); + rAttr.MergeValue(rItem, TRUE); + } + + nWhich = aIter.NextWhich(); + } + } +} + +void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, BOOL bReplaceAll) +{ + if (AreObjectsMarked()) + { +#ifdef DBG_UTIL + { + BOOL bHasEEFeatureItems=FALSE; + SfxItemIter aIter(rAttr); + const SfxPoolItem* pItem=aIter.FirstItem(); + while (!bHasEEFeatureItems && pItem!=NULL) { + if (!IsInvalidItem(pItem)) { + USHORT nW=pItem->Which(); + if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=TRUE; + } + pItem=aIter.NextItem(); + } + if(bHasEEFeatureItems) + { + String aMessage; + aMessage.AppendAscii("SdrEditView::SetAttrToMarked(): Das setzen von EE_FEATURE-Items an der SdrView macht keinen Sinn! Es fuehrt nur zu Overhead und nicht mehr lesbaren Dokumenten."); + InfoBox(NULL, aMessage).Execute(); + } + } +#endif + + // #103836# if the user thets character attributes to the complete shape, + // we want to remove all hard set character attributes with same + // which ids from the text. We do that later but here we remember + // all character attribute which id's that are set. + std::vector<sal_uInt16> aCharWhichIds; + { + SfxItemIter aIter(rAttr); + const SfxPoolItem* pItem=aIter.FirstItem(); + while( pItem!=NULL ) + { + if (!IsInvalidItem(pItem)) + { + sal_uInt16 nWhich = pItem->Which(); + if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END) + aCharWhichIds.push_back( nWhich ); + } + pItem=aIter.NextItem(); + } + } + + // Joe, 2.7.98: Damit Undo nach Format.Standard auch die Textattribute korrekt restauriert + BOOL bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll); + + // AW 030100: save additional geom info when para or char attributes + // are changed and the geom form of the text object might be changed + BOOL bPossibleGeomChange(FALSE); + SfxWhichIter aIter(rAttr); + UINT16 nWhich = aIter.FirstWhich(); + while(!bPossibleGeomChange && nWhich) + { + SfxItemState eState = rAttr.GetItemState(nWhich); + if(eState == SFX_ITEM_SET) + { + if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME) + || nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL + || nWhich == SDRATTR_3DOBJ_BACKSCALE + || nWhich == SDRATTR_3DOBJ_DEPTH + || nWhich == SDRATTR_3DOBJ_END_ANGLE + || nWhich == SDRATTR_3DSCENE_DISTANCE) + { + bPossibleGeomChange = TRUE; + } + } + nWhich = aIter.NextWhich(); + } + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + { + XubString aStr; + ImpTakeDescriptionStr(STR_EditSetAttributes,aStr); + BegUndo(aStr); + } + + const sal_uInt32 nMarkAnz(GetMarkedObjectCount()); + std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters; + + // create ItemSet without SFX_ITEM_DONTCARE. Put() + // uses it's second parameter (bInvalidAsDefault) to + // remove all such items to set them to default. + SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges()); + aAttr.Put(rAttr, TRUE); + + // #i38135# + bool bResetAnimationTimer(false); + + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj = pM->GetMarkedSdrObj(); + + if( bUndo ) + { + std::vector< SdrUndoAction* > vConnectorUndoActions; + SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj ); + if ( pEdgeObj ) + bPossibleGeomChange = TRUE; + else if( bUndo ) + vConnectorUndoActions = CreateConnectorUndo( *pObj ); + + AddUndoActions( vConnectorUndoActions ); + } + + // new geometry undo + if(bPossibleGeomChange && bUndo) + { + // save position and size of obect, too + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + } + + if( bUndo ) + { + // #i8508# + // If this is a text object also rescue the OutlinerParaObject since + // applying attributes to the object may change text layout when + // multiple portions exist with multiple formats. If a OutlinerParaObject + // really exists and needs to be rescued is evaluated in the undo + // implementation itself. + const bool bRescueText = dynamic_cast< SdrTextObj* >(pObj) != 0; + + // add attribute undo + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj,FALSE,bHasEEItems || bPossibleGeomChange || bRescueText)); + } + + // set up a scxene updater if object is a 3d object + if(dynamic_cast< E3dObject* >(pObj)) + { + aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj)); + } + + // set attributes at object + pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll); + + if(pObj->ISA(SdrTextObj)) + { + SdrTextObj* pTextObj = ((SdrTextObj*)pObj); + + if(0 != aCharWhichIds.size()) + { + Rectangle aOldBoundRect = pTextObj->GetLastBoundRect(); + + // #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect()); + pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds ); + + // object has changed, should be called form + // RemoveOutlinerCharacterAttribs. This will change when the text + // object implementation changes. + pTextObj->SetChanged(); + + pTextObj->BroadcastObjectChange(); + pTextObj->SendUserCall(SDRUSERCALL_CHGATTR, aOldBoundRect); + } + } + + // #i38495# + if(!bResetAnimationTimer) + { + if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact()) + { + bResetAnimationTimer = true; + } + } + } + + // fire scene updaters + while(aUpdaters.size()) + { + delete aUpdaters.back(); + aUpdaters.pop_back(); + } + + // #i38135# + if(bResetAnimationTimer) + { + SetAnimationTimer(0L); + } + + // besser vorher checken, was gemacht werden soll: + // pObj->SetAttr() oder SetNotPersistAttr() + // !!! fehlende Implementation !!! + SetNotPersistAttrToMarked(rAttr,bReplaceAll); + + if( bUndo ) + EndUndo(); + } +} + +SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const +{ + SfxStyleSheet* pRet=NULL; + BOOL b1st=TRUE; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet(); + if (b1st) pRet=pSS; + else if (pRet!=pSS) return NULL; // verschiedene StyleSheets + b1st=FALSE; + } + return pRet; +} + +void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, BOOL bDontRemoveHardAttr) +{ + if (AreObjectsMarked()) + { + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + { + XubString aStr; + if (pStyleSheet!=NULL) + ImpTakeDescriptionStr(STR_EditSetStylesheet,aStr); + else + ImpTakeDescriptionStr(STR_EditDelStylesheet,aStr); + BegUndo(aStr); + } + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + if( bUndo ) + { + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj())); + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true)); + } + pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr); + } + + if( bUndo ) + EndUndo(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/* new interface src537 */ +BOOL SdrEditView::GetAttributes(SfxItemSet& rTargetSet, BOOL bOnlyHardAttr) const +{ + if(GetMarkedObjectCount()) + { + rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), FALSE); + return TRUE; + } + else + { + return SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr); + } +} + +BOOL SdrEditView::SetAttributes(const SfxItemSet& rSet, BOOL bReplaceAll) +{ + if (GetMarkedObjectCount()!=0) { + SetAttrToMarked(rSet,bReplaceAll); + return TRUE; + } else { + return SdrMarkView::SetAttributes(rSet,bReplaceAll); + } +} + +SfxStyleSheet* SdrEditView::GetStyleSheet() const // SfxStyleSheet* SdrEditView::GetStyleSheet(BOOL& rOk) const +{ + if (GetMarkedObjectCount()!=0) { + //rOk=TRUE; + return GetStyleSheetFromMarked(); + } else { + return SdrMarkView::GetStyleSheet(); // SdrMarkView::GetStyleSheet(rOk); + } +} + +BOOL SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, BOOL bDontRemoveHardAttr) +{ + if (GetMarkedObjectCount()!=0) { + SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr); + return TRUE; + } else { + return SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SfxItemSet SdrEditView::GetGeoAttrFromMarked() const +{ + SfxItemSet aRetSet(pMod->GetItemPool(), // SID_ATTR_TRANSFORM_... aus s:svxids.hrc + SID_ATTR_TRANSFORM_POS_X,SID_ATTR_TRANSFORM_ANGLE, + SID_ATTR_TRANSFORM_PROTECT_POS,SID_ATTR_TRANSFORM_AUTOHEIGHT, + SDRATTR_ECKENRADIUS,SDRATTR_ECKENRADIUS, + 0); + if (AreObjectsMarked()) { + SfxItemSet aMarkAttr(GetAttrFromMarked(FALSE)); // wg. AutoGrowHeight und Eckenradius + Rectangle aRect(GetMarkedObjRect()); + + if(GetSdrPageView()) + { + GetSdrPageView()->LogicToPagePos(aRect); + } + + // Position + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X,aRect.Left())); + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y,aRect.Top())); + + // Groesse + long nResizeRefX=aRect.Left(); + long nResizeRefY=aRect.Top(); + if (eDragMode==SDRDRAG_ROTATE) { // Drehachse auch als Referenz fuer Resize + nResizeRefX=aRef1.X(); + nResizeRefY=aRef1.Y(); + } + aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH,aRect.Right()-aRect.Left())); + aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT,aRect.Bottom()-aRect.Top())); + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X,nResizeRefX)); + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y,nResizeRefY)); + + Point aRotateAxe(aRef1); + + if(GetSdrPageView()) + { + GetSdrPageView()->LogicToPagePos(aRotateAxe); + } + + // Drehung + long nRotateRefX=aRect.Center().X(); + long nRotateRefY=aRect.Center().Y(); + if (eDragMode==SDRDRAG_ROTATE) { + nRotateRefX=aRotateAxe.X(); + nRotateRefY=aRotateAxe.Y(); + } + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE,GetMarkedObjRotate())); + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X,nRotateRefX)); + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y,nRotateRefY)); + + // Shear + long nShearRefX=aRect.Left(); + long nShearRefY=aRect.Bottom(); + if (eDragMode==SDRDRAG_ROTATE) { // Drehachse auch als Referenz fuer Shear + nShearRefX=aRotateAxe.X(); + nShearRefY=aRotateAxe.Y(); + } + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR,GetMarkedObjShear())); + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X,nShearRefX)); + aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y,nShearRefY)); + + // Pruefen der einzelnen Objekte, ob Objekte geschuetzt sind + const SdrMarkList& rMarkList=GetMarkedObjectList(); + ULONG nMarkCount=rMarkList.GetMarkCount(); + SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj(); + BOOL bPosProt=pObj->IsMoveProtect(); + BOOL bSizProt=pObj->IsResizeProtect(); + BOOL bPosProtDontCare=FALSE; + BOOL bSizProtDontCare=FALSE; + for (ULONG i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); i++) { + pObj=rMarkList.GetMark(i)->GetMarkedSdrObj(); + if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=TRUE; + if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=TRUE; + } + + // InvalidateItem setzt das Item auf DONT_CARE + if (bPosProtDontCare) { + aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POS); + } else { + aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POS,bPosProt)); + } + if (bSizProtDontCare) { + aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZE); + } else { + aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZE,bSizProt)); + } + + SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH); + BOOL bAutoGrow=((SdrTextAutoGrowWidthItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue(); + if (eState==SFX_ITEM_DONTCARE) { + aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH); + } else if (eState==SFX_ITEM_SET) { + aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH,bAutoGrow)); + } + + eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT); + bAutoGrow=((SdrTextAutoGrowHeightItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue(); + if (eState==SFX_ITEM_DONTCARE) { + aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT); + } else if (eState==SFX_ITEM_SET) { + aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT,bAutoGrow)); + } + + eState=aMarkAttr.GetItemState(SDRATTR_ECKENRADIUS); + long nRadius=((SdrEckenradiusItem&)(aMarkAttr.Get(SDRATTR_ECKENRADIUS))).GetValue(); + if (eState==SFX_ITEM_DONTCARE) { + aRetSet.InvalidateItem(SDRATTR_ECKENRADIUS); + } else if (eState==SFX_ITEM_SET) { + aRetSet.Put(SdrEckenradiusItem(nRadius)); + } + + } + return aRetSet; +} + +Point ImpGetPoint(Rectangle aRect, RECT_POINT eRP) +{ + switch(eRP) { + case RP_LT: return aRect.TopLeft(); + case RP_MT: return aRect.TopCenter(); + case RP_RT: return aRect.TopRight(); + case RP_LM: return aRect.LeftCenter(); + case RP_MM: return aRect.Center(); + case RP_RM: return aRect.RightCenter(); + case RP_LB: return aRect.BottomLeft(); + case RP_MB: return aRect.BottomCenter(); + case RP_RB: return aRect.BottomRight(); + } + return Point(); // Sollte nicht vorkommen ! +} + +void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr) +{ + Rectangle aRect(GetMarkedObjRect()); + + if(GetSdrPageView()) + { + GetSdrPageView()->LogicToPagePos(aRect); + } + + long nOldRotateAngle=GetMarkedObjRotate(); + long nOldShearAngle=GetMarkedObjShear(); + const SdrMarkList& rMarkList=GetMarkedObjectList(); + ULONG nMarkCount=rMarkList.GetMarkCount(); + SdrObject* pObj=NULL; + + RECT_POINT eSizePoint=RP_MM; + long nPosDX=0; + long nPosDY=0; + long nSizX=0; + long nSizY=0; + long nRotateAngle=0; + + // #86909# + sal_Bool bModeIsRotate(eDragMode == SDRDRAG_ROTATE); + long nRotateX(0); + long nRotateY(0); + long nOldRotateX(0); + long nOldRotateY(0); + if(bModeIsRotate) + { + Point aRotateAxe(aRef1); + + if(GetSdrPageView()) + { + GetSdrPageView()->LogicToPagePos(aRotateAxe); + } + + nRotateX = nOldRotateX = aRotateAxe.X(); + nRotateY = nOldRotateY = aRotateAxe.Y(); + } + + long nNewShearAngle=0; + long nShearAngle=0; + long nShearX=0; + long nShearY=0; + BOOL bShearVert=FALSE; + + BOOL bChgPos=FALSE; + BOOL bChgSiz=FALSE; + BOOL bChgHgt=FALSE; + BOOL bRotate=FALSE; + BOOL bShear =FALSE; + + BOOL bSetAttr=FALSE; + SfxItemSet aSetAttr(pMod->GetItemPool()); + + const SfxPoolItem* pPoolItem=NULL; + + // Position + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_X,TRUE,&pPoolItem)) { + nPosDX=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Left(); + bChgPos=TRUE; + } + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_Y,TRUE,&pPoolItem)){ + nPosDY=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Top(); + bChgPos=TRUE; + } + // Groesse + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_WIDTH,TRUE,&pPoolItem)) { + nSizX=((const SfxUInt32Item*)pPoolItem)->GetValue(); + bChgSiz=TRUE; + } + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,TRUE,&pPoolItem)) { + nSizY=((const SfxUInt32Item*)pPoolItem)->GetValue(); + bChgSiz=TRUE; + bChgHgt=TRUE; + } + if (bChgSiz) { + eSizePoint=(RECT_POINT)((const SfxAllEnumItem&)rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINT)).GetValue(); + } + + // Rotation + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ANGLE,TRUE,&pPoolItem)) { + nRotateAngle=((const SfxInt32Item*)pPoolItem)->GetValue()-nOldRotateAngle; + bRotate = (nRotateAngle != 0); + } + + // #86909# pos rot point x + if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_X, TRUE ,&pPoolItem)) + nRotateX = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_X)).GetValue(); + + // #86909# pos rot point y + if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_Y, TRUE ,&pPoolItem)) + nRotateY = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_Y)).GetValue(); + + // Shear + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_SHEAR,TRUE,&pPoolItem)) { + nNewShearAngle=((const SfxInt32Item*)pPoolItem)->GetValue(); + if (nNewShearAngle>SDRMAXSHEAR) nNewShearAngle=SDRMAXSHEAR; + if (nNewShearAngle<-SDRMAXSHEAR) nNewShearAngle=-SDRMAXSHEAR; + if (nNewShearAngle!=nOldShearAngle) { + bShearVert=((const SfxBoolItem&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL)).GetValue(); + if (bShearVert) { + nShearAngle=nNewShearAngle; + } else { + if (nNewShearAngle!=0 && nOldShearAngle!=0) { + // Bugfix #25714#. + double nOld=tan((double)nOldShearAngle*nPi180); + double nNew=tan((double)nNewShearAngle*nPi180); + nNew-=nOld; + nNew=atan(nNew)/nPi180; + nShearAngle=Round(nNew); + } else { + nShearAngle=nNewShearAngle-nOldShearAngle; + } + } + bShear=nShearAngle!=0; + if (bShear) { + nShearX=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X)).GetValue(); + nShearY=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y)).GetValue(); + } + } + } + + // AutoGrow + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOWIDTH,TRUE,&pPoolItem)) { + BOOL bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue(); + aSetAttr.Put(SdrTextAutoGrowWidthItem(bAutoGrow)); + bSetAttr=TRUE; + } + + if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOHEIGHT,TRUE,&pPoolItem)) { + BOOL bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue(); + aSetAttr.Put(SdrTextAutoGrowHeightItem(bAutoGrow)); + bSetAttr=TRUE; + } + + // Eckenradius + if (bEdgeRadiusAllowed && SFX_ITEM_SET==rAttr.GetItemState(SDRATTR_ECKENRADIUS,TRUE,&pPoolItem)) { + long nRadius=((SdrEckenradiusItem*)pPoolItem)->GetValue(); + aSetAttr.Put(SdrEckenradiusItem(nRadius)); + bSetAttr=TRUE; + } + + ForcePossibilities(); + + BegUndo(ImpGetResStr(STR_EditTransform),GetDescriptionOfMarkedObjects()); + + if (bSetAttr) { + SetAttrToMarked(aSetAttr,FALSE); + } + + // Groesse und Hoehe aendern + if (bChgSiz && (bResizeFreeAllowed || bResizePropAllowed)) { + Fraction aWdt(nSizX,aRect.Right()-aRect.Left()); + Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top()); + Point aRef(ImpGetPoint(aRect,eSizePoint)); + + if(GetSdrPageView()) + { + GetSdrPageView()->PagePosToLogic(aRef); + } + + ResizeMarkedObj(aRef,aWdt,aHgt); + } + + // Rotieren + if (bRotate && (bRotateFreeAllowed || bRotate90Allowed)) { + Point aRef(nRotateX,nRotateY); + + if(GetSdrPageView()) + { + GetSdrPageView()->PagePosToLogic(aRef); + } + + RotateMarkedObj(aRef,nRotateAngle); + } + + // #86909# set rotation point position + if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY)) + { + Point aNewRef1(nRotateX, nRotateY); + + if(GetSdrPageView()) + { + GetSdrPageView()->PagePosToLogic(aNewRef1); + } + + SetRef1(aNewRef1); + } + + // Shear + if (bShear && bShearAllowed) { + Point aRef(nShearX,nShearY); + + if(GetSdrPageView()) + { + GetSdrPageView()->PagePosToLogic(aRef); + } + + ShearMarkedObj(aRef,nShearAngle,bShearVert); + + // #i74358# + // ShearMarkedObj creates a linear combination of the existing transformation and + // the new shear to apply. If the object is already transformed (e.g. rotated) the + // linear combination will not decompose to the same start values again, but to a + // new combination. Thus it makes no sense to check if the wanted shear is reached + // or not. Taking out. +#if 0 + long nTempAngle=GetMarkedObjShear(); + if (nTempAngle!=0 && nTempAngle!=nNewShearAngle && !bShearVert) { + // noch eine 2. Iteration zur Kompensation der Rundungsfehler + double nOld=tan((double)nTempAngle*nPi180); + double nNew=tan((double)nNewShearAngle*nPi180); + nNew-=nOld; + nNew=atan(nNew)/nPi180; + nTempAngle=Round(nNew); + if (nTempAngle!=0) { + ShearMarkedObj(aRef,nTempAngle,bShearVert); + } + } +#endif + } + + // Position aendern + if (bChgPos && bMoveAllowed) { + MoveMarkedObj(Size(nPosDX,nPosDY)); + } + + // protect position + if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_POS, TRUE, &pPoolItem)) + { + const sal_Bool bProtPos(((const SfxBoolItem*)pPoolItem)->GetValue()); + bool bChanged(false); + + for(sal_uInt32 i(0); i < nMarkCount; i++) + { + pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + + if(pObj->IsMoveProtect() != bProtPos) + { + bChanged = true; + pObj->SetMoveProtect(bProtPos); + + if(bProtPos) + { + pObj->SetResizeProtect(true); + } + } + } + + if(bChanged) + { + bMoveProtect = bProtPos; + + if(bProtPos) + { + bResizeProtect = true; + } + + // #i77187# there is no simple method to get the toolbars updated + // in the application. The App is listening to selection change and i + // will use it here (even if not true). It's acceptable since changing + // this model data is pretty rare and only possible using the F4 dialog + MarkListHasChanged(); + } + } + + if(!bMoveProtect) + { + // protect size + if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_SIZE, TRUE, &pPoolItem)) + { + const sal_Bool bProtSize(((const SfxBoolItem*)pPoolItem)->GetValue()); + bool bChanged(false); + + for(sal_uInt32 i(0); i < nMarkCount; i++) + { + pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + + if(pObj->IsResizeProtect() != bProtSize) + { + bChanged = true; + pObj->SetResizeProtect(bProtSize); + } + } + + if(bChanged) + { + bResizeProtect = bProtSize; + + // #i77187# see above + MarkListHasChanged(); + } + } + } + + EndUndo(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrEditView::IsAlignPossible() const +{ // Mindestens 2 markierte Objekte, davon mind. 1 beweglich + ForcePossibilities(); + ULONG nAnz=GetMarkedObjectCount(); + if (nAnz==0) return FALSE; // Nix markiert! + if (nAnz==1) return bMoveAllowed; // einzelnes Obj an der Seite ausrichten + return bOneOrMoreMovable; // ansonsten ist MarkCount>=2 +} + +void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert, BOOL bBoundRects) +{ + if (eHor==SDRHALIGN_NONE && eVert==SDRVALIGN_NONE) + return; + + SortMarkedObjects(); + if (GetMarkedObjectCount()<1) + return; + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + { + XubString aStr(GetDescriptionOfMarkedObjects()); + if (eHor==SDRHALIGN_NONE) + { + switch (eVert) + { + case SDRVALIGN_TOP : ImpTakeDescriptionStr(STR_EditAlignVTop ,aStr); break; + case SDRVALIGN_BOTTOM: ImpTakeDescriptionStr(STR_EditAlignVBottom,aStr); break; + case SDRVALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignVCenter,aStr); break; + default: break; + } + } + else if (eVert==SDRVALIGN_NONE) + { + switch (eHor) + { + case SDRHALIGN_LEFT : ImpTakeDescriptionStr(STR_EditAlignHLeft ,aStr); break; + case SDRHALIGN_RIGHT : ImpTakeDescriptionStr(STR_EditAlignHRight ,aStr); break; + case SDRHALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignHCenter,aStr); break; + default: break; + } + } + else if (eHor==SDRHALIGN_CENTER && eVert==SDRVALIGN_CENTER) + { + ImpTakeDescriptionStr(STR_EditAlignCenter,aStr); + } + else + { + ImpTakeDescriptionStr(STR_EditAlign,aStr); + } + BegUndo(aStr); + } + + Rectangle aBound; + ULONG nMarkAnz=GetMarkedObjectCount(); + ULONG nm; + BOOL bHasFixed=FALSE; + for (nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrObjTransformInfoRec aInfo; + pObj->TakeObjInfo(aInfo); + if (!aInfo.bMoveAllowed || pObj->IsMoveProtect()) + { + Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect()); + aBound.Union(aObjRect); + bHasFixed=TRUE; + } + } + if (!bHasFixed) + { + if (nMarkAnz==1) + { // einzelnes Obj an der Seite ausrichten + const SdrObject* pObj=GetMarkedObjectByIndex(0L); + const SdrPage* pPage=pObj->GetPage(); + const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(GetSdrPageViewOfMarkedByIndex(0),&(pObj->GetSnapRect())); + const SdrPageGridFrame* pFrame=NULL; + if (pGFL!=NULL && pGFL->GetCount()!=0) + { // Writer + pFrame=&((*pGFL)[0]); + } + + if (pFrame!=NULL) + { // Writer + aBound=pFrame->GetUserArea(); + } + else + { + aBound=Rectangle(pPage->GetLftBorder(),pPage->GetUppBorder(), + pPage->GetWdt()-pPage->GetRgtBorder(), + pPage->GetHgt()-pPage->GetLwrBorder()); + } + } + else + { + if (bBoundRects) + aBound=GetMarkedObjBoundRect(); + else + aBound=GetMarkedObjRect(); + } + } + Point aCenter(aBound.Center()); + for (nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrObjTransformInfoRec aInfo; + pObj->TakeObjInfo(aInfo); + if (aInfo.bMoveAllowed && !pObj->IsMoveProtect()) + { + // SdrPageView* pPV=pM->GetPageView(); + long nXMov=0; + long nYMov=0; + Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect()); + switch (eVert) + { + case SDRVALIGN_TOP : nYMov=aBound.Top() -aObjRect.Top() ; break; + case SDRVALIGN_BOTTOM: nYMov=aBound.Bottom()-aObjRect.Bottom() ; break; + case SDRVALIGN_CENTER: nYMov=aCenter.Y() -aObjRect.Center().Y(); break; + default: break; + } + switch (eHor) + { + case SDRHALIGN_LEFT : nXMov=aBound.Left() -aObjRect.Left() ; break; + case SDRHALIGN_RIGHT : nXMov=aBound.Right() -aObjRect.Right() ; break; + case SDRHALIGN_CENTER: nXMov=aCenter.X() -aObjRect.Center().X(); break; + default: break; + } + if (nXMov!=0 || nYMov!=0) + { + // #104104# SdrEdgeObj needs an extra SdrUndoGeoObj since the + // connections may need to be saved + if( bUndo ) + { + if( dynamic_cast<SdrEdgeObj*>(pObj) ) + { + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + } + + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov))); + } + + pObj->Move(Size(nXMov,nYMov)); + } + } + } + + if( bUndo ) + EndUndo(); +} + diff --git a/svx/source/svdraw/svdedtv2.cxx b/svx/source/svdraw/svdedtv2.cxx new file mode 100644 index 000000000000..8cf83c0429cc --- /dev/null +++ b/svx/source/svdraw/svdedtv2.cxx @@ -0,0 +1,2139 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 "svditer.hxx" +#include <svx/svdograf.hxx> // fuer Possibilities +#include <svx/svdoole2.hxx> // und Mtf-Import +#include "svdstr.hrc" // Namen aus der Resource +#include "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*/, ULONG /*nOldPos*/, ULONG /*nNewPos*/) +{ +} + +void SdrEditView::MovMarkedToTop() +{ + ULONG nAnz=GetMarkedObjectCount(); + if (nAnz!=0) + { + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOTOP); + + SortMarkedObjects(); + ULONG nm; + for (nm=0; nm<nAnz; nm++) + { // Ordnums muessen alle stimmen! + GetMarkedObjectByIndex(nm)->GetOrdNum(); + } + BOOL bChg=FALSE; + SdrObjList* pOL0=NULL; + ULONG nNewPos=0; + for (nm=nAnz; nm>0;) + { + nm--; + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrObjList* pOL=pObj->GetObjList(); + if (pOL!=pOL0) + { + nNewPos=ULONG(pOL->GetObjCount()-1); + pOL0=pOL; + } + ULONG nNowPos=pObj->GetOrdNumDirect(); + const Rectangle& rBR=pObj->GetCurrentBoundRect(); + ULONG nCmpPos=nNowPos+1; + SdrObject* pMaxObj=GetMaxToTopObj(pObj); + if (pMaxObj!=NULL) + { + ULONG 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 + } + BOOL bEnd=FALSE; + while (nCmpPos<nNewPos && !bEnd) + { + SdrObject* pCmpObj=pOL->GetObj(nCmpPos); + if (pCmpObj==NULL) + { + DBG_ERROR("MovMarkedToTop(): Vergleichsobjekt nicht gefunden"); + bEnd=TRUE; + } + else if (pCmpObj==pMaxObj) + { + nNewPos=nCmpPos; + nNewPos--; + bEnd=TRUE; + } + else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect())) + { + nNewPos=nCmpPos; + bEnd=TRUE; + } + else + { + nCmpPos++; + } + } + if (nNowPos!=nNewPos) + { + bChg=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() +{ + ULONG nAnz=GetMarkedObjectCount(); + if (nAnz!=0) + { + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOBTM); + + SortMarkedObjects(); + ULONG nm; + for (nm=0; nm<nAnz; nm++) + { // Ordnums muessen alle stimmen! + GetMarkedObjectByIndex(nm)->GetOrdNum(); + } + + BOOL bChg=FALSE; + SdrObjList* pOL0=NULL; + ULONG 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; + } + ULONG nNowPos=pObj->GetOrdNumDirect(); + const Rectangle& rBR=pObj->GetCurrentBoundRect(); + ULONG nCmpPos=nNowPos; if (nCmpPos>0) nCmpPos--; + SdrObject* pMaxObj=GetMaxToBtmObj(pObj); + if (pMaxObj!=NULL) + { + ULONG 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 + } + BOOL bEnd=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=TRUE; + } + else if (pCmpObj==pMaxObj) + { + nNewPos=nCmpPos; + nNewPos++; + bEnd=TRUE; + } + else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect())) + { + nNewPos=nCmpPos; + bEnd=TRUE; + } + else + { + nCmpPos--; + } + } + if (nNowPos!=nNewPos) + { + bChg=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) +{ + ULONG 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 + ULONG 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(); + } + } + ULONG nm; + for (nm=0; nm<nAnz; nm++) + { // Ordnums muessen alle stimmen! + GetMarkedObjectByIndex(nm)->GetOrdNum(); + } + BOOL bChg=FALSE; + SdrObjList* pOL0=NULL; + ULONG 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=ULONG(pOL->GetObjCount()-1); + pOL0=pOL; + } + ULONG nNowPos=pObj->GetOrdNumDirect(); + SdrObject* pMaxObj=GetMaxToTopObj(pObj); + if (pMaxObj!=NULL) + { + ULONG 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()) + { + ULONG 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=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) +{ + ULONG 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 + ULONG 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(); + } + } + ULONG nm; + for (nm=0; nm<nAnz; nm++) { // Ordnums muessen alle stimmen! + GetMarkedObjectByIndex(nm)->GetOrdNum(); + } + BOOL bChg=FALSE; + SdrObjList* pOL0=NULL; + ULONG 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; + } + ULONG nNowPos=pObj->GetOrdNumDirect(); + SdrObject* pMinObj=GetMaxToBtmObj(pObj); + if (pMinObj!=NULL) { + ULONG 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()) { + ULONG 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=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(); + ULONG nMarkAnz=GetMarkedObjectCount(); + if (nMarkAnz>0) + { + //BOOL bNeedBundle=FALSE; + BOOL bChg=FALSE; + + bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_REVORDER); + + ULONG a=0; + do { + // Markierung ueber mehrere PageViews berueksichtigen + ULONG b=a+1; + while (b<nMarkAnz && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) b++; + b--; + SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList(); + ULONG 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); + ULONG nOrd1=pObj1->GetOrdNumDirect(); + ULONG 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=TRUE; + } + a=b+1; + } while (a<nMarkAnz); + + if(bUndo) + EndUndo(); + + if(bChg) + MarkListHasChanged(); + } +} + +void SdrEditView::ImpCheckToTopBtmPossible() +{ + ULONG nAnz=GetMarkedObjectCount(); + if (nAnz==0) + return; + if (nAnz==1) + { // Sonderbehandlung fuer Einzelmarkierung + SdrObject* pObj=GetMarkedObjectByIndex(0); + SdrObjList* pOL=pObj->GetObjList(); + ULONG nMax=pOL->GetObjCount(); + ULONG nMin=0; + ULONG nObjNum=pObj->GetOrdNum(); + SdrObject* pRestrict=GetMaxToTopObj(pObj); + if (pRestrict!=NULL) { + ULONG nRestrict=pRestrict->GetOrdNum(); + if (nRestrict<nMax) nMax=nRestrict; + } + pRestrict=GetMaxToBtmObj(pObj); + if (pRestrict!=NULL) { + ULONG nRestrict=pRestrict->GetOrdNum(); + if (nRestrict>nMin) nMin=nRestrict; + } + bToTopPossible=nObjNum<ULONG(nMax-1); + bToBtmPossible=nObjNum>nMin; + } else { // Mehrfachselektion + ULONG 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; + } + ULONG nPos=pObj->GetOrdNum(); + bToBtmPossible=nPos>ULONG(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; + } + ULONG nPos=pObj->GetOrdNum(); + bToTopPossible=nPos+1<ULONG(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; + INT32 mnPos; + INT32 mnLength; +}; + +DECLARE_LIST(ImpDistributeEntryList, ImpDistributeEntry*) + +void SdrEditView::DistributeMarkedObjects() +{ + 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 + + UINT16 nResult = pDlg->Execute(); + + if(nResult == RET_OK) + { + SvxDistributeHorizontal eHor = pDlg->GetDistributeHor(); + SvxDistributeVertical eVer = pDlg->GetDistributeVer(); + ImpDistributeEntryList aEntryList; + 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 + 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); + INT32 nDelta = (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 + 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); + INT32 nDelta = (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((ULONG)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 + 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); + INT32 nDelta = (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 + 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); + INT32 nDelta = (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((ULONG)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(); + + UINT32 nInsPos=0xFFFFFFFF; + const SdrObject* pAttrObj = NULL; + basegfx::B2DPolyPolygon aMergePolyPolygonA; + basegfx::B2DPolyPolygon aMergePolyPolygonB; + + SdrObjList* pInsOL = NULL; + SdrPageView* pInsPV = NULL; + BOOL bFirstObjectComplete(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(TRUE); + ConvertMarkedToPathObj(sal_True); + OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)"); + + for(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 = 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, FALSE, 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, FALSE, 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); // TRUE=andere Objekte ausser PathObj's vorhanden + sal_Bool bMin1PolyPoly(sal_False); // 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, ULONG& rPos, SdrPageView* pPV, 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, TRUE)); + MarkObj(pPath, pPV, FALSE, 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, TRUE)); + MarkObj(pPath, pPV, FALSE, 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, FALSE, 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, FALSE, TRUE); + } + } + } + } +} + +void SdrEditView::DismantleMarkedObjects(BOOL bMakeLines) +{ + //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); + } + + ULONG nm; + ULONG 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())); + ULONG nPos0=pObj->GetOrdNumDirect(); + ULONG 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,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 ULONG nAnz = GetMarkedObjectCount(); + for(ULONG 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. + ULONG nInsPos=pSrcLst->GetObjCount(); + BOOL bNeedInsPos=TRUE; + for (ULONG 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(); + } + BOOL bForeignList=pSrcLst!=pAktLst; + BOOL bGrouped=pSrcLst!=pPage; + if (!bForeignList && bNeedInsPos) + { + nInsPos=pObj->GetOrdNum(); // ua, damit sind alle ObjOrdNum der Page gesetzt + nInsPos++; + bNeedInsPos=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)); + ULONG nAnz=pDstLst->GetObjCount(); + SdrInsertReason aReason(SDRREASON_VIEWCALL,pRefObj); + pAktLst->InsertObject(pGrp,nInsPos,&aReason); + if( bUndo ) + { + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // Kein Recalc! + for (ULONG 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); + + ULONG nCount=0; + XubString aName1; + XubString aName; + BOOL bNameOk=FALSE; + for (ULONG 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=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 = FALSE; + } + } + ULONG 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. + ULONG nAnz=pSrcLst->GetObjCount(); + ULONG 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()),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,TRUE); // Durch das obige Einsortieren ist aNewMark genau verkehrtherum + MarkListHasChanged(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// ### ### # # # # ##### #### ##### ##### ### #### ### # # # +// # # # # ## # # # # # # # # # # # # # # # # # +// # # # # # # # # #### #### # # # # #### # # # # +// # # # # # ## # # # # # # # # # # # # # # +// ### ### # # # ##### # # # # ### # ### #### # +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, BOOL bPath, 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(BOOL bPath, BOOL bLineToArea) +{ + BOOL bMrkChg=FALSE; + BOOL bModChg=FALSE; + if (AreObjectsMarked()) { + ULONG nMarkAnz=GetMarkedObjectCount(); + USHORT 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 (ULONG 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=TRUE; + } + } else { + SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea); + if (pNewObj!=NULL) { + bModChg=TRUE; + bMrkChg=TRUE; + GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm); + } + } + } + EndUndo(); + if (bMrkChg) AdjustMarkHdl(); + if (bMrkChg) MarkListHasChanged(); + } +} + +void SdrEditView::ConvertMarkedToPathObj(BOOL bLineToArea) +{ + ImpConvertTo(TRUE, bLineToArea); +} + +void SdrEditView::ConvertMarkedToPolyObj(BOOL bLineToArea) +{ + ImpConvertTo(FALSE, bLineToArea); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// # # ##### ##### ### ##### # # ##### # # # #### ### #### ##### +// ## ## # # # # # # # # # ## ## # # # # # # # +// # # # #### # ##### ### # # #### ### # # # # #### # # #### # +// # # # # # # # # # # # # # # # # # # # +// # # ##### # # # # # #### ##### # # # # ### # # # +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo) +{ + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + BegUndo(String(), String(), SDRREPFUNC_OBJ_IMPORTMTF); + + SortMarkedObjects(); + SdrMarkList aForTheDescription; + SdrMarkList aNewMarked; + ULONG nAnz=GetMarkedObjectCount(); + + for (ULONG 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(); + ULONG nInsPos=pObj->GetOrdNum()+1; + SdrGrafObj* pGraf=PTR_CAST(SdrGrafObj,pObj); + SdrOle2Obj* pOle2=PTR_CAST(SdrOle2Obj,pObj); + ULONG nInsAnz=0; + if (pGraf!=NULL && pGraf->HasGDIMetaFile()) + { + ImpSdrGDIMetaFileImport aFilter(*pMod); + aFilter.SetScaleRect(pGraf->GetSnapRect()); + aFilter.SetLayer(pObj->GetLayer()); + nInsAnz=aFilter.DoImport(pGraf->GetTransformedGraphic().GetGDIMetaFile(),*pOL,nInsPos,pProgrInfo); + } + if ( pOle2!=NULL && pOle2->GetGraphic() ) + { + //const GDIMetaFile* pMtf=pOle2->GetGDIMetaFile(); + ImpSdrGDIMetaFileImport aFilter(*pMod); + aFilter.SetScaleRect(pOle2->GetLogicRect()); + aFilter.SetLayer(pObj->GetLayer()); + nInsAnz=aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(),*pOL,nInsPos,pProgrInfo); + } + if (nInsAnz!=0) + { + ULONG nObj=nInsPos; + for (ULONG i=0; i<nInsAnz; i++) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj))); + + // Neue MarkList pflegen + SdrMark aNewMark(pOL->GetObj(nObj), 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(ULONG a(0); a < aNewMarked.GetMarkCount(); a++) + { + GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a)); + } + + SortMarkedObjects(); + } + + if( bUndo ) + { + SetUndoComment(ImpGetResStr(STR_EditImportMtf),aForTheDescription.GetMarkDescription()); + EndUndo(); + } +} + diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx new file mode 100644 index 000000000000..7235310def0b --- /dev/null +++ b/svx/source/svdraw/svdedxv.cxx @@ -0,0 +1,2146 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <com/sun/star/i18n/WordType.hpp> + +#include <svtools/accessibilityoptions.hxx> + +#include <svx/svdedxv.hxx> +#include <svl/solar.hrc> + +//#include <tools/string.h> +#include <svl/itemiter.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/hatch.hxx> +#include <svl/whiter.hxx> +#include <svl/style.hxx> +#include <editeng/editstat.hxx> +#include <tools/config.hxx> +#include <vcl/cursor.hxx> +#include <editeng/unotext.hxx> + +#include <editeng/editeng.hxx> +#include <editeng/editobj.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/scripttypeitem.hxx> +#include "svditext.hxx" +#include <svx/svdoutl.hxx> +#include <svx/sdtfchim.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdundo.hxx> +#include "svditer.hxx" +#include "svx/svdpagv.hxx" +#include "svx/svdpage.hxx" +#include "svx/svdetc.hxx" // fuer GetDraftFillColor +#include "svx/svdotable.hxx" +#include <svx/selectioncontroller.hxx> +#ifdef DBG_UTIL +#include <svdibrow.hxx> +#endif + +#include <svx/svdoutl.hxx> +#include <svx/svddrgv.hxx> // fuer SetSolidDragging() +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include "globl3d.hxx" +#include <editeng/outliner.hxx> +#include <editeng/adjitem.hxx> + +// #98988# +#include <svtools/colorcfg.hxx> +#include <vcl/svapp.hxx> //add CHINA001 +#include <sdrpaintwindow.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObjEditView::ImpClearVars() +{ + bQuickTextEditMode=TRUE; + bMacroMode=TRUE; + pTextEditOutliner=NULL; + pTextEditOutlinerView=NULL; + pTextEditPV=NULL; + pTextEditWin=NULL; + pTextEditCursorMerker=NULL; + pEditPara=NULL; + bTextEditNewObj=FALSE; + bMacroDown=FALSE; + pMacroObj=NULL; + pMacroPV=NULL; + pMacroWin=NULL; + nMacroTol=0; + bTextEditDontDelete=FALSE; + bTextEditOnlyOneView=FALSE; +} + +SdrObjEditView::SdrObjEditView(SdrModel* pModel1, OutputDevice* pOut): + SdrGlueEditView(pModel1,pOut) +{ + ImpClearVars(); +} + +SdrObjEditView::~SdrObjEditView() +{ + pTextEditWin = NULL; // Damit es in SdrEndTextEdit kein ShowCursor gibt + if (IsTextEdit()) SdrEndTextEdit(); + if (pTextEditOutliner!=NULL) { + delete pTextEditOutliner; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrObjEditView::IsAction() const +{ + return IsMacroObj() || SdrGlueEditView::IsAction(); +} + +void SdrObjEditView::MovAction(const Point& rPnt) +{ + if (IsMacroObj()) MovMacroObj(rPnt); + SdrGlueEditView::MovAction(rPnt); +} + +void SdrObjEditView::EndAction() +{ + if (IsMacroObj()) EndMacroObj(); + SdrGlueEditView::EndAction(); +} + +void SdrObjEditView::BckAction() +{ + BrkMacroObj(); + SdrGlueEditView::BckAction(); +} + +void SdrObjEditView::BrkAction() +{ + BrkMacroObj(); + SdrGlueEditView::BrkAction(); +} + +void SdrObjEditView::TakeActionRect(Rectangle& rRect) const +{ + if (IsMacroObj()) { + rRect=pMacroObj->GetCurrentBoundRect(); + } else { + SdrGlueEditView::TakeActionRect(rRect); + } +} + +void __EXPORT SdrObjEditView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + SdrGlueEditView::Notify(rBC,rHint); + // Printerwechsel waerend des Editierens + SdrHint* pSdrHint=PTR_CAST(SdrHint,&rHint); + if (pSdrHint!=NULL && pTextEditOutliner!=NULL) { + SdrHintKind eKind=pSdrHint->GetKind(); + if (eKind==HINT_REFDEVICECHG) { + pTextEditOutliner->SetRefDevice(pMod->GetRefDevice()); + } + if (eKind==HINT_DEFAULTTABCHG) { + pTextEditOutliner->SetDefTab(pMod->GetDefaultTabulator()); + } + if (eKind==HINT_DEFFONTHGTCHG) { + // ... + } + if (eKind==HINT_MODELSAVED) { // #43095# + pTextEditOutliner->ClearModifyFlag(); + } + } +} + +void SdrObjEditView::ModelHasChanged() +{ + SdrGlueEditView::ModelHasChanged(); + if (mxTextEditObj.is() && !mxTextEditObj->IsInserted()) SdrEndTextEdit(); // Objekt geloescht + // TextEditObj geaendert? + if (IsTextEdit()) { + SdrTextObj* pTextObj=dynamic_cast<SdrTextObj*>( mxTextEditObj.get() ); + if (pTextObj!=NULL) { + ULONG nOutlViewAnz=pTextEditOutliner->GetViewCount(); + BOOL bAreaChg=FALSE; + BOOL bAnchorChg=FALSE; + BOOL bColorChg=FALSE; + bool bContourFrame=pTextObj->IsContourTextFrame(); + EVAnchorMode eNewAnchor(ANCHOR_VCENTER_HCENTER); + Rectangle aOldArea(aMinTextEditArea); + aOldArea.Union(aTextEditArea); + Color aNewColor; + { // Area Checken + Size aPaperMin1; + Size aPaperMax1; + Rectangle aEditArea1; + Rectangle aMinArea1; + pTextObj->TakeTextEditArea(&aPaperMin1,&aPaperMax1,&aEditArea1,&aMinArea1); + + // #108784# + Point aPvOfs(pTextObj->GetTextEditOffset()); + + aEditArea1.Move(aPvOfs.X(),aPvOfs.Y()); + aMinArea1.Move(aPvOfs.X(),aPvOfs.Y()); + Rectangle aNewArea(aMinArea1); + aNewArea.Union(aEditArea1); + if (aNewArea!=aOldArea || aEditArea1!=aTextEditArea || aMinArea1!=aMinTextEditArea || + pTextEditOutliner->GetMinAutoPaperSize()!=aPaperMin1 || pTextEditOutliner->GetMaxAutoPaperSize()!=aPaperMax1) { + aTextEditArea=aEditArea1; + aMinTextEditArea=aMinArea1; + pTextEditOutliner->SetUpdateMode(FALSE); + pTextEditOutliner->SetMinAutoPaperSize(aPaperMin1); + pTextEditOutliner->SetMaxAutoPaperSize(aPaperMax1); + pTextEditOutliner->SetPaperSize(Size(0,0)); // Damit der Outliner neu formatiert + if (!bContourFrame) { + pTextEditOutliner->ClearPolygon(); + ULONG nStat=pTextEditOutliner->GetControlWord(); + nStat|=EE_CNTRL_AUTOPAGESIZE; + pTextEditOutliner->SetControlWord(nStat); + } else { + ULONG nStat=pTextEditOutliner->GetControlWord(); + nStat&=~EE_CNTRL_AUTOPAGESIZE; + pTextEditOutliner->SetControlWord(nStat); + Rectangle aAnchorRect; + pTextObj->TakeTextAnchorRect(aAnchorRect); + pTextObj->ImpSetContourPolygon(*pTextEditOutliner,aAnchorRect, TRUE); + } + for (ULONG nOV=0; nOV<nOutlViewAnz; nOV++) { + OutlinerView* pOLV=pTextEditOutliner->GetView(nOV); + ULONG nStat0=pOLV->GetControlWord(); + ULONG nStat=nStat0; + // AutoViewSize nur wenn nicht KontourFrame. + if (!bContourFrame) nStat|=EV_CNTRL_AUTOSIZE; + else nStat&=~EV_CNTRL_AUTOSIZE; + if (nStat!=nStat0) pOLV->SetControlWord(nStat); + } + pTextEditOutliner->SetUpdateMode(TRUE); + bAreaChg=TRUE; + } + } + if (pTextEditOutlinerView!=NULL) { // Fuellfarbe und Anker checken + EVAnchorMode eOldAnchor=pTextEditOutlinerView->GetAnchorMode(); + eNewAnchor=(EVAnchorMode)pTextObj->GetOutlinerViewAnchorMode(); + bAnchorChg=eOldAnchor!=eNewAnchor; + Color aOldColor(pTextEditOutlinerView->GetBackgroundColor()); + aNewColor = GetTextEditBackgroundColor(*this); + bColorChg=aOldColor!=aNewColor; + } + // #104082# refresh always when it's a contour frame. That + // refresh is necessary since it triggers the repaint + // which makes the Handles visible. Changes at TakeTextRect() + // seem to have resulted in a case where no refresh is executed. + // Before that, a refresh must have been always executed + // (else this error would have happend earlier), thus i + // even think here a refresh should be done always. + // Since follow-up problems cannot even be guessed I only + // add this one more case to the if below. + // BTW: It's VERY bad style that here, inside ModelHasChanged() + // the outliner is again massively changed for the text object + // in text edit mode. Normally, all necessary data should be + // set at SdrBeginTextEdit(). Some changes and value assigns in + // SdrBeginTextEdit() are completely useless since they are set here + // again on ModelHasChanged(). + if (bContourFrame || bAreaChg || bAnchorChg || bColorChg) + { + for (ULONG nOV=0; nOV<nOutlViewAnz; nOV++) + { + OutlinerView* pOLV=pTextEditOutliner->GetView(nOV); + { // Alten OutlinerView-Bereich invalidieren + Window* pWin=pOLV->GetWindow(); + Rectangle aTmpRect(aOldArea); + USHORT nPixSiz=pOLV->GetInvalidateMore()+1; + Size aMore(pWin->PixelToLogic(Size(nPixSiz,nPixSiz))); + aTmpRect.Left()-=aMore.Width(); + aTmpRect.Right()+=aMore.Width(); + aTmpRect.Top()-=aMore.Height(); + aTmpRect.Bottom()+=aMore.Height(); + InvalidateOneWin(*pWin,aTmpRect); + } + if (bAnchorChg) + pOLV->SetAnchorMode(eNewAnchor); + if (bColorChg) + pOLV->SetBackgroundColor( aNewColor ); + + pOLV->SetOutputArea(aTextEditArea); // weil sonst scheinbar nicht richtig umgeankert wird + ImpInvalidateOutlinerView(*pOLV); + } + pTextEditOutlinerView->ShowCursor(); + } + } + ImpMakeTextCursorAreaVisible(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@@ @@@@@ @@ @@@@@@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@@ @@ @@@@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@@@@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObjEditView::ImpPaintOutlinerView(OutlinerView& rOutlView, const Rectangle& rRect) const +{ + Window* pWin = rOutlView.GetWindow(); + + if(pWin) + { + const SdrTextObj* pText = PTR_CAST(SdrTextObj,GetTextEditObject()); + bool bTextFrame(pText && pText->IsTextFrame()); + bool bFitToSize(0 != (pTextEditOutliner->GetControlWord() & EE_CNTRL_STRETCHING)); + bool bModifyMerk(pTextEditOutliner->IsModified()); // #43095# + Rectangle aBlankRect(rOutlView.GetOutputArea()); + aBlankRect.Union(aMinTextEditArea); + Rectangle aPixRect(pWin->LogicToPixel(aBlankRect)); + aBlankRect.Intersection(rRect); + rOutlView.GetOutliner()->SetUpdateMode(TRUE); // Bugfix #22596# + rOutlView.Paint(aBlankRect); + + if(!bModifyMerk) + { + // #43095# + pTextEditOutliner->ClearModifyFlag(); + } + + if(bTextFrame && !bFitToSize) + { + aPixRect.Left()--; + aPixRect.Top()--; + aPixRect.Right()++; + aPixRect.Bottom()++; + sal_uInt16 nPixSiz(rOutlView.GetInvalidateMore() - 1); + + { + // xPixRect Begrenzen, wegen Treiberproblem bei zu weit hinausragenden Pixelkoordinaten + Size aMaxXY(pWin->GetOutputSizePixel()); + long a(2 * nPixSiz); + long nMaxX(aMaxXY.Width() + a); + long nMaxY(aMaxXY.Height() + a); + + if (aPixRect.Left ()<-a) aPixRect.Left()=-a; + if (aPixRect.Top ()<-a) aPixRect.Top ()=-a; + if (aPixRect.Right ()>nMaxX) aPixRect.Right ()=nMaxX; + if (aPixRect.Bottom()>nMaxY) aPixRect.Bottom()=nMaxY; + } + + Rectangle aOuterPix(aPixRect); + aOuterPix.Left()-=nPixSiz; + aOuterPix.Top()-=nPixSiz; + aOuterPix.Right()+=nPixSiz; + aOuterPix.Bottom()+=nPixSiz; + + bool bMerk(pWin->IsMapModeEnabled()); + pWin->EnableMapMode(FALSE); + PolyPolygon aPolyPoly( 2 ); + + svtools::ColorConfig aColorConfig; + Color aHatchCol( aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor ); + const Hatch aHatch( HATCH_SINGLE, aHatchCol, 3, 450 ); + + aPolyPoly.Insert( aOuterPix ); + aPolyPoly.Insert( aPixRect ); + pWin->DrawHatch( aPolyPoly, aHatch ); + + pWin->EnableMapMode(bMerk); + } + + rOutlView.ShowCursor(); + } +} + +void SdrObjEditView::ImpInvalidateOutlinerView(OutlinerView& rOutlView) const +{ + Window* pWin = rOutlView.GetWindow(); + + if(pWin) + { + const SdrTextObj* pText = PTR_CAST(SdrTextObj,GetTextEditObject()); + bool bTextFrame(pText && pText->IsTextFrame()); + bool bFitToSize(0 != (pTextEditOutliner->GetControlWord() & EE_CNTRL_STRETCHING)); + + if(bTextFrame && !bFitToSize) + { + Rectangle aBlankRect(rOutlView.GetOutputArea()); + aBlankRect.Union(aMinTextEditArea); + Rectangle aPixRect(pWin->LogicToPixel(aBlankRect)); + sal_uInt16 nPixSiz(rOutlView.GetInvalidateMore() - 1); + + aPixRect.Left()--; + aPixRect.Top()--; + aPixRect.Right()++; + aPixRect.Bottom()++; + + { + // xPixRect Begrenzen, wegen Treiberproblem bei zu weit hinausragenden Pixelkoordinaten + Size aMaxXY(pWin->GetOutputSizePixel()); + long a(2 * nPixSiz); + long nMaxX(aMaxXY.Width() + a); + long nMaxY(aMaxXY.Height() + a); + + if (aPixRect.Left ()<-a) aPixRect.Left()=-a; + if (aPixRect.Top ()<-a) aPixRect.Top ()=-a; + if (aPixRect.Right ()>nMaxX) aPixRect.Right ()=nMaxX; + if (aPixRect.Bottom()>nMaxY) aPixRect.Bottom()=nMaxY; + } + + Rectangle aOuterPix(aPixRect); + aOuterPix.Left()-=nPixSiz; + aOuterPix.Top()-=nPixSiz; + aOuterPix.Right()+=nPixSiz; + aOuterPix.Bottom()+=nPixSiz; + + bool bMerk(pWin->IsMapModeEnabled()); + pWin->EnableMapMode(FALSE); + pWin->Invalidate(aOuterPix); + pWin->EnableMapMode(bMerk); + } + } +} + +OutlinerView* SdrObjEditView::ImpMakeOutlinerView(Window* pWin, BOOL /*bNoPaint*/, OutlinerView* pGivenView) const +{ + // Hintergrund + Color aBackground(GetTextEditBackgroundColor(*this)); + SdrTextObj* pText = dynamic_cast< SdrTextObj * >( mxTextEditObj.get() ); + BOOL bTextFrame=pText!=NULL && pText->IsTextFrame(); + BOOL bContourFrame=pText!=NULL && pText->IsContourTextFrame(); + // OutlinerView erzeugen + OutlinerView* pOutlView=pGivenView; + pTextEditOutliner->SetUpdateMode(FALSE); + if (pOutlView==NULL) pOutlView=new OutlinerView(pTextEditOutliner,pWin); + else pOutlView->SetWindow(pWin); + // Scrollen verbieten + ULONG nStat=pOutlView->GetControlWord(); + nStat&=~EV_CNTRL_AUTOSCROLL; + // AutoViewSize nur wenn nicht KontourFrame. + if (!bContourFrame) nStat|=EV_CNTRL_AUTOSIZE; + if (bTextFrame) { + USHORT nPixSiz=aHdl.GetHdlSize()*2+1; + nStat|=EV_CNTRL_INVONEMORE; + pOutlView->SetInvalidateMore(nPixSiz); + } + pOutlView->SetControlWord(nStat); + pOutlView->SetBackgroundColor( aBackground ); + if (pText!=NULL) + { + pOutlView->SetAnchorMode((EVAnchorMode)(pText->GetOutlinerViewAnchorMode())); + pTextEditOutliner->SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)pText->GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); + } + pOutlView->SetOutputArea(aTextEditArea); + pTextEditOutliner->SetUpdateMode(TRUE); + ImpInvalidateOutlinerView(*pOutlView); + return pOutlView; +} + +BOOL SdrObjEditView::IsTextEditFrame() const +{ + SdrTextObj* pText = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() ); + return pText!=NULL && pText->IsTextFrame(); +} + +IMPL_LINK(SdrObjEditView,ImpOutlinerStatusEventHdl,EditStatus*,pEditStat) +{ + if(pTextEditOutliner ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj * >( mxTextEditObj.get() ); + if( pTextObj ) + { + pTextObj->onEditOutlinerStatusEvent( pEditStat ); + } + } + return 0; +} + +IMPL_LINK(SdrObjEditView,ImpOutlinerCalcFieldValueHdl,EditFieldInfo*,pFI) +{ + bool bOk=false; + String& rStr=pFI->GetRepresentation(); + rStr.Erase(); + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() ); + if (pTextObj!=NULL) { + Color* pTxtCol=NULL; + Color* pFldCol=NULL; + bOk=pTextObj->CalcFieldValue(pFI->GetField(),pFI->GetPara(),pFI->GetPos(),TRUE,pTxtCol,pFldCol,rStr); + if (bOk) { + if (pTxtCol!=NULL) { + pFI->SetTxtColor(*pTxtCol); + delete pTxtCol; + } + if (pFldCol!=NULL) { + pFI->SetFldColor(*pFldCol); + delete pFldCol; + } else { + pFI->SetFldColor(Color(COL_LIGHTGRAY)); // kann spaeter (357) raus + } + } + } + Outliner& rDrawOutl=pMod->GetDrawOutliner(pTextObj); + Link aDrawOutlLink=rDrawOutl.GetCalcFieldValueHdl(); + if (!bOk && aDrawOutlLink.IsSet()) { + aDrawOutlLink.Call(pFI); + bOk = (BOOL)rStr.Len(); + } + if (!bOk && aOldCalcFieldValueLink.IsSet()) { + return aOldCalcFieldValueLink.Call(pFI); + } + return 0; +} + +sal_Bool SdrObjEditView::SdrBeginTextEdit( + SdrObject* pObj, SdrPageView* pPV, Window* pWin, + sal_Bool bIsNewObj, SdrOutliner* pGivenOutliner, + OutlinerView* pGivenOutlinerView, + sal_Bool bDontDeleteOutliner, sal_Bool bOnlyOneView, + sal_Bool bGrabFocus) +{ + SdrEndTextEdit(); + + if( dynamic_cast< SdrTextObj* >( pObj ) == 0 ) + return FALSE; // currently only possible with text objects + + if(bGrabFocus && pWin) + { + // attetion, this call may cause an EndTextEdit() call to this view + pWin->GrabFocus(); // to force the cursor into the edit view + } + + bTextEditDontDelete=bDontDeleteOutliner && pGivenOutliner!=NULL; + bTextEditOnlyOneView=bOnlyOneView; + bTextEditNewObj=bIsNewObj; + const sal_uInt32 nWinAnz(PaintWindowCount()); + sal_uInt32 i; + sal_Bool bBrk(sal_False); + // Abbruch, wenn kein Objekt angegeben. + + if(!pObj) + { + bBrk = sal_True; + } + + if(!bBrk && !pWin) + { + for(i = 0L; i < nWinAnz && !pWin; i++) + { + SdrPaintWindow* pPaintWindow = GetPaintWindow(i); + + if(OUTDEV_WINDOW == pPaintWindow->GetOutputDevice().GetOutDevType()) + { + pWin = (Window*)(&pPaintWindow->GetOutputDevice()); + } + } + + // Abbruch, wenn kein Window da. + if(!pWin) + { + bBrk = sal_True; + } + } + + if(!bBrk && !pPV) + { + pPV = GetSdrPageView(); + + // Abbruch, wenn keine PageView zu dem Objekt vorhanden. + if(!pPV) + { + bBrk = sal_True; + } + } + + if(pObj && pPV) + { + // Kein TextEdit an Objekten im gesperrten Layer + if(pPV->GetLockedLayers().IsSet(pObj->GetLayer())) + { + bBrk = sal_True; + } + } + + if(pTextEditOutliner) + { + DBG_ERROR("SdrObjEditView::SdrBeginTextEdit() da stand noch ein alter Outliner rum"); + delete pTextEditOutliner; + pTextEditOutliner = 0L; + } + + if(!bBrk) + { + pTextEditWin=pWin; + pTextEditPV=pPV; + mxTextEditObj.reset( pObj ); + pTextEditOutliner=pGivenOutliner; + if (pTextEditOutliner==NULL) + pTextEditOutliner = SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, mxTextEditObj->GetModel() ); + + { + SvtAccessibilityOptions aOptions; + pTextEditOutliner->ForceAutoColor( aOptions.GetIsAutomaticFontColor() ); + } + + BOOL bEmpty = mxTextEditObj->GetOutlinerParaObject()==NULL; + + aOldCalcFieldValueLink=pTextEditOutliner->GetCalcFieldValueHdl(); + // Der FieldHdl muss von SdrBeginTextEdit gesetzt sein, da dor ein UpdateFields gerufen wird. + pTextEditOutliner->SetCalcFieldValueHdl(LINK(this,SdrObjEditView,ImpOutlinerCalcFieldValueHdl)); + pTextEditOutliner->SetBeginPasteOrDropHdl(LINK(this,SdrObjEditView,BeginPasteOrDropHdl)); + pTextEditOutliner->SetEndPasteOrDropHdl(LINK(this,SdrObjEditView, EndPasteOrDropHdl)); + + // It is just necessary to make the visualized page known. Set it. + pTextEditOutliner->setVisualizedPage(pPV ? pPV->GetPage() : 0); + + pTextEditOutliner->SetTextObjNoInit( dynamic_cast< SdrTextObj* >( mxTextEditObj.get() ) ); + + if(mxTextEditObj->BegTextEdit(*pTextEditOutliner)) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() ); + DBG_ASSERT( pTextObj, "svx::SdrObjEditView::BegTextEdit(), no text object?" ); + if( !pTextObj ) + return FALSE; + + // #111096# Switch off evtl. running TextAnimation + pTextObj->SetTextAnimationAllowed(sal_False); + + // alten Cursor merken + if (pTextEditOutliner->GetViewCount()!=0) + { + OutlinerView* pTmpOLV=pTextEditOutliner->RemoveView(ULONG(0)); + if(pTmpOLV!=NULL && pTmpOLV!=pGivenOutlinerView) + delete pTmpOLV; + } + + // EditArea ueberTakeTextEditArea bestimmen + // Das koennte eigentlich entfallen, da TakeTextRect() die Berechnung der aTextEditArea vornimmt + // Die aMinTextEditArea muss jedoch wohl auch erfolgen (darum bleibt es voerst drinnen) + pTextObj->TakeTextEditArea(NULL,NULL,&aTextEditArea,&aMinTextEditArea); + + Rectangle aTextRect; + Rectangle aAnchorRect; + pTextObj->TakeTextRect(*pTextEditOutliner, aTextRect, TRUE, + &aAnchorRect /* #97097# Give TRUE here, not FALSE */); + + if ( !pTextObj->IsContourTextFrame() ) + { + // FitToSize erstmal nicht mit ContourFrame + SdrFitToSizeType eFit = pTextObj->GetFitToSize(); + if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES) + aTextRect = aAnchorRect; + } + + aTextEditArea = aTextRect; + + // #108784# + Point aPvOfs(pTextObj->GetTextEditOffset()); + + aTextEditArea.Move(aPvOfs.X(),aPvOfs.Y()); + aMinTextEditArea.Move(aPvOfs.X(),aPvOfs.Y()); + pTextEditCursorMerker=pWin->GetCursor(); + + aHdl.SetMoveOutside(TRUE); + + // #i72757# + // Since IsMarkHdlWhenTextEdit() is ignored, it is necessary + // to call AdjustMarkHdl() always. + AdjustMarkHdl(); + + pTextEditOutlinerView=ImpMakeOutlinerView(pWin,!bEmpty,pGivenOutlinerView); + + // check if this view is already inserted + ULONG i2,nCount = pTextEditOutliner->GetViewCount(); + for( i2 = 0; i2 < nCount; i2++ ) + { + if( pTextEditOutliner->GetView(i2) == pTextEditOutlinerView ) + break; + } + + if( i2 == nCount ) + pTextEditOutliner->InsertView(pTextEditOutlinerView,0); + + aHdl.SetMoveOutside(FALSE); + aHdl.SetMoveOutside(TRUE); + //OLMRefreshAllIAOManagers(); + + // alle Wins als OutlinerView beim Outliner anmelden + if(!bOnlyOneView) + { + for(i = 0L; i < nWinAnz; i++) + { + SdrPaintWindow* pPaintWindow = GetPaintWindow(i); + OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); + + if(&rOutDev != pWin && OUTDEV_WINDOW == rOutDev.GetOutDevType()) + { + OutlinerView* pOutlView = ImpMakeOutlinerView((Window*)(&rOutDev), !bEmpty, 0L); + pTextEditOutliner->InsertView(pOutlView, (sal_uInt16)i); + } + } + } + + pTextEditOutlinerView->ShowCursor(); + pTextEditOutliner->SetStatusEventHdl(LINK(this,SdrObjEditView,ImpOutlinerStatusEventHdl)); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + pTextEditOutliner->ClearModifyFlag(); + + // #71519#, #91453# + if(pWin) + { + sal_Bool bExtraInvalidate(sal_False); + + // #71519# + if(!bExtraInvalidate) + { + SdrFitToSizeType eFit = pTextObj->GetFitToSize(); + if(eFit == SDRTEXTFIT_PROPORTIONAL || eFit == SDRTEXTFIT_ALLLINES) + bExtraInvalidate = sal_True; + } + + if(bExtraInvalidate) + { + pWin->Invalidate(aTextEditArea); + } + } + + // send HINT_BEGEDIT #99840# + if( GetModel() ) + { + SdrHint aHint(*pTextObj); + aHint.SetKind(HINT_BEGEDIT); + GetModel()->Broadcast(aHint); + } + + pTextEditOutliner->setVisualizedPage(0); + + if( mxSelectionController.is() ) + mxSelectionController->onSelectionHasChanged(); + + return sal_True; // Gut gelaufen, TextEdit laeuft nun + } + else + { + bBrk = sal_True; + pTextEditOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink); + pTextEditOutliner->SetBeginPasteOrDropHdl(Link()); + pTextEditOutliner->SetEndPasteOrDropHdl(Link()); + + } + } + if (pTextEditOutliner != NULL) + { + pTextEditOutliner->setVisualizedPage(0); + } + + // wenn hier angekommen, dann ist irgendwas schief gelaufen + if(!bDontDeleteOutliner) + { + if(pGivenOutliner!=NULL) + { + delete pGivenOutliner; + pTextEditOutliner = NULL; + } + if(pGivenOutlinerView!=NULL) + { + delete pGivenOutlinerView; + pGivenOutlinerView = NULL; + } + } + if( pTextEditOutliner!=NULL ) + { + delete pTextEditOutliner; + } + + pTextEditOutliner=NULL; + pTextEditOutlinerView=NULL; + mxTextEditObj.reset(0); + pTextEditPV=NULL; + pTextEditWin=NULL; + //HMHif (bMarkHdlWhenTextEdit) { + //HMH HideMarkHdl(); + //HMH} + aHdl.SetMoveOutside(FALSE); + //HMHShowMarkHdl(); + + return sal_False; +} + +SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally) +{ + SdrEndTextEditKind eRet=SDRENDTEXTEDIT_UNCHANGED; + SdrTextObj* pTEObj = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() ); + Window* pTEWin =pTextEditWin; + SdrOutliner* pTEOutliner =pTextEditOutliner; + OutlinerView* pTEOutlinerView=pTextEditOutlinerView; + Cursor* pTECursorMerker=pTextEditCursorMerker; + + // send HINT_ENDEDIT #99840# + if( GetModel() && mxTextEditObj.is() ) + { + SdrHint aHint(*mxTextEditObj.get()); + aHint.SetKind(HINT_ENDEDIT); + GetModel()->Broadcast(aHint); + } + + mxTextEditObj.reset(0); + pTextEditPV=NULL; + pTextEditWin=NULL; + pTextEditOutliner=NULL; + pTextEditOutlinerView=NULL; + pTextEditCursorMerker=NULL; + aTextEditArea=Rectangle(); + + if (pTEOutliner!=NULL) + { + BOOL bModified=pTEOutliner->IsModified(); + if (pTEOutlinerView!=NULL) + { + pTEOutlinerView->HideCursor(); + } + if (pTEObj!=NULL) + { + pTEOutliner->CompleteOnlineSpelling(); + + SdrUndoObjSetText* pTxtUndo = 0; + + if( bModified ) + { + sal_Int32 nText; + for( nText = 0; nText < pTEObj->getTextCount(); ++nText ) + if( pTEObj->getText( nText ) == pTEObj->getActiveText() ) + break; + + pTxtUndo = dynamic_cast< SdrUndoObjSetText* >( GetModel()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTEObj, nText ) ); + } + DBG_ASSERT( !bModified || pTxtUndo, "svx::SdrObjEditView::EndTextEdit(), could not create undo action!" ); + // Den alten CalcFieldValue-Handler wieder setzen + // Muss vor Obj::EndTextEdit() geschehen, da dort ein UpdateFields() gemacht wird. + pTEOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink); + pTEOutliner->SetBeginPasteOrDropHdl(Link()); + pTEOutliner->SetEndPasteOrDropHdl(Link()); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + { + XubString aObjName; + pTEObj->TakeObjNameSingul(aObjName); + BegUndo(ImpGetResStr(STR_UndoObjSetText),aObjName); + } + + pTEObj->EndTextEdit(*pTEOutliner); + + if( (pTEObj->GetRotateAngle() != 0) || (pTEObj && pTEObj->ISA(SdrTextObj) && ((SdrTextObj*)pTEObj)->IsFontwork()) ) + { + // obviously a repaint + pTEObj->ActionChanged(); + } + + if (pTxtUndo!=NULL) + { + pTxtUndo->AfterSetText(); + if (!pTxtUndo->IsDifferent()) + { + delete pTxtUndo; + pTxtUndo=NULL; + } + } + // Loeschung des gesamten TextObj checken + SdrUndoAction* pDelUndo=NULL; + BOOL bDelObj=FALSE; + SdrTextObj* pTextObj=PTR_CAST(SdrTextObj,pTEObj); + if (pTextObj!=NULL && bTextEditNewObj) + { + bDelObj=pTextObj->IsTextFrame() && + !pTextObj->HasText() && + !pTextObj->IsEmptyPresObj() && + !pTextObj->HasFill() && + !pTextObj->HasLine(); + + if(pTEObj->IsInserted() && bDelObj && pTextObj->GetObjInventor()==SdrInventor && !bDontDeleteReally) + { + SdrObjKind eIdent=(SdrObjKind)pTextObj->GetObjIdentifier(); + if(eIdent==OBJ_TEXT || eIdent==OBJ_TEXTEXT) + { + pDelUndo= GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pTEObj); + } + } + } + if (pTxtUndo!=NULL) + { + if( bUndo ) + AddUndo(pTxtUndo); + eRet=SDRENDTEXTEDIT_CHANGED; + } + if (pDelUndo!=NULL) + { + if( bUndo ) + { + AddUndo(pDelUndo); + } + else + { + delete pDelUndo; + } + eRet=SDRENDTEXTEDIT_DELETED; + DBG_ASSERT(pTEObj->GetObjList()!=NULL,"SdrObjEditView::SdrEndTextEdit(): Fatal: Editiertes Objekt hat keine ObjList!"); + if (pTEObj->GetObjList()!=NULL) + { + pTEObj->GetObjList()->RemoveObject(pTEObj->GetOrdNum()); + CheckMarked(); // und gleich die Maekierung entfernen... + } + } + else if (bDelObj) + { // Fuer den Writer: Loeschen muss die App nachholen. + eRet=SDRENDTEXTEDIT_SHOULDBEDELETED; + } + + if( bUndo ) + EndUndo(); // EndUndo hinter Remove, falls der UndoStack gleich weggehaun' wird + + // #111096# + // Switch on evtl. TextAnimation again after TextEdit + if(pTEObj->ISA(SdrTextObj)) + { + ((SdrTextObj*)pTEObj)->SetTextAnimationAllowed(sal_True); + } + + // #i72757# + // Since IsMarkHdlWhenTextEdit() is ignored, it is necessary + // to call AdjustMarkHdl() always. + AdjustMarkHdl(); + } + // alle OutlinerViews loeschen + for (ULONG i=pTEOutliner->GetViewCount(); i>0;) + { + i--; + OutlinerView* pOLV=pTEOutliner->GetView(i); + USHORT nMorePix=pOLV->GetInvalidateMore() + 10; // solaris aw033 test #i# + Window* pWin=pOLV->GetWindow(); + Rectangle aRect(pOLV->GetOutputArea()); + pTEOutliner->RemoveView(i); + if (!bTextEditDontDelete || i!=0) + { + // die nullte gehoert mir u.U. nicht. + delete pOLV; + } + aRect.Union(aTextEditArea); + aRect.Union(aMinTextEditArea); + aRect=pWin->LogicToPixel(aRect); + aRect.Left()-=nMorePix; + aRect.Top()-=nMorePix; + aRect.Right()+=nMorePix; + aRect.Bottom()+=nMorePix; + aRect=pWin->PixelToLogic(aRect); + InvalidateOneWin(*pWin,aRect); +// pWin->Invalidate(INVALIDATE_UPDATE); + +// pWin->Update(); +// pWin->Flush(); + pWin->SetFillColor(); + pWin->SetLineColor(COL_BLACK); + pWin->DrawPixel(aRect.TopLeft()); + pWin->DrawPixel(aRect.TopRight()); + pWin->DrawPixel(aRect.BottomLeft()); + pWin->DrawPixel(aRect.BottomRight()); + //pWin->DrawRect(aRect); + } + // und auch den Outliner selbst + if (!bTextEditDontDelete) delete pTEOutliner; + else pTEOutliner->Clear(); + if (pTEWin!=NULL) { + pTEWin->SetCursor(pTECursorMerker); + } +//HMH if (bMarkHdlWhenTextEdit) { +//HMH HideMarkHdl(); +//HMH } + aHdl.SetMoveOutside(FALSE); + if (eRet!=SDRENDTEXTEDIT_UNCHANGED) +//HMH { +//HMH ShowMarkHdl(); // Handles kommen ansonsten via Broadcast +//HMH } +//HMH else + { + GetMarkedObjectListWriteAccess().SetNameDirty(); + } +#ifdef DBG_UTIL + if (pItemBrowser) + { + GetMarkedObjectListWriteAccess().SetNameDirty(); + pItemBrowser->SetDirty(); + } +#endif + } + + // #108784# + if( pTEObj && + pTEObj->GetModel() && + !pTEObj->GetModel()->isLocked() && + pTEObj->GetBroadcaster()) + { + SdrHint aHint(HINT_ENDEDIT); + aHint.SetObject(pTEObj); + ((SfxBroadcaster*)pTEObj->GetBroadcaster())->Broadcast(aHint); + } + + return eRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// info about TextEdit. Default is sal_False. +bool SdrObjEditView::IsTextEdit() const +{ + return mxTextEditObj.is(); +} + +// info about TextEditPageView. Default is 0L. +SdrPageView* SdrObjEditView::GetTextEditPageView() const +{ + return pTextEditPV; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +OutlinerView* SdrObjEditView::ImpFindOutlinerView(Window* pWin) const +{ + if (pWin==NULL) return NULL; + if (pTextEditOutliner==NULL) return NULL; + OutlinerView* pNewView=NULL; + ULONG nWinAnz=pTextEditOutliner->GetViewCount(); + for (ULONG i=0; i<nWinAnz && pNewView==NULL; i++) { + OutlinerView* pView=pTextEditOutliner->GetView(i); + if (pView->GetWindow()==pWin) pNewView=pView; + } + return pNewView; +} + +void SdrObjEditView::SetTextEditWin(Window* pWin) +{ + if(mxTextEditObj.is() && pWin!=NULL && pWin!=pTextEditWin) + { + OutlinerView* pNewView=ImpFindOutlinerView(pWin); + if (pNewView!=NULL && pNewView!=pTextEditOutlinerView) + { + if (pTextEditOutlinerView!=NULL) + { + pTextEditOutlinerView->HideCursor(); + } + pTextEditOutlinerView=pNewView; + pTextEditWin=pWin; + pWin->GrabFocus(); // Damit der Cursor hier auch blinkt + pNewView->ShowCursor(); + ImpMakeTextCursorAreaVisible(); + } + } +} + +BOOL SdrObjEditView::IsTextEditHit(const Point& rHit, short nTol) const +{ + BOOL bOk=FALSE; + if(mxTextEditObj.is()) + { + nTol=ImpGetHitTolLogic(nTol,NULL); + // nur drittel Toleranz hier, damit die Handles + // noch vernuenftig getroffen werden koennen + nTol=nTol/3; + nTol=0; // Joe am 6.3.1997: Keine Hittoleranz mehr hier + if (!bOk) + { + Rectangle aEditArea; + OutlinerView* pOLV=pTextEditOutliner->GetView(0); + if (pOLV!=NULL) + { + aEditArea.Union(pOLV->GetOutputArea()); + } + aEditArea.Left()-=nTol; + aEditArea.Top()-=nTol; + aEditArea.Right()+=nTol; + aEditArea.Bottom()+=nTol; + bOk=aEditArea.IsInside(rHit); + if (bOk) + { // Nun noch checken, ob auch wirklich Buchstaben getroffen wurden + Point aPnt(rHit); aPnt-=aEditArea.TopLeft(); + long nHitTol = 2000; + OutputDevice* pRef = pTextEditOutliner->GetRefDevice(); + if( pRef ) + nHitTol = pRef->LogicToLogic( nHitTol, MAP_100TH_MM, pRef->GetMapMode().GetMapUnit() ); + + bOk = pTextEditOutliner->IsTextPos( aPnt, (sal_uInt16)nHitTol ); + } + } + } + return bOk; +} + +BOOL SdrObjEditView::IsTextEditFrameHit(const Point& rHit) const +{ + BOOL bOk=FALSE; + if(mxTextEditObj.is()) + { + SdrTextObj* pText= dynamic_cast<SdrTextObj*>(mxTextEditObj.get()); + OutlinerView* pOLV=pTextEditOutliner->GetView(0); + if( pOLV ) + { + Window* pWin=pOLV->GetWindow(); + if (pText!=NULL && pText->IsTextFrame() && pOLV!=NULL && pWin!=NULL) { + USHORT nPixSiz=pOLV->GetInvalidateMore(); + Rectangle aEditArea(aMinTextEditArea); + aEditArea.Union(pOLV->GetOutputArea()); + if (!aEditArea.IsInside(rHit)) { + Size aSiz(pWin->PixelToLogic(Size(nPixSiz,nPixSiz))); + aEditArea.Left()-=aSiz.Width(); + aEditArea.Top()-=aSiz.Height(); + aEditArea.Right()+=aSiz.Width(); + aEditArea.Bottom()+=aSiz.Height(); + bOk=aEditArea.IsInside(rHit); + } + } + } + } + return bOk; +} + +void SdrObjEditView::AddTextEditOfs(MouseEvent& rMEvt) const +{ + if(mxTextEditObj.is()) + { + Point aPvOfs; + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() ); + + if( pTextObj ) + { + // #108784# + aPvOfs += pTextObj->GetTextEditOffset(); + } + + Point aObjOfs(mxTextEditObj->GetLogicRect().TopLeft()); + (Point&)(rMEvt.GetPosPixel())+=aPvOfs+aObjOfs; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrObjEditView::KeyInput(const KeyEvent& rKEvt, Window* pWin) +{ + if(pTextEditOutlinerView) + { +#ifdef DBG_UTIL + if(rKEvt.GetKeyCode().GetCode() == KEY_RETURN && pTextEditOutliner->GetParagraphCount() == 1) + { + ByteString aLine( + pTextEditOutliner->GetText(pTextEditOutliner->GetParagraph( 0 ), 1), + gsl_getSystemTextEncoding()); + aLine = aLine.ToUpperAscii(); + + if(aLine == "HELLO JOE, PLEASE SHOW THE ITEMBROWSER") + ShowItemBrowser(); + } +#endif + if (pTextEditOutlinerView->PostKeyEvent(rKEvt)) + { + if( pMod /* && !pMod->IsChanged() */ ) + { + if( pTextEditOutliner && pTextEditOutliner->IsModified() ) + pMod->SetChanged( sal_True ); + } + + if (pWin!=NULL && pWin!=pTextEditWin) SetTextEditWin(pWin); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + ImpMakeTextCursorAreaVisible(); + return TRUE; + } + } + return SdrGlueEditView::KeyInput(rKEvt,pWin); +} + +BOOL SdrObjEditView::MouseButtonDown(const MouseEvent& rMEvt, Window* pWin) +{ + if (pTextEditOutlinerView!=NULL) { + BOOL bPostIt=pTextEditOutliner->IsInSelectionMode(); + if (!bPostIt) { + Point aPt(rMEvt.GetPosPixel()); + if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt); + else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt); + bPostIt=IsTextEditHit(aPt,nHitTolLog); + } + if (bPostIt) { + Point aPixPos(rMEvt.GetPosPixel()); + Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea())); + if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left (); + if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right (); + if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top (); + if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom(); + MouseEvent aMEvt(aPixPos,rMEvt.GetClicks(),rMEvt.GetMode(), + rMEvt.GetButtons(),rMEvt.GetModifier()); + if (pTextEditOutlinerView->MouseButtonDown(aMEvt)) { + if (pWin!=NULL && pWin!=pTextEditWin) SetTextEditWin(pWin); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + ImpMakeTextCursorAreaVisible(); + return TRUE; + } + } + } + return SdrGlueEditView::MouseButtonDown(rMEvt,pWin); +} + +BOOL SdrObjEditView::MouseButtonUp(const MouseEvent& rMEvt, Window* pWin) +{ + if (pTextEditOutlinerView!=NULL) { + BOOL bPostIt=pTextEditOutliner->IsInSelectionMode(); + if (!bPostIt) { + Point aPt(rMEvt.GetPosPixel()); + if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt); + else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt); + bPostIt=IsTextEditHit(aPt,nHitTolLog); + } + if (bPostIt) { + Point aPixPos(rMEvt.GetPosPixel()); + Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea())); + if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left (); + if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right (); + if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top (); + if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom(); + MouseEvent aMEvt(aPixPos,rMEvt.GetClicks(),rMEvt.GetMode(), + rMEvt.GetButtons(),rMEvt.GetModifier()); + if (pTextEditOutlinerView->MouseButtonUp(aMEvt)) { +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + ImpMakeTextCursorAreaVisible(); + return TRUE; + } + } + } + return SdrGlueEditView::MouseButtonUp(rMEvt,pWin); +} + +BOOL SdrObjEditView::MouseMove(const MouseEvent& rMEvt, Window* pWin) +{ + if (pTextEditOutlinerView!=NULL) { + BOOL bSelMode=pTextEditOutliner->IsInSelectionMode(); + BOOL bPostIt=bSelMode; + if (!bPostIt) { + Point aPt(rMEvt.GetPosPixel()); + if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt); + else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt); + bPostIt=IsTextEditHit(aPt,nHitTolLog); + } + if (bPostIt) { + Point aPixPos(rMEvt.GetPosPixel()); + Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea())); + if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left (); + if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right (); + if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top (); + if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom(); + MouseEvent aMEvt(aPixPos,rMEvt.GetClicks(),rMEvt.GetMode(), + rMEvt.GetButtons(),rMEvt.GetModifier()); + if (pTextEditOutlinerView->MouseMove(aMEvt) && bSelMode) { +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + ImpMakeTextCursorAreaVisible(); + return TRUE; + } + } + } + return SdrGlueEditView::MouseMove(rMEvt,pWin); +} + +BOOL SdrObjEditView::Command(const CommandEvent& rCEvt, Window* pWin) +{ + // solange bis die OutlinerView einen BOOL zurueckliefert + // bekommt sie nur COMMAND_STARTDRAG + if (pTextEditOutlinerView!=NULL) + { + if (rCEvt.GetCommand()==COMMAND_STARTDRAG) { + BOOL bPostIt=pTextEditOutliner->IsInSelectionMode() || !rCEvt.IsMouseEvent(); + if (!bPostIt && rCEvt.IsMouseEvent()) { + Point aPt(rCEvt.GetMousePosPixel()); + if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt); + else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt); + bPostIt=IsTextEditHit(aPt,nHitTolLog); + } + if (bPostIt) { + Point aPixPos(rCEvt.GetMousePosPixel()); + if (rCEvt.IsMouseEvent()) { + Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea())); + if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left (); + if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right (); + if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top (); + if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom(); + } + CommandEvent aCEvt(aPixPos,rCEvt.GetCommand(),rCEvt.IsMouseEvent()); + // Command ist an der OutlinerView leider void + pTextEditOutlinerView->Command(aCEvt); + if (pWin!=NULL && pWin!=pTextEditWin) SetTextEditWin(pWin); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + ImpMakeTextCursorAreaVisible(); + return TRUE; + } + } + else // if (rCEvt.GetCommand() == COMMAND_VOICE ) + { + pTextEditOutlinerView->Command(rCEvt); + return TRUE; + } + } + return SdrGlueEditView::Command(rCEvt,pWin); +} + +BOOL SdrObjEditView::Cut(ULONG nFormat) +{ + if (pTextEditOutliner!=NULL) { + pTextEditOutlinerView->Cut(); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + ImpMakeTextCursorAreaVisible(); + return TRUE; + } else { + return SdrGlueEditView::Cut(nFormat); + } +} + +BOOL SdrObjEditView::Yank(ULONG nFormat) +{ + if (pTextEditOutliner!=NULL) { + pTextEditOutlinerView->Copy(); + return TRUE; + } else { + return SdrGlueEditView::Yank(nFormat); + } +} + +BOOL SdrObjEditView::Paste(Window* pWin, ULONG nFormat) +{ + if (pTextEditOutliner!=NULL) { + if (pWin!=NULL) { + OutlinerView* pNewView=ImpFindOutlinerView(pWin); + if (pNewView!=NULL) { + pNewView->Paste(); + } + } else { + pTextEditOutlinerView->Paste(); + } +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + ImpMakeTextCursorAreaVisible(); + return TRUE; + } else { + return SdrGlueEditView::Paste(pWin,nFormat); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrObjEditView::ImpIsTextEditAllSelected() const +{ + BOOL bRet=FALSE; + if (pTextEditOutliner!=NULL && pTextEditOutlinerView!=NULL) + { + if(SdrTextObj::HasTextImpl( pTextEditOutliner ) ) + { + const sal_uInt32 nParaAnz=pTextEditOutliner->GetParagraphCount(); + Paragraph* pLastPara=pTextEditOutliner->GetParagraph( nParaAnz > 1 ? nParaAnz - 1 : 0 ); + + ESelection aESel(pTextEditOutlinerView->GetSelection()); + if (aESel.nStartPara==0 && aESel.nStartPos==0 && aESel.nEndPara==USHORT(nParaAnz-1)) + { + XubString aStr(pTextEditOutliner->GetText(pLastPara)); + + if(aStr.Len() == aESel.nEndPos) + bRet = TRUE; + } + // und nun auch noch fuer den Fall, das rueckwaerts selektiert wurde + if (!bRet && aESel.nEndPara==0 && aESel.nEndPos==0 && aESel.nStartPara==USHORT(nParaAnz-1)) + { + XubString aStr(pTextEditOutliner->GetText(pLastPara)); + + if(aStr.Len() == aESel.nStartPos) + bRet = TRUE; + } + } + else + { + bRet=TRUE; + } + } + return bRet; +} + +void SdrObjEditView::ImpMakeTextCursorAreaVisible() +{ + if (pTextEditOutlinerView!=NULL && pTextEditWin!=NULL) { + Cursor* pCsr=pTextEditWin->GetCursor(); + if (pCsr!=NULL) { + Size aSiz(pCsr->GetSize()); + if (aSiz.Width()!=0 && aSiz.Height()!=0) { // #38450# + MakeVisible(Rectangle(pCsr->GetPos(),aSiz),*pTextEditWin); + } + } + } +} + +USHORT SdrObjEditView::GetScriptType() const +{ + USHORT nScriptType = 0; + + if( IsTextEdit() ) + { + if( mxTextEditObj->GetOutlinerParaObject() ) + nScriptType = mxTextEditObj->GetOutlinerParaObject()->GetTextObject().GetScriptType(); + + if( pTextEditOutlinerView ) + nScriptType = pTextEditOutlinerView->GetSelectedScriptType(); + } + else + { + sal_uInt32 nMarkCount( GetMarkedObjectCount() ); + + for( sal_uInt32 i = 0; i < nMarkCount; i++ ) + { + OutlinerParaObject* pParaObj = GetMarkedObjectByIndex( i )->GetOutlinerParaObject(); + + if( pParaObj ) + { + nScriptType |= pParaObj->GetTextObject().GetScriptType(); + } + } + } + + if( nScriptType == 0 ) + nScriptType = SCRIPTTYPE_LATIN; + + return nScriptType; +} + +/* new interface src537 */ +BOOL SdrObjEditView::GetAttributes(SfxItemSet& rTargetSet, BOOL bOnlyHardAttr) const +{ + if( mxSelectionController.is() ) + if( mxSelectionController->GetAttributes( rTargetSet, bOnlyHardAttr ) ) + return TRUE; + + if(IsTextEdit()) + { + DBG_ASSERT(pTextEditOutlinerView!=NULL,"SdrObjEditView::GetAttributes(): pTextEditOutlinerView=NULL"); + DBG_ASSERT(pTextEditOutliner!=NULL,"SdrObjEditView::GetAttributes(): pTextEditOutliner=NULL"); + + // #92389# take care of bOnlyHardAttr(!) + if(!bOnlyHardAttr && mxTextEditObj->GetStyleSheet()) + rTargetSet.Put(mxTextEditObj->GetStyleSheet()->GetItemSet()); + + // add object attributes + rTargetSet.Put( mxTextEditObj->GetMergedItemSet() ); + + if( mxTextEditObj->GetOutlinerParaObject() ) + rTargetSet.Put( SvxScriptTypeItem( mxTextEditObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) ); + + if(pTextEditOutlinerView) + { + // FALSE= InvalidItems nicht al Default, sondern als "Loecher" betrachten + rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), FALSE); + rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ), FALSE ); + } + + if(GetMarkedObjectCount()==1 && GetMarkedObjectByIndex(0)==mxTextEditObj.get()) + { + MergeNotPersistAttrFromMarked(rTargetSet, bOnlyHardAttr); + } + + return TRUE; + } + else + { + return SdrGlueEditView::GetAttributes(rTargetSet, bOnlyHardAttr); + } +} + +BOOL SdrObjEditView::SetAttributes(const SfxItemSet& rSet, BOOL bReplaceAll) +{ + BOOL bRet=FALSE; + BOOL bTextEdit=pTextEditOutlinerView!=NULL && mxTextEditObj.is(); + BOOL bAllTextSelected=ImpIsTextEditAllSelected(); + SfxItemSet* pModifiedSet=NULL; + const SfxItemSet* pSet=&rSet; + //const SvxAdjustItem* pParaJust=NULL; + + if (!bTextEdit) + { + // Kein TextEdit aktiv -> alle Items ans Zeichenobjekt + if( mxSelectionController.is() ) + bRet=mxSelectionController->SetAttributes(*pSet,bReplaceAll ); + + if( !bRet ) + { + bRet=SdrGlueEditView::SetAttributes(*pSet,bReplaceAll); + } + } + else + { +#ifdef DBG_UTIL + { + BOOL bHasEEFeatureItems=FALSE; + SfxItemIter aIter(rSet); + const SfxPoolItem* pItem=aIter.FirstItem(); + while (!bHasEEFeatureItems && pItem!=NULL) + { + if (!IsInvalidItem(pItem)) + { + USHORT nW=pItem->Which(); + if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) + bHasEEFeatureItems=TRUE; + } + + pItem=aIter.NextItem(); + } + + if(bHasEEFeatureItems) + { + String aMessage; + aMessage.AppendAscii("SdrObjEditView::SetAttributes(): Das setzen von EE_FEATURE-Items an der SdrView macht keinen Sinn! Es fuehrt nur zu Overhead und nicht mehr lesbaren Dokumenten."); + InfoBox(NULL, aMessage).Execute(); + } + } +#endif + + BOOL bOnlyEEItems; + BOOL bNoEEItems=!SearchOutlinerItems(*pSet,bReplaceAll,&bOnlyEEItems); + // alles selektiert? -> Attrs auch an den Rahmen + // und falls keine EEItems, dann Attrs nur an den Rahmen + if (bAllTextSelected || bNoEEItems) + { + if( mxSelectionController.is() ) + bRet=mxSelectionController->SetAttributes(*pSet,bReplaceAll ); + + if( !bRet ) + { + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + { + String aStr; + ImpTakeDescriptionStr(STR_EditSetAttributes,aStr); + BegUndo(aStr); + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*mxTextEditObj.get())); + + // #i43537# + // If this is a text object also rescue the OutlinerParaObject since + // applying attributes to the object may change text layout when + // multiple portions exist with multiple formats. If a OutlinerParaObject + // really exists and needs to be rescued is evaluated in the undo + // implementation itself. + bool bRescueText = dynamic_cast< SdrTextObj* >(mxTextEditObj.get()); + + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*mxTextEditObj.get(),false,!bNoEEItems || bRescueText)); + EndUndo(); + } + + mxTextEditObj->SetMergedItemSetAndBroadcast(*pSet, bReplaceAll); + + FlushComeBackTimer(); // Damit ModeHasChanged sofort kommt + bRet=TRUE; + } + } + else if (!bOnlyEEItems) + { + // sonst Set ggf. splitten + // Es wird nun ein ItemSet aSet gemacht, in den die EE_Items von + // *pSet nicht enhalten ist (ansonsten ist es eine Kopie). + USHORT* pNewWhichTable=RemoveWhichRange(pSet->GetRanges(),EE_ITEMS_START,EE_ITEMS_END); + SfxItemSet aSet(pMod->GetItemPool(),pNewWhichTable); + /*90353*/ delete[] pNewWhichTable; + SfxWhichIter aIter(aSet); + USHORT nWhich=aIter.FirstWhich(); + while (nWhich!=0) + { + const SfxPoolItem* pItem; + SfxItemState eState=pSet->GetItemState(nWhich,FALSE,&pItem); + if (eState==SFX_ITEM_SET) aSet.Put(*pItem); + nWhich=aIter.NextWhich(); + } + + + if( mxSelectionController.is() ) + bRet=mxSelectionController->SetAttributes(aSet,bReplaceAll ); + + if( !bRet ) + { + if( IsUndoEnabled() ) + { + String aStr; + ImpTakeDescriptionStr(STR_EditSetAttributes,aStr); + BegUndo(aStr); + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*mxTextEditObj.get())); + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*mxTextEditObj.get(),false,false)); + EndUndo(); + } + + mxTextEditObj->SetMergedItemSetAndBroadcast(aSet, bReplaceAll); + + if (GetMarkedObjectCount()==1 && GetMarkedObjectByIndex(0)==mxTextEditObj.get()) + { + SetNotPersistAttrToMarked(aSet,bReplaceAll); + } + } + FlushComeBackTimer(); + bRet=TRUE; + } + if(!bNoEEItems) + { + // und nun die Attribute auch noch an die EditEngine + if (bReplaceAll) { + // Am Outliner kann man leider nur alle Attribute platthauen + pTextEditOutlinerView->RemoveAttribs( TRUE ); + } + pTextEditOutlinerView->SetAttribs(rSet); + +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) + pItemBrowser->SetDirty(); +#endif + + ImpMakeTextCursorAreaVisible(); + } + bRet=TRUE; + } + if (pModifiedSet!=NULL) + delete pModifiedSet; + return bRet; +} + +SfxStyleSheet* SdrObjEditView::GetStyleSheet() const +{ + SfxStyleSheet* pSheet = 0; + + if( mxSelectionController.is() ) + { + if( mxSelectionController->GetStyleSheet( pSheet ) ) + return pSheet; + } + + if ( pTextEditOutlinerView ) + { + pSheet = pTextEditOutlinerView->GetStyleSheet(); + } + else + { + pSheet = SdrGlueEditView::GetStyleSheet(); + } + return pSheet; +} + +BOOL SdrObjEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, BOOL bDontRemoveHardAttr) +{ + if( mxSelectionController.is() ) + { + if( mxSelectionController->SetStyleSheet( pStyleSheet, bDontRemoveHardAttr ) ) + return TRUE; + } + + // if we are currently in edit mode we must also set the stylesheet + // on all paragraphs in the Outliner for the edit view + // #92191# + if( NULL != pTextEditOutlinerView ) + { + Outliner* pOutliner = pTextEditOutlinerView->GetOutliner(); + + const ULONG nParaCount = pOutliner->GetParagraphCount(); + ULONG nPara; + for( nPara = 0; nPara < nParaCount; nPara++ ) + { + pOutliner->SetStyleSheet( nPara, pStyleSheet ); + } + } + + return SdrGlueEditView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObjEditView::AddWindowToPaintView(OutputDevice* pNewWin) +{ + SdrGlueEditView::AddWindowToPaintView(pNewWin); + + if(mxTextEditObj.is() && !bTextEditOnlyOneView && pNewWin->GetOutDevType()==OUTDEV_WINDOW) + { + OutlinerView* pOutlView=ImpMakeOutlinerView((Window*)pNewWin,FALSE,NULL); + pTextEditOutliner->InsertView(pOutlView); + } +} + +void SdrObjEditView::DeleteWindowFromPaintView(OutputDevice* pOldWin) +{ + SdrGlueEditView::DeleteWindowFromPaintView(pOldWin); + + if(mxTextEditObj.is() && !bTextEditOnlyOneView && pOldWin->GetOutDevType()==OUTDEV_WINDOW) + { + for (ULONG i=pTextEditOutliner->GetViewCount(); i>0;) { + i--; + OutlinerView* pOLV=pTextEditOutliner->GetView(i); + if (pOLV && pOLV->GetWindow()==(Window*)pOldWin) { + delete pTextEditOutliner->RemoveView(i); + } + } + } +} + +BOOL SdrObjEditView::IsTextEditInSelectionMode() const +{ + return pTextEditOutliner!=NULL && pTextEditOutliner->IsInSelectionMode(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@ @@ @@@@ @@@@ @@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ +// @@@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@@ @@ @@ @@ @@ @@ +// @@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@@@@@@ @@ @@ @@ @@ @@ +// @@@@@@@ @@@@@@ @@ @@@@@ @@ @@ @@@@@@@ @@ @@ @@ @@ @@@@ +// @@ @ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@@@ @@ @@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrObjEditView::BegMacroObj(const Point& rPnt, short nTol, SdrObject* pObj, SdrPageView* pPV, Window* pWin) +{ + BOOL bRet=FALSE; + BrkMacroObj(); + if (pObj!=NULL && pPV!=NULL && pWin!=NULL && pObj->HasMacro()) { + nTol=ImpGetHitTolLogic(nTol,NULL); + pMacroObj=pObj; + pMacroPV=pPV; + pMacroWin=pWin; + bMacroDown=FALSE; + nMacroTol=USHORT(nTol); + aMacroDownPos=rPnt; + MovMacroObj(rPnt); + } + return bRet; +} + +void SdrObjEditView::ImpMacroUp(const Point& rUpPos) +{ + if (pMacroObj!=NULL && bMacroDown) + { + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=rUpPos; + aHitRec.aDownPos=aMacroDownPos; + aHitRec.nTol=nMacroTol; + aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers(); + aHitRec.pPageView=pMacroPV; + aHitRec.pOut=pMacroWin; + pMacroObj->PaintMacro(*pMacroWin,Rectangle(),aHitRec); + bMacroDown=FALSE; + } +} + +void SdrObjEditView::ImpMacroDown(const Point& rDownPos) +{ + if (pMacroObj!=NULL && !bMacroDown) + { + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=rDownPos; + aHitRec.aDownPos=aMacroDownPos; + aHitRec.nTol=nMacroTol; + aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers(); + aHitRec.pPageView=pMacroPV; + aHitRec.bDown=TRUE; + aHitRec.pOut=pMacroWin; + pMacroObj->PaintMacro(*pMacroWin,Rectangle(),aHitRec); + bMacroDown=TRUE; + } +} + +void SdrObjEditView::MovMacroObj(const Point& rPnt) +{ + if (pMacroObj!=NULL) { + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=rPnt; + aHitRec.aDownPos=aMacroDownPos; + aHitRec.nTol=nMacroTol; + aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers(); + aHitRec.pPageView=pMacroPV; + aHitRec.bDown=bMacroDown; + aHitRec.pOut=pMacroWin; + BOOL bDown=pMacroObj->IsMacroHit(aHitRec); + if (bDown) ImpMacroDown(rPnt); + else ImpMacroUp(rPnt); + } +} + +void SdrObjEditView::BrkMacroObj() +{ + if (pMacroObj!=NULL) { + ImpMacroUp(aMacroDownPos); + pMacroObj=NULL; + pMacroPV=NULL; + pMacroWin=NULL; + } +} + +BOOL SdrObjEditView::EndMacroObj() +{ + if (pMacroObj!=NULL && bMacroDown) { + ImpMacroUp(aMacroDownPos); + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=aMacroDownPos; + aHitRec.aDownPos=aMacroDownPos; + aHitRec.nTol=nMacroTol; + aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers(); + aHitRec.pPageView=pMacroPV; + aHitRec.bDown=TRUE; + aHitRec.pOut=pMacroWin; + bool bRet=pMacroObj->DoMacro(aHitRec); + pMacroObj=NULL; + pMacroPV=NULL; + pMacroWin=NULL; + return bRet; + } else { + BrkMacroObj(); + return FALSE; + } +} + +/** fills the given any with a XTextCursor for the current text selection. + Leaves the any untouched if there currently is no text selected */ +void SdrObjEditView::getTextSelection( ::com::sun::star::uno::Any& rSelection ) +{ + if( IsTextEdit() ) + { + OutlinerView* pOutlinerView = GetTextEditOutlinerView(); + if( pOutlinerView && pOutlinerView->HasSelection() ) + { + SdrObject* pObj = GetTextEditObject(); + + if( pObj ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::text::XText > xText( pObj->getUnoShape(), ::com::sun::star::uno::UNO_QUERY ); + if( xText.is() ) + { + SvxUnoTextBase* pRange = SvxUnoTextBase::getImplementation( xText ); + if( pRange ) + { + rSelection <<= pRange->createTextCursorBySelection( pOutlinerView->GetSelection() ); + } + } + } + } + } +} + +namespace sdr { namespace table { +extern rtl::Reference< sdr::SelectionController > CreateTableController( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController ); +} } + +/* check if we have a single selection and that single object likes + to handle the mouse and keyboard events itself + + @todo: the selection controller should be queried from the + object specific view contact. Currently this method only + works for tables. +*/ +void SdrObjEditView::MarkListHasChanged() +{ + SdrGlueEditView::MarkListHasChanged(); + + if( mxSelectionController.is() ) + { + mxLastSelectionController = mxSelectionController; + mxSelectionController->onSelectionHasChanged(); + } + + mxSelectionController.clear(); + + const SdrMarkList& rMarkList=GetMarkedObjectList(); + if( rMarkList.GetMarkCount() == 1 ) + { + const SdrObject* pObj= rMarkList.GetMark(0)->GetMarkedSdrObj(); + // check for table + if( pObj && (pObj->GetObjInventor() == SdrInventor ) && (pObj->GetObjIdentifier() == OBJ_TABLE) ) + { + mxSelectionController = sdr::table::CreateTableController( this, pObj, mxLastSelectionController ); + if( mxSelectionController.is() ) + { + mxLastSelectionController.clear(); + mxSelectionController->onSelectionHasChanged(); + } + } + } +} + +IMPL_LINK( SdrObjEditView, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos ) +{ + OnEndPasteOrDrop( pInfos ); + return 0; +} + +IMPL_LINK( SdrObjEditView, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos ) +{ + OnBeginPasteOrDrop( pInfos ); + return 0; +} + +void SdrObjEditView::OnBeginPasteOrDrop( PasteOrDropInfos* ) +{ + // applications can derive from these virtual methods to do something before a drop or paste operation +} + +void SdrObjEditView::OnEndPasteOrDrop( PasteOrDropInfos* ) +{ + // applications can derive from these virtual methods to do something before a drop or paste operation +} + +bool SdrObjEditView::SupportsFormatPaintbrush( UINT32 nObjectInventor, UINT16 nObjectIdentifier ) const +{ + if( nObjectInventor != SdrInventor && nObjectInventor != E3dInventor ) + return false; + switch(nObjectIdentifier) + { + case OBJ_NONE: + case OBJ_GRUP: + return false; + case OBJ_LINE: + case OBJ_RECT: + case OBJ_CIRC: + case OBJ_SECT: + case OBJ_CARC: + case OBJ_CCUT: + case OBJ_POLY: + case OBJ_PLIN: + case OBJ_PATHLINE: + case OBJ_PATHFILL: + case OBJ_FREELINE: + case OBJ_FREEFILL: + case OBJ_SPLNLINE: + case OBJ_SPLNFILL: + case OBJ_TEXT: + case OBJ_TEXTEXT: + case OBJ_TITLETEXT: + case OBJ_OUTLINETEXT: + case OBJ_GRAF: + case OBJ_OLE2: + case OBJ_TABLE: + return true; + case OBJ_EDGE: + case OBJ_CAPTION: + return false; + case OBJ_PATHPOLY: + case OBJ_PATHPLIN: + return true; + case OBJ_PAGE: + case OBJ_MEASURE: + case OBJ_DUMMY: + case OBJ_FRAME: + case OBJ_UNO: + return false; + case OBJ_CUSTOMSHAPE: + return true; + default: + return false; + } +} + +static const USHORT* GetFormatRangeImpl( bool bTextOnly ) +{ + static const USHORT gRanges[] = { + SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, + SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST, + SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST, + XATTR_LINE_FIRST, XATTR_LINE_LAST, + XATTR_FILL_FIRST, XATTRSET_FILL, + EE_PARA_START, EE_PARA_END, + EE_CHAR_START, EE_CHAR_END, + 0,0 + }; + return &gRanges[ bTextOnly ? 10 : 0]; +} + +bool SdrObjEditView::TakeFormatPaintBrush( boost::shared_ptr< SfxItemSet >& rFormatSet ) +{ + if( mxSelectionController.is() && mxSelectionController->TakeFormatPaintBrush(rFormatSet) ) + return true; + + const SdrMarkList& rMarkList = GetMarkedObjectList(); + if( rMarkList.GetMarkCount() >= 1 ) + { + OutlinerView* pOLV = GetTextEditOutlinerView(); + + rFormatSet.reset( new SfxItemSet( GetModel()->GetItemPool(), GetFormatRangeImpl( pOLV != NULL ) ) ); + if( pOLV ) + { + rFormatSet->Put( pOLV->GetAttribs() ); + } + else + { + const BOOL bOnlyHardAttr = FALSE; + rFormatSet->Put( GetAttrFromMarked(bOnlyHardAttr) ); + } + return true; + } + + return false; +} + +static SfxItemSet CreatePaintSet( const USHORT *pRanges, SfxItemPool& rPool, const SfxItemSet& rSourceSet, const SfxItemSet& rTargetSet, bool bNoCharacterFormats, bool bNoParagraphFormats ) +{ + SfxItemSet aPaintSet( rPool, pRanges ); + + while( *pRanges ) + { + USHORT nWhich = *pRanges++; + const USHORT nLastWhich = *pRanges++; + + if( bNoCharacterFormats && (nWhich == EE_CHAR_START) ) + continue; + + if( bNoParagraphFormats && (nWhich == EE_PARA_START ) ) + continue; + + for( ; nWhich < nLastWhich; nWhich++ ) + { + const SfxPoolItem* pSourceItem = rSourceSet.GetItem( nWhich ); + const SfxPoolItem* pTargetItem = rTargetSet.GetItem( nWhich ); + + if( (pSourceItem && !pTargetItem) || (pSourceItem && pTargetItem && !((*pSourceItem) == (*pTargetItem)) ) ) + { + aPaintSet.Put( *pSourceItem ); + } + } + } + return aPaintSet; +} + +void SdrObjEditView::ApplyFormatPaintBrushToText( SfxItemSet& rFormatSet, SdrTextObj& rTextObj, SdrText* pText, bool bNoCharacterFormats, bool bNoParagraphFormats ) +{ + OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : 0; + if(pParaObj) + { + SdrOutliner& rOutliner = rTextObj.ImpGetDrawOutliner(); + rOutliner.SetText(*pParaObj); + + sal_uInt32 nParaCount(rOutliner.GetParagraphCount()); + + if(nParaCount) + { + for(sal_uInt16 nPara = 0; nPara < nParaCount; nPara++) + { + if( !bNoCharacterFormats ) + rOutliner.QuickRemoveCharAttribs( nPara, /* remove all */0 ); + + SfxItemSet aSet(rOutliner.GetParaAttribs(nPara)); + aSet.Put(CreatePaintSet( GetFormatRangeImpl(true), *aSet.GetPool(), rFormatSet, aSet, bNoCharacterFormats, bNoParagraphFormats ) ); + rOutliner.SetParaAttribs(nPara, aSet); + } + + OutlinerParaObject* pTemp = rOutliner.CreateParaObject(0, (sal_uInt16)nParaCount); + rOutliner.Clear(); + + rTextObj.NbcSetOutlinerParaObjectForText(pTemp,pText); + } + } +} + +void SdrObjEditView::ApplyFormatPaintBrush( SfxItemSet& rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats ) +{ + if( !mxSelectionController.is() || !mxSelectionController->ApplyFormatPaintBrush( rFormatSet, bNoCharacterFormats, bNoParagraphFormats ) ) + { + const SdrMarkList& rMarkList = GetMarkedObjectList(); + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + OutlinerView* pOLV = GetTextEditOutlinerView(); + + const SfxItemSet& rShapeSet = pObj->GetMergedItemSet(); + + if( !pOLV ) + { + // if not in text edit mode (aka the user selected text or clicked on a word) + // apply formating attributes to selected shape + // All formating items (see ranges above) that are unequal in selected shape and + // the format paintbrush are hard set on the selected shape. + + const USHORT* pRanges = rFormatSet.GetRanges(); + bool bTextOnly = true; + + while( *pRanges ) + { + if( (*pRanges != EE_PARA_START) && (*pRanges != EE_CHAR_START) ) + { + bTextOnly = false; + break; + } + pRanges += 2; + } + + if( !bTextOnly ) + { + SfxItemSet aPaintSet( CreatePaintSet( GetFormatRangeImpl(false), *rShapeSet.GetPool(), rFormatSet, rShapeSet, bNoCharacterFormats, bNoParagraphFormats ) ); + const BOOL bReplaceAll = FALSE; + SetAttrToMarked(aPaintSet, bReplaceAll); + } + + // now apply character and paragraph formating to text, if the shape has any + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(pObj); + if( pTextObj ) + { + sal_Int32 nText = pTextObj->getTextCount(); + + while( --nText >= 0 ) + { + SdrText* pText = pTextObj->getText( nText ); + ApplyFormatPaintBrushToText( rFormatSet, *pTextObj, pText, bNoCharacterFormats, bNoParagraphFormats ); + } + } + } + else + { + ::Outliner* pOutliner = pOLV->GetOutliner(); + if( pOutliner ) + { + const EditEngine& rEditEngine = pOutliner->GetEditEngine(); + + ESelection aSel( pOLV->GetSelection() ); + if( !aSel.HasRange() ) + pOLV->SetSelection( rEditEngine.GetWord( aSel, com::sun::star::i18n::WordType::DICTIONARY_WORD ) ); + + const BOOL bRemoveParaAttribs = !bNoParagraphFormats; + pOLV->RemoveAttribsKeepLanguages( bRemoveParaAttribs ); + SfxItemSet aSet( pOLV->GetAttribs() ); + SfxItemSet aPaintSet( CreatePaintSet(GetFormatRangeImpl(true), *aSet.GetPool(), rFormatSet, aSet, bNoCharacterFormats, bNoParagraphFormats ) ); + pOLV->SetAttribs( aPaintSet ); + } + } + } +} diff --git a/svx/source/svdraw/svdetc.cxx b/svx/source/svdraw/svdetc.cxx new file mode 100644 index 000000000000..8a4245919821 --- /dev/null +++ b/svx/source/svdraw/svdetc.cxx @@ -0,0 +1,1118 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include "editeng/forbiddencharacterstable.hxx" +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <svx/svdetc.hxx> +#include "svditext.hxx" +#include <svx/svdmodel.hxx> +#include <svx/svdtrans.hxx> +#include "svdglob.hxx" +#include "svdstr.hrc" +#include "svdviter.hxx" +#include <svx/svdview.hxx> +#include <svx/svdoutl.hxx> +#include <vcl/bmpacc.hxx> +#include <editeng/eeitem.hxx> +#include <svl/itemset.hxx> +#include <tools/config.hxx> +#include <unotools/cacheoptions.hxx> +#include <svl/whiter.hxx> +#include <tools/bigint.hxx> +#include "editeng/fontitem.hxx" +#include <editeng/colritem.hxx> +#include <editeng/fhgtitem.hxx> +#include <svx/xgrad.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/svdoole2.hxx> +#include <svl/itempool.hxx> +#include <unotools/localedatawrapper.hxx> +#include <com/sun/star/lang/Locale.hpp> +#include <comphelper/processfactory.hxx> +#include <i18npool/lang.h> +#include <unotools/charclass.hxx> +#include <unotools/syslocale.hxx> +#include <svx/xflbckit.hxx> +#include <svx/extrusionbar.hxx> +#include <svx/fontworkbar.hxx> +#include <vcl/svapp.hxx> //add CHINA001 +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdotable.hxx> +#include <svx/sdrhittesthelper.hxx> + +using namespace ::com::sun::star; + +/****************************************************************************** +* Globale Daten der DrawingEngine +******************************************************************************/ + +SdrGlobalData::SdrGlobalData() : + pSysLocale(NULL), + pCharClass(NULL), + pLocaleData(NULL), + pOutliner(NULL), + pDefaults(NULL), + pResMgr(NULL), + nExchangeFormat(0) +{ + //pSysLocale = new SvtSysLocale; + //pCharClass = pSysLocale->GetCharClassPtr(); + //pLocaleData = pSysLocale->GetLocaleDataPtr(); + + svx::ExtrusionBar::RegisterInterface(); + svx::FontworkBar::RegisterInterface(); +} + +SdrGlobalData::~SdrGlobalData() +{ + delete pOutliner; + delete pDefaults; + delete pResMgr; + //! do NOT delete pCharClass and pLocaleData + delete pSysLocale; +} +const SvtSysLocale* SdrGlobalData::GetSysLocale() +{ + if ( !pSysLocale ) + pSysLocale = new SvtSysLocale; + return pSysLocale; +} +const CharClass* SdrGlobalData::GetCharClass() +{ + if ( !pCharClass ) + pCharClass = GetSysLocale()->GetCharClassPtr(); + return pCharClass; +} +const LocaleDataWrapper* SdrGlobalData::GetLocaleData() +{ + if ( !pLocaleData ) + pLocaleData = GetSysLocale()->GetLocaleDataPtr(); + return pLocaleData; +} +//////////////////////////////////////////////////////////////////////////////////////////////////// + +OLEObjCache::OLEObjCache() +: Container( 0 ) +{ + SvtCacheOptions aCacheOptions; + + nSize = aCacheOptions.GetDrawingEngineOLE_Objects(); + pTimer = new AutoTimer(); + Link aLink = LINK(this, OLEObjCache, UnloadCheckHdl); + + pTimer->SetTimeoutHdl(aLink); + pTimer->SetTimeout(20000); + pTimer->Start(); + + aLink.Call(pTimer); +} + +OLEObjCache::~OLEObjCache() +{ + pTimer->Stop(); + delete pTimer; +} + +void OLEObjCache::UnloadOnDemand() +{ + if ( nSize < Count() ) + { + // more objects than configured cache size try to remove objects + // of course not the freshly inserted one at nIndex=0 + ULONG nCount2 = Count(); + ULONG nIndex = nCount2-1; + while( nIndex && nCount2 > nSize ) + { + SdrOle2Obj* pUnloadObj = (SdrOle2Obj*) GetObject(nIndex--); + if ( pUnloadObj ) + { + try + { + // it is important to get object without reinitialization to avoid reentrance + uno::Reference< embed::XEmbeddedObject > xUnloadObj = pUnloadObj->GetObjRef_NoInit(); + + sal_Bool bUnload = SdrOle2Obj::CanUnloadRunningObj( xUnloadObj, pUnloadObj->GetAspect() ); + + // check whether the object can be unloaded before looking for the parent objects + if ( xUnloadObj.is() && bUnload ) + { + uno::Reference< frame::XModel > xUnloadModel( xUnloadObj->getComponent(), uno::UNO_QUERY ); + if ( xUnloadModel.is() ) + { + for ( ULONG nCheckInd = 0; nCheckInd < Count(); nCheckInd++ ) + { + SdrOle2Obj* pCacheObj = (SdrOle2Obj*) GetObject(nCheckInd); + if ( pCacheObj && pCacheObj != pUnloadObj ) + { + uno::Reference< frame::XModel > xParentModel = pCacheObj->GetParentXModel(); + if ( xUnloadModel == xParentModel ) + bUnload = sal_False; // the object has running embedded objects + } + } + } + } + + if ( bUnload && UnloadObj(pUnloadObj) ) + // object was successfully unloaded + nCount2--; + } + catch( uno::Exception& ) + {} + } + } + } +} + +void OLEObjCache::SetSize(ULONG nNewSize) +{ + nSize = nNewSize; +} + +void OLEObjCache::InsertObj(SdrOle2Obj* pObj) +{ + if ( Count() ) + { + SdrOle2Obj* pExistingObj = (SdrOle2Obj*)GetObject( 0 ); + if ( pObj == pExistingObj ) + // the object is already on the top, nothing has to be changed + return; + } + + // get the old position of the object to know whether it is already in container + ULONG nOldPos = GetPos( pObj ); + + // insert object into first position + Remove( nOldPos ); + Insert(pObj, (ULONG) 0L); + + if ( nOldPos == CONTAINER_ENTRY_NOTFOUND ) + { + // a new object was inserted, recalculate the cache + UnloadOnDemand(); + } +} + +void OLEObjCache::RemoveObj(SdrOle2Obj* pObj) +{ + Remove(pObj); +} + +BOOL OLEObjCache::UnloadObj(SdrOle2Obj* pObj) +{ + BOOL bUnloaded = FALSE; + if (pObj) + { + //#i80528# The old mechanism is completely useless, only taking into account if + // in all views the GrafDraft feature is used. This will nearly never have been the + // case since no one ever used this option. + // + // A much better (and working) criteria would be the VOC contact count. + // The quesion is what will happen whe i make it work now suddenly? I + // will try it for 2.4. + const sdr::contact::ViewContact& rViewContact = pObj->GetViewContact(); + const bool bVisible(rViewContact.HasViewObjectContacts(true)); + + if(!bVisible) + { + bUnloaded = pObj->Unload(); + } + } + + return bUnloaded; +} + +IMPL_LINK(OLEObjCache, UnloadCheckHdl, AutoTimer*, /*pTim*/) +{ + UnloadOnDemand(); + return 0; +} + +void ContainerSorter::DoSort(ULONG a, ULONG b) const +{ + ULONG nAnz=rCont.Count(); + if (b>nAnz) b=nAnz; + if (b>0) b--; + if (a<b) ImpSubSort(a,b); +} + +void ContainerSorter::Is1stLessThan2nd(const void* /*pElem1*/, const void* /*pElem2*/) const +{ +} + +void ContainerSorter::ImpSubSort(long nL, long nR) const +{ + long i,j; + const void* pX; + void* pI; + void* pJ; + i=nL; + j=nR; + pX=rCont.GetObject((nL+nR)/2); + do { + pI=rCont.Seek(i); + while (pI!=pX && Compare(pI,pX)<0) { i++; pI=rCont.Next(); } + pJ=rCont.Seek(j); + while (pJ!=pX && Compare(pX,pJ)<0) { j--; pJ=rCont.Prev(); } + if (i<=j) { + rCont.Replace(pJ,i); + rCont.Replace(pI,j); + i++; + j--; + } + } while (i<=j); + if (nL<j) ImpSubSort(nL,j); + if (i<nR) ImpSubSort(i,nR); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpUShortContainerSorter: public ContainerSorter { +public: + ImpUShortContainerSorter(Container& rNewCont): ContainerSorter(rNewCont) {} + virtual int Compare(const void* pElem1, const void* pElem2) const; +}; + +int ImpUShortContainerSorter::Compare(const void* pElem1, const void* pElem2) const +{ + USHORT n1=USHORT(ULONG(pElem1)); + USHORT n2=USHORT(ULONG(pElem2)); + return n1<n2 ? -1 : n1>n2 ? 1 : 0; +} + +void UShortCont::Sort() +{ + ImpUShortContainerSorter aSorter(aArr); + aSorter.DoSort(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpClipMerk { + Region aClip; + FASTBOOL bClip; +public: + ImpClipMerk(const OutputDevice& rOut): aClip(rOut.GetClipRegion()),bClip(rOut.IsClipRegion()) {} + void Restore(OutputDevice& rOut) + { + // Kein Clipping in die Metafileaufzeichnung + GDIMetaFile* pMtf=rOut.GetConnectMetaFile(); + if (pMtf!=NULL && (!pMtf->IsRecord() || pMtf->IsPause())) pMtf=NULL; + if (pMtf!=NULL) pMtf->Pause(TRUE); + if (bClip) rOut.SetClipRegion(aClip); + else rOut.SetClipRegion(); + if (pMtf!=NULL) pMtf->Pause(FALSE); + } +}; + +class ImpColorMerk { + Color aLineColor; + Color aFillColor; + Color aBckgrdColor; + Font aFont; +public: + ImpColorMerk(const OutputDevice& rOut): + aLineColor( rOut.GetLineColor() ), + aFillColor( rOut.GetFillColor() ), + aBckgrdColor( rOut.GetBackground().GetColor() ), + aFont (rOut.GetFont()) {} + + ImpColorMerk(const OutputDevice& rOut, USHORT nMode) + { + if ( (nMode & SDRHDC_SAVEPEN) == SDRHDC_SAVEPEN ) + aLineColor = rOut.GetLineColor(); + + if ( (nMode & SDRHDC_SAVEBRUSH) == SDRHDC_SAVEBRUSH) + { + aFillColor = rOut.GetFillColor(); + aBckgrdColor = rOut.GetBackground().GetColor(); + } + + if ( (nMode & SDRHDC_SAVEFONT) == SDRHDC_SAVEFONT) + aFont=rOut.GetFont(); + } + + void Restore(OutputDevice& rOut, USHORT nMode=SDRHDC_SAVEPENANDBRUSHANDFONT) + { + if ( (nMode & SDRHDC_SAVEPEN) == SDRHDC_SAVEPEN) + rOut.SetLineColor( aLineColor ); + + if ( (nMode & SDRHDC_SAVEBRUSH) == SDRHDC_SAVEBRUSH) + { + rOut.SetFillColor( aFillColor ); + rOut.SetBackground( Wallpaper( aBckgrdColor ) ); + } + if ((nMode & SDRHDC_SAVEFONT) ==SDRHDC_SAVEFONT) + { + if (!rOut.GetFont().IsSameInstance(aFont)) + { + rOut.SetFont(aFont); + } + } + } + + const Color& GetLineColor() const { return aLineColor; } +}; + +ImpSdrHdcMerk::ImpSdrHdcMerk(const OutputDevice& rOut, USHORT nNewMode, FASTBOOL bAutoMerk): + pFarbMerk(NULL), + pClipMerk(NULL), + pLineColorMerk(NULL), + nMode(nNewMode) +{ + if (bAutoMerk) Save(rOut); +} + +ImpSdrHdcMerk::~ImpSdrHdcMerk() +{ + if (pFarbMerk!=NULL) delete pFarbMerk; + if (pClipMerk!=NULL) delete pClipMerk; + if (pLineColorMerk !=NULL) delete pLineColorMerk; +} + +void ImpSdrHdcMerk::Save(const OutputDevice& rOut) +{ + if (pFarbMerk!=NULL) + { + delete pFarbMerk; + pFarbMerk=NULL; + } + if (pClipMerk!=NULL) + { + delete pClipMerk; + pClipMerk=NULL; + } + if (pLineColorMerk !=NULL) + { + delete pLineColorMerk ; + pLineColorMerk =NULL; + } + if ((nMode & SDRHDC_SAVECLIPPING) ==SDRHDC_SAVECLIPPING) + pClipMerk=new ImpClipMerk(rOut); + + USHORT nCol=nMode & SDRHDC_SAVEPENANDBRUSHANDFONT; + + if (nCol==SDRHDC_SAVEPEN) + pLineColorMerk=new Color( rOut.GetLineColor() ); + else if (nCol==SDRHDC_SAVEPENANDBRUSHANDFONT) + pFarbMerk=new ImpColorMerk(rOut); + else if (nCol!=0) + pFarbMerk=new ImpColorMerk(rOut,nCol); +} + +void ImpSdrHdcMerk::Restore(OutputDevice& rOut, USHORT nMask) const +{ + nMask&=nMode; // nur restaurieren, was auch gesichert wurde + + if ((nMask & SDRHDC_SAVECLIPPING) ==SDRHDC_SAVECLIPPING && pClipMerk!=NULL) + pClipMerk->Restore(rOut); + + USHORT nCol=nMask & SDRHDC_SAVEPENANDBRUSHANDFONT; + + if (nCol==SDRHDC_SAVEPEN) + { + if (pLineColorMerk!=NULL) + rOut.SetLineColor(*pLineColorMerk); + else if (pFarbMerk!=NULL) + rOut.SetLineColor( pFarbMerk->GetLineColor() ); + } else if (nCol!=0 && pFarbMerk!=NULL) + pFarbMerk->Restore(rOut,nCol); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrLinkList::Clear() +{ + unsigned nAnz=GetLinkCount(); + for (unsigned i=0; i<nAnz; i++) { + delete (Link*)aList.GetObject(i); + } + aList.Clear(); +} + +unsigned SdrLinkList::FindEntry(const Link& rLink) const +{ + unsigned nAnz=GetLinkCount(); + for (unsigned i=0; i<nAnz; i++) { + if (GetLink(i)==rLink) return i; + } + return 0xFFFF; +} + +void SdrLinkList::InsertLink(const Link& rLink, unsigned nPos) +{ + unsigned nFnd=FindEntry(rLink); + if (nFnd==0xFFFF) { + if (rLink.IsSet()) { + aList.Insert(new Link(rLink),nPos); + } else { + DBG_ERROR("SdrLinkList::InsertLink(): Versuch, einen nicht gesetzten Link einzufuegen"); + } + } else { + DBG_ERROR("SdrLinkList::InsertLink(): Link schon vorhanden"); + } +} + +void SdrLinkList::RemoveLink(const Link& rLink) +{ + unsigned nFnd=FindEntry(rLink); + if (nFnd!=0xFFFF) { + Link* pLink=(Link*)aList.Remove(nFnd); + delete pLink; + } else { + DBG_ERROR("SdrLinkList::RemoveLink(): Link nicht gefunden"); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #98988# Re-implement GetDraftFillColor(...) + +FASTBOOL GetDraftFillColor(const SfxItemSet& rSet, Color& rCol) +{ + XFillStyle eFill=((XFillStyleItem&)rSet.Get(XATTR_FILLSTYLE)).GetValue(); + FASTBOOL bRetval(FALSE); + + switch(eFill) + { + case XFILL_SOLID: + { + rCol = ((XFillColorItem&)rSet.Get(XATTR_FILLCOLOR)).GetColorValue(); + bRetval = TRUE; + + break; + } + case XFILL_HATCH: + { + Color aCol1(((XFillHatchItem&)rSet.Get(XATTR_FILLHATCH)).GetHatchValue().GetColor()); + Color aCol2(COL_WHITE); + + // #97870# when hatch background is activated, use object fill color as hatch color + sal_Bool bFillHatchBackground = ((const XFillBackgroundItem&)(rSet.Get(XATTR_FILLBACKGROUND))).GetValue(); + if(bFillHatchBackground) + { + aCol2 = ((const XFillColorItem&)(rSet.Get(XATTR_FILLCOLOR))).GetColorValue(); + } + + const basegfx::BColor aAverageColor(basegfx::average(aCol1.getBColor(), aCol2.getBColor())); + rCol = Color(aAverageColor); + bRetval = TRUE; + + break; + } + case XFILL_GRADIENT: { + const XGradient& rGrad=((XFillGradientItem&)rSet.Get(XATTR_FILLGRADIENT)).GetGradientValue(); + Color aCol1(rGrad.GetStartColor()); + Color aCol2(rGrad.GetEndColor()); + const basegfx::BColor aAverageColor(basegfx::average(aCol1.getBColor(), aCol2.getBColor())); + rCol = Color(aAverageColor); + bRetval = TRUE; + + break; + } + case XFILL_BITMAP: + { + const Bitmap& rBitmap = ((XFillBitmapItem&)rSet.Get(XATTR_FILLBITMAP)).GetBitmapValue().GetBitmap(); + const Size aSize(rBitmap.GetSizePixel()); + const sal_uInt32 nWidth = aSize.Width(); + const sal_uInt32 nHeight = aSize.Height(); + Bitmap aBitmap(rBitmap); + BitmapReadAccess* pAccess = aBitmap.AcquireReadAccess(); + + if(pAccess && nWidth > 0 && nHeight > 0) + { + sal_uInt32 nRt(0L); + sal_uInt32 nGn(0L); + sal_uInt32 nBl(0L); + const sal_uInt32 nMaxSteps(8L); + const sal_uInt32 nXStep((nWidth > nMaxSteps) ? nWidth / nMaxSteps : 1L); + const sal_uInt32 nYStep((nHeight > nMaxSteps) ? nHeight / nMaxSteps : 1L); + sal_uInt32 nAnz(0L); + + for(sal_uInt32 nY(0L); nY < nHeight; nY += nYStep) + { + for(sal_uInt32 nX(0L); nX < nWidth; nX += nXStep) + { + const BitmapColor& rCol2 = (pAccess->HasPalette()) + ? pAccess->GetPaletteColor((BYTE)pAccess->GetPixel(nY, nX)) + : pAccess->GetPixel(nY, nX); + + nRt += rCol2.GetRed(); + nGn += rCol2.GetGreen(); + nBl += rCol2.GetBlue(); + nAnz++; + } + } + + nRt /= nAnz; + nGn /= nAnz; + nBl /= nAnz; + + rCol = Color(UINT8(nRt), UINT8(nGn), UINT8(nBl)); + + bRetval = TRUE; + } + + if(pAccess) + { + aBitmap.ReleaseAccess(pAccess); + } + + break; + } + default: break; + } + + return bRetval; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrEngineDefaults::SdrEngineDefaults(): + aFontName( OutputDevice::GetDefaultFont( DEFAULTFONT_SERIF, LANGUAGE_SYSTEM, DEFAULTFONT_FLAGS_ONLYONE ).GetName() ), + eFontFamily(FAMILY_ROMAN), + aFontColor(COL_AUTO), + nFontHeight(847), // 847/100mm = ca. 24 Point + eMapUnit(MAP_100TH_MM), + aMapFraction(1,1) +{ +} + +SdrEngineDefaults& SdrEngineDefaults::GetDefaults() +{ + SdrGlobalData& rGlobalData=GetSdrGlobalData(); + if (rGlobalData.pDefaults==NULL) { + rGlobalData.pDefaults=new SdrEngineDefaults; + } + return *rGlobalData.pDefaults; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEngineDefaults::LanguageHasChanged() +{ + SdrGlobalData& rGlobalData=GetSdrGlobalData(); + if (rGlobalData.pResMgr!=NULL) { + delete rGlobalData.pResMgr; + rGlobalData.pResMgr=NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrOutliner* SdrMakeOutliner( USHORT nOutlinerMode, SdrModel* pModel ) +{ + //SdrEngineDefaults& rDefaults = SdrEngineDefaults::GetDefaults(); + + SfxItemPool* pPool = &pModel->GetItemPool(); + SdrOutliner* pOutl = new SdrOutliner( pPool, nOutlinerMode ); + pOutl->SetEditTextObjectPool( pPool ); + pOutl->SetStyleSheetPool( (SfxStyleSheetPool*) pModel->GetStyleSheetPool() ); + pOutl->SetDefTab( pModel->GetDefaultTabulator() ); + pOutl->SetForbiddenCharsTable( pModel->GetForbiddenCharsTable() ); + pOutl->SetAsianCompressionMode( pModel->GetCharCompressType() ); + pOutl->SetKernAsianPunctuation( pModel->IsKernAsianPunctuation() ); + pOutl->SetAddExtLeading( pModel->IsAddExtLeading() ); + + return pOutl; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +SdrLinkList& ImpGetUserMakeObjHdl() +{ + SdrGlobalData& rGlobalData=GetSdrGlobalData(); + return rGlobalData.aUserMakeObjHdl; +} + +SdrLinkList& ImpGetUserMakeObjUserDataHdl() +{ + SdrGlobalData& rGlobalData=GetSdrGlobalData(); + return rGlobalData.aUserMakeObjUserDataHdl; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ResMgr* ImpGetResMgr() +{ + SdrGlobalData& rGlobalData = GetSdrGlobalData(); + + if(!rGlobalData.pResMgr) + { + ByteString aName("svx"); + rGlobalData.pResMgr = + ResMgr::CreateResMgr( aName.GetBuffer(), Application::GetSettings().GetUILocale() ); + } + + return rGlobalData.pResMgr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +String ImpGetResStr(sal_uInt16 nResID) +{ + return String(ResId(nResID, *ImpGetResMgr())); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace sdr +{ +String GetResourceString(sal_uInt16 nResID) +{ + return ImpGetResStr( nResID ); +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SearchOutlinerItems(const SfxItemSet& rSet, BOOL bInklDefaults, BOOL* pbOnlyEE) +{ + BOOL bHas=FALSE; + BOOL bOnly=TRUE; + BOOL bLookOnly=pbOnlyEE!=NULL; + SfxWhichIter aIter(rSet); + USHORT nWhich=aIter.FirstWhich(); + while (((bLookOnly && bOnly) || !bHas) && nWhich!=0) { + // bei bInklDefaults ist der gesamte Which-Range + // ausschlaggebend, ansonsten nur die gesetzten Items + // Disabled und DontCare wird als Loch im Which-Range betrachtet + SfxItemState eState=rSet.GetItemState(nWhich); + if ((eState==SFX_ITEM_DEFAULT && bInklDefaults) || eState==SFX_ITEM_SET) { + if (nWhich<EE_ITEMS_START || nWhich>EE_ITEMS_END) bOnly=FALSE; + else bHas=TRUE; + } + nWhich=aIter.NextWhich(); + } + if (!bHas) bOnly=FALSE; + if (pbOnlyEE!=NULL) *pbOnlyEE=bOnly; + return bHas; +} + +USHORT* RemoveWhichRange(const USHORT* pOldWhichTable, USHORT nRangeBeg, USHORT nRangeEnd) +{ + // insgesamt sind 6 Faelle moeglich (je Range): + // [Beg..End] zu entfernender Range + // [b..e] [b..e] [b..e] Fall 1,3,2: egal, ganz weg, egal + Ranges + // [b........e] [b........e] Fall 4,5 : Bereich verkleinern | in + // [b......................e] Fall 6 : Splitting + pOldWhichTable + USHORT nAnz=0; + while (pOldWhichTable[nAnz]!=0) nAnz++; + nAnz++; // nAnz muesste nun in jedem Fall eine ungerade Zahl sein (0 am Ende des Arrays) + DBG_ASSERT((nAnz&1)==1,"Joe: RemoveWhichRange: WhichTable hat keine ungerade Anzahl von Eintraegen"); + USHORT nAlloc=nAnz; + // benoetigte Groesse des neuen Arrays ermitteln + USHORT nNum=nAnz-1; + while (nNum!=0) { + nNum-=2; + USHORT nBeg=pOldWhichTable[nNum]; + USHORT nEnd=pOldWhichTable[nNum+1]; + if (nEnd<nRangeBeg) /*nCase=1*/ ; + else if (nBeg>nRangeEnd) /* nCase=2 */ ; + else if (nBeg>=nRangeBeg && nEnd<=nRangeEnd) /* nCase=3 */ nAlloc-=2; + else if (nEnd<=nRangeEnd) /* nCase=4 */; + else if (nBeg>=nRangeBeg) /* nCase=5*/ ; + else /* nCase=6 */ nAlloc+=2; + } + + USHORT* pNewWhichTable=new USHORT[nAlloc]; + memcpy(pNewWhichTable,pOldWhichTable,nAlloc*sizeof(USHORT)); + pNewWhichTable[nAlloc-1]=0; // im Falle 3 fehlt die 0 am Ende + // nun die unerwuenschten Ranges entfernen + nNum=nAlloc-1; + while (nNum!=0) { + nNum-=2; + USHORT nBeg=pNewWhichTable[nNum]; + USHORT nEnd=pNewWhichTable[nNum+1]; + unsigned nCase=0; + if (nEnd<nRangeBeg) nCase=1; + else if (nBeg>nRangeEnd) nCase=2; + else if (nBeg>=nRangeBeg && nEnd<=nRangeEnd) nCase=3; + else if (nEnd<=nRangeEnd) nCase=4; + else if (nBeg>=nRangeBeg) nCase=5; + else nCase=6; + switch (nCase) { + case 3: { + unsigned nTailBytes=(nAnz-(nNum+2))*sizeof(USHORT); + memcpy(&pNewWhichTable[nNum],&pNewWhichTable[nNum+2],nTailBytes); + nAnz-=2; // Merken: Array hat sich verkleinert + } break; + case 4: pNewWhichTable[nNum+1]=nRangeBeg-1; break; + case 5: pNewWhichTable[nNum]=nRangeEnd+1; break; + case 6: { + unsigned nTailBytes=(nAnz-(nNum+2))*sizeof(USHORT); + memcpy(&pNewWhichTable[nNum+4],&pNewWhichTable[nNum+2],nTailBytes); + nAnz+=2; // Merken: Array hat sich vergroessert + pNewWhichTable[nNum+2]=nRangeEnd+1; + pNewWhichTable[nNum+3]=pNewWhichTable[nNum+1]; + pNewWhichTable[nNum+1]=nRangeBeg-1; + } break; + } // switch + } + return pNewWhichTable; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvdProgressInfo::SvdProgressInfo( Link *_pLink ) +{ + DBG_ASSERT(_pLink!=NULL,"SvdProgressInfo(): Kein Link angegeben!!"); + + pLink = _pLink; + nSumActionCount = 0; + nSumCurAction = 0; + + nObjCount = 0; + nCurObj = 0; + + nActionCount = 0; + nCurAction = 0; + + nInsertCount = 0; + nCurInsert = 0; +} + +void SvdProgressInfo::Init( ULONG _nSumActionCount, ULONG _nObjCount ) +{ + nSumActionCount = _nSumActionCount; + nObjCount = _nObjCount; +} + +BOOL SvdProgressInfo::ReportActions( ULONG nAnzActions ) +{ + nSumCurAction += nAnzActions; + nCurAction += nAnzActions; + if(nCurAction > nActionCount) + nCurAction = nActionCount; + + return pLink->Call(NULL) == 1L; +} + +BOOL SvdProgressInfo::ReportInserts( ULONG nAnzInserts ) +{ + nSumCurAction += nAnzInserts; + nCurInsert += nAnzInserts; + + return pLink->Call(NULL) == 1L; +} + +BOOL SvdProgressInfo::ReportRescales( ULONG nAnzRescales ) +{ + nSumCurAction += nAnzRescales; + return pLink->Call(NULL) == 1L; +} + +void SvdProgressInfo::SetActionCount( ULONG _nActionCount ) +{ + nActionCount = _nActionCount; +} + +void SvdProgressInfo::SetInsertCount( ULONG _nInsertCount ) +{ + nInsertCount = _nInsertCount; +} + +BOOL SvdProgressInfo::SetNextObject() +{ + nActionCount = 0; + nCurAction = 0; + + nInsertCount = 0; + nCurInsert = 0; + + nCurObj++; + return ReportActions(0); +} + +void SvdProgressInfo::ReportError() +{ + pLink->Call((void *)1L); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i101872# isolate GetTextEditBackgroundColor to tooling; it woll anyways only be used as long +// as text edit is not running on overlay + +namespace +{ + bool impGetSdrObjListFillColor( + const SdrObjList& rList, + const Point& rPnt, + const SdrPageView& rTextEditPV, + const SetOfByte& rVisLayers, + Color& rCol) + { + if(!rList.GetModel()) + return false; + + bool bRet(false); + bool bMaster(rList.GetPage() ? rList.GetPage()->IsMasterPage() : false); + + for(ULONG no(rList.GetObjCount()); !bRet && no > 0; ) + { + no--; + SdrObject* pObj = rList.GetObj(no); + SdrObjList* pOL = pObj->GetSubList(); + + if(pOL) + { + // group object + bRet = impGetSdrObjListFillColor(*pOL, rPnt, rTextEditPV, rVisLayers, rCol); + } + else + { + SdrTextObj* pText = dynamic_cast< SdrTextObj * >(pObj); + + // #108867# Exclude zero master page object (i.e. background shape) from color query + if(pText + && pObj->IsClosedObj() + && (!bMaster || (!pObj->IsNotVisibleAsMaster() && 0 != no)) + && pObj->GetCurrentBoundRect().IsInside(rPnt) + && !pText->IsHideContour() + && SdrObjectPrimitiveHit(*pObj, rPnt, 0, rTextEditPV, &rVisLayers, false)) + { + bRet = GetDraftFillColor(pObj->GetMergedItemSet(), rCol); + } + } + } + + return bRet; + } + + bool impGetSdrPageFillColor( + const SdrPage& rPage, + const Point& rPnt, + const SdrPageView& rTextEditPV, + const SetOfByte& rVisLayers, + Color& rCol, + bool bSkipBackgroundShape) + { + if(!rPage.GetModel()) + return false; + + bool bRet(impGetSdrObjListFillColor(rPage, rPnt, rTextEditPV, rVisLayers, rCol)); + + if(!bRet && !rPage.IsMasterPage()) + { + if(rPage.TRG_HasMasterPage()) + { + SetOfByte aSet(rVisLayers); + aSet &= rPage.TRG_GetMasterPageVisibleLayers(); + SdrPage& rMasterPage = rPage.TRG_GetMasterPage(); + + // #108867# Don't fall back to background shape on + // master pages. This is later handled by + // GetBackgroundColor, and is necessary to cater for + // the silly ordering: 1. shapes, 2. master page + // shapes, 3. page background, 4. master page + // background. + bRet = impGetSdrPageFillColor(rMasterPage, rPnt, rTextEditPV, aSet, rCol, true); + } + } + + // #108867# Only now determine background color from background shapes + if(!bRet && !bSkipBackgroundShape) + { + rCol = rPage.GetPageBackgroundColor(); + return true; + } + + return bRet; + } + + Color impCalcBackgroundColor( + const Rectangle& rArea, + const SdrPageView& rTextEditPV, + const SdrPage& rPage) + { + svtools::ColorConfig aColorConfig; + Color aBackground(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + + if(!rStyleSettings.GetHighContrastMode()) + { + // search in page + const USHORT SPOTCOUNT(5); + Point aSpotPos[SPOTCOUNT]; + Color aSpotColor[SPOTCOUNT]; + ULONG nHeight( rArea.GetSize().Height() ); + ULONG nWidth( rArea.GetSize().Width() ); + ULONG nWidth14 = nWidth / 4; + ULONG nHeight14 = nHeight / 4; + ULONG nWidth34 = ( 3 * nWidth ) / 4; + ULONG nHeight34 = ( 3 * nHeight ) / 4; + + USHORT i; + for ( i = 0; i < SPOTCOUNT; i++ ) + { + // five spots are used + switch ( i ) + { + case 0 : + { + // Center-Spot + aSpotPos[i] = rArea.Center(); + } + break; + + case 1 : + { + // TopLeft-Spot + aSpotPos[i] = rArea.TopLeft(); + aSpotPos[i].X() += nWidth14; + aSpotPos[i].Y() += nHeight14; + } + break; + + case 2 : + { + // TopRight-Spot + aSpotPos[i] = rArea.TopLeft(); + aSpotPos[i].X() += nWidth34; + aSpotPos[i].Y() += nHeight14; + } + break; + + case 3 : + { + // BottomLeft-Spot + aSpotPos[i] = rArea.TopLeft(); + aSpotPos[i].X() += nWidth14; + aSpotPos[i].Y() += nHeight34; + } + break; + + case 4 : + { + // BottomRight-Spot + aSpotPos[i] = rArea.TopLeft(); + aSpotPos[i].X() += nWidth34; + aSpotPos[i].Y() += nHeight34; + } + break; + + } + + aSpotColor[i] = Color( COL_WHITE ); + impGetSdrPageFillColor(rPage, aSpotPos[i], rTextEditPV, rTextEditPV.GetVisibleLayers(), aSpotColor[i], false); + } + + USHORT aMatch[SPOTCOUNT]; + + for ( i = 0; i < SPOTCOUNT; i++ ) + { + // were same spot colors found? + aMatch[i] = 0; + + for ( USHORT j = 0; j < SPOTCOUNT; j++ ) + { + if( j != i ) + { + if( aSpotColor[i] == aSpotColor[j] ) + { + aMatch[i]++; + } + } + } + } + + // highest weight to center spot + aBackground = aSpotColor[0]; + + for ( USHORT nMatchCount = SPOTCOUNT - 1; nMatchCount > 1; nMatchCount-- ) + { + // which spot color was found most? + for ( i = 0; i < SPOTCOUNT; i++ ) + { + if( aMatch[i] == nMatchCount ) + { + aBackground = aSpotColor[i]; + nMatchCount = 1; // break outer for-loop + break; + } + } + } + } + + return aBackground; + } +} // end of anonymous namespace + +Color GetTextEditBackgroundColor(const SdrObjEditView& rView) +{ + svtools::ColorConfig aColorConfig; + Color aBackground(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + + if(!rStyleSettings.GetHighContrastMode()) + { + bool bFound(false); + SdrTextObj* pText = dynamic_cast< SdrTextObj * >(rView.GetTextEditObject()); + + if(pText && pText->IsClosedObj()) + { + ::sdr::table::SdrTableObj* pTable = dynamic_cast< ::sdr::table::SdrTableObj * >( pText ); + + if( pTable ) + bFound = GetDraftFillColor(pTable->GetActiveCellItemSet(), aBackground ); + + if( !bFound ) + bFound=GetDraftFillColor(pText->GetMergedItemSet(), aBackground); + } + + if(!bFound && pText) + { + SdrPageView* pTextEditPV = rView.GetTextEditPageView(); + + if(pTextEditPV) + { + Point aPvOfs(pText->GetTextEditOffset()); + const SdrPage* pPg = pTextEditPV->GetPage(); + + if(pPg) + { + Rectangle aSnapRect( pText->GetSnapRect() ); + aSnapRect.Move(aPvOfs.X(), aPvOfs.Y()); + + return impCalcBackgroundColor(aSnapRect, *pTextEditPV, *pPg); + } + } + } + } + + return aBackground; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdfmtf.cxx b/svx/source/svdraw/svdfmtf.cxx new file mode 100644 index 000000000000..34a77fcd9e62 --- /dev/null +++ b/svx/source/svdraw/svdfmtf.cxx @@ -0,0 +1,1028 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include "svdfmtf.hxx" +#include <editeng/editdata.hxx> +#include <math.h> +#include <svx/xpoly.hxx> +#include <vcl/svapp.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/shdditem.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xgrad.hxx> +#include <svx/xflgrit.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/akrnitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/colritem.hxx> +#include <vcl/metric.hxx> +#include <editeng/charscaleitem.hxx> +#include <svx/xflhtit.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdobj.hxx> +#include "svditext.hxx" +#include <svx/svdotext.hxx> +#include <svx/svdorect.hxx> +#include <svx/svdocirc.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdetc.hxx> +#include <svl/itemset.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <svx/xlinjoit.hxx> +#include <svx/xlndsit.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel): + nMapScalingOfs(0), + pLineAttr(NULL),pFillAttr(NULL),pTextAttr(NULL), + pPage(NULL),pModel(NULL),nLayer(0), + nLineWidth(0), + maLineJoin(basegfx::B2DLINEJOIN_NONE), + maDash(XDASH_RECT, 0, 0, 0, 0, 0), + bFntDirty(TRUE), + bLastObjWasPolyWithoutLine(FALSE),bNoLine(FALSE),bNoFill(FALSE),bLastObjWasLine(FALSE) +{ + aVD.EnableOutput(FALSE); + + // #i111954# init to no fill and no line initially + aVD.SetLineColor(); + aVD.SetFillColor(); + + aOldLineColor.SetRed( aVD.GetLineColor().GetRed() + 1 ); // invalidate old line color + pLineAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_LINE_FIRST,XATTR_LINE_LAST); + pFillAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST); + pTextAttr=new SfxItemSet(rModel.GetItemPool(),EE_ITEMS_START,EE_ITEMS_END); + pModel=&rModel; +} + +ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport() +{ + delete pLineAttr; + delete pFillAttr; + delete pTextAttr; +} + +ULONG ImpSdrGDIMetaFileImport::DoImport(const GDIMetaFile& rMtf, + SdrObjList& rOL, + ULONG nInsPos, + SvdProgressInfo *pProgrInfo) +{ + pPage = rOL.GetPage(); + GDIMetaFile* pTmpMtf=NULL; + GDIMetaFile* pMtf = (GDIMetaFile*) &rMtf; + ULONG nActionAnz=pMtf->GetActionCount(); + sal_Bool bError = sal_False; + + + // setup some global scale parameter + // fScaleX, fScaleY, aScaleX, aScaleY, bMov, bSize + fScaleX = fScaleY = 1.0; + Size aMtfSize( pMtf->GetPrefSize() ); + if ( aMtfSize.Width() & aMtfSize.Height() && ( aScaleRect.IsEmpty() == sal_False ) ) + { + aOfs = aScaleRect.TopLeft(); + if ( aMtfSize.Width() != ( aScaleRect.GetWidth() - 1 ) ) + fScaleX = (double)( aScaleRect.GetWidth() - 1 ) / (double)aMtfSize.Width(); + if ( aMtfSize.Height() != ( aScaleRect.GetHeight() - 1 ) ) + fScaleY = (double)( aScaleRect.GetHeight() - 1 ) / (double)aMtfSize.Height(); + } + + bMov = aOfs.X()!=0 || aOfs.Y()!=0; + bSize = sal_False; + + aScaleX = Fraction( 1, 1 ); + aScaleY = Fraction( 1, 1 ); + if ( aMtfSize.Width() != ( aScaleRect.GetWidth() - 1 ) ) + { + aScaleX = Fraction( aScaleRect.GetWidth() - 1, aMtfSize.Width() ); + bSize = sal_True; + } + if ( aMtfSize.Height() != ( aScaleRect.GetHeight() - 1 ) ) + { + aScaleY = Fraction( aScaleRect.GetHeight() - 1, aMtfSize.Height() ); + bSize = sal_True; + } + + if(65000 < nActionAnz) + { + nActionAnz = 65000; + bError = TRUE; + } + + if(pProgrInfo) + pProgrInfo->SetActionCount(nActionAnz); + + ULONG nActionsToReport = 0; + + for( MetaAction* pAct = pMtf->FirstAction(); pAct; pAct = pMtf->NextAction() ) + { + switch (pAct->GetType()) + { + case META_PIXEL_ACTION : DoAction((MetaPixelAction &)*pAct); break; + case META_POINT_ACTION : DoAction((MetaPointAction &)*pAct); break; + case META_LINE_ACTION : DoAction((MetaLineAction &)*pAct); break; + case META_RECT_ACTION : DoAction((MetaRectAction &)*pAct); break; + case META_ROUNDRECT_ACTION : DoAction((MetaRoundRectAction &)*pAct); break; + case META_ELLIPSE_ACTION : DoAction((MetaEllipseAction &)*pAct); break; + case META_ARC_ACTION : DoAction((MetaArcAction &)*pAct); break; + case META_PIE_ACTION : DoAction((MetaPieAction &)*pAct); break; + case META_CHORD_ACTION : DoAction((MetaChordAction &)*pAct); break; + case META_POLYLINE_ACTION : DoAction((MetaPolyLineAction &)*pAct); break; + case META_POLYGON_ACTION : DoAction((MetaPolygonAction &)*pAct); break; + case META_POLYPOLYGON_ACTION : DoAction((MetaPolyPolygonAction &)*pAct); break; + case META_TEXT_ACTION : DoAction((MetaTextAction &)*pAct); break; + case META_TEXTARRAY_ACTION : DoAction((MetaTextArrayAction &)*pAct); break; + case META_STRETCHTEXT_ACTION : DoAction((MetaStretchTextAction &)*pAct); break; + case META_BMP_ACTION : DoAction((MetaBmpAction &)*pAct); break; + case META_BMPSCALE_ACTION : DoAction((MetaBmpScaleAction &)*pAct); break; + case META_BMPEX_ACTION : DoAction((MetaBmpExAction &)*pAct); break; + case META_BMPEXSCALE_ACTION : DoAction((MetaBmpExScaleAction &)*pAct); break; + case META_LINECOLOR_ACTION : DoAction((MetaLineColorAction &)*pAct); break; + case META_FILLCOLOR_ACTION : DoAction((MetaFillColorAction &)*pAct); break; + case META_TEXTCOLOR_ACTION : DoAction((MetaTextColorAction &)*pAct); break; + case META_TEXTFILLCOLOR_ACTION : DoAction((MetaTextFillColorAction &)*pAct); break; + case META_FONT_ACTION : DoAction((MetaFontAction &)*pAct); break; + case META_TEXTALIGN_ACTION : DoAction((MetaTextAlignAction &)*pAct); break; + case META_MAPMODE_ACTION : DoAction((MetaMapModeAction &)*pAct); break; + case META_CLIPREGION_ACTION : DoAction((MetaClipRegionAction &)*pAct); break; + case META_MOVECLIPREGION_ACTION : DoAction((MetaMoveClipRegionAction &)*pAct); break; + case META_ISECTRECTCLIPREGION_ACTION: DoAction((MetaISectRectClipRegionAction&)*pAct); break; + case META_ISECTREGIONCLIPREGION_ACTION: DoAction((MetaISectRegionClipRegionAction&)*pAct); break; + case META_RASTEROP_ACTION : DoAction((MetaRasterOpAction &)*pAct); break; + case META_PUSH_ACTION : DoAction((MetaPushAction &)*pAct); break; + case META_POP_ACTION : DoAction((MetaPopAction &)*pAct); break; + case META_HATCH_ACTION : DoAction((MetaHatchAction &)*pAct); break; + case META_COMMENT_ACTION : DoAction((MetaCommentAction &)*pAct, pMtf); break; + + } + + if(pProgrInfo != NULL) + { + nActionsToReport++; + if(nActionsToReport >= 16) // Alle 16 Action updaten + { + if(!pProgrInfo->ReportActions(nActionsToReport)) + break; + nActionsToReport = 0; + } + } + } + + if(pProgrInfo != NULL) + { + pProgrInfo->ReportActions(nActionsToReport); + nActionsToReport = 0; + } + + // MapMode-Scaling vornehmen + MapScaling(); + // Objekte in vorgegebenes Rechteck hineinskalieren + ULONG nAnz=aTmpList.GetObjCount(); + + // Beim berechnen der Fortschrittsanzeige wird GetActionCount()*3 benutzt. + // Da in aTmpList allerdings weniger eintraege als GetActionCount() + // existieren koennen, muessen hier die zuviel vermuteten Actionen wieder + // hinzugefuegt werden. + nActionsToReport = (pMtf->GetActionCount() - nAnz)*2; + + + // Alle noch nicht gemeldeten Rescales melden + if(pProgrInfo) + { + pProgrInfo->ReportRescales(nActionsToReport); + pProgrInfo->SetInsertCount(nAnz); + } + nActionsToReport = 0; + + // alle in aTmpList zwischengespeicherten Objekte nun in rOL ab der Position nInsPos einfuegen + if (nInsPos>rOL.GetObjCount()) nInsPos=rOL.GetObjCount(); + SdrInsertReason aReason(SDRREASON_VIEWCALL); + for (ULONG i=0; i<nAnz; i++) + { + SdrObject* pObj=aTmpList.GetObj(i); + rOL.NbcInsertObject(pObj,nInsPos,&aReason); + nInsPos++; + + if(pProgrInfo != NULL) + { + nActionsToReport++; + if(nActionsToReport >= 32) // Alle 32 Action updaten + { + pProgrInfo->ReportInserts(nActionsToReport); + nActionsToReport = 0; + } + } + } + if (pTmpMtf!=NULL) delete pTmpMtf; + + // ein letztesmal alle verbliebennen Inserts reporten + if(pProgrInfo != NULL) + { + pProgrInfo->ReportInserts(nActionsToReport); + if(bError) + pProgrInfo->ReportError(); + } + + return aTmpList.GetObjCount(); +} + +void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, FASTBOOL bForceTextAttr) +{ + bNoLine = FALSE; bNoFill = FALSE; + FASTBOOL bLine=TRUE && !bForceTextAttr; + FASTBOOL bFill=pObj==NULL || pObj->IsClosedObj() && !bForceTextAttr; + FASTBOOL bText=bForceTextAttr || (pObj!=NULL && pObj->GetOutlinerParaObject()!=NULL); + + if ( bLine ) + { + if ( nLineWidth ) + pLineAttr->Put( XLineWidthItem( nLineWidth ) ); + else + pLineAttr->Put( XLineWidthItem( 0 ) ); + + aOldLineColor = aVD.GetLineColor(); + if( aVD.IsLineColor() ) + { + pLineAttr->Put(XLineStyleItem(XLINE_SOLID)); + pLineAttr->Put(XLineColorItem(String(), aVD.GetLineColor())); + } + else + pLineAttr->Put(XLineStyleItem(XLINE_NONE)); + + switch(maLineJoin) + { + default : // basegfx::B2DLINEJOIN_NONE + pLineAttr->Put(XLineJointItem(XLINEJOINT_NONE)); + break; + case basegfx::B2DLINEJOIN_MIDDLE: + pLineAttr->Put(XLineJointItem(XLINEJOINT_MIDDLE)); + break; + case basegfx::B2DLINEJOIN_BEVEL: + pLineAttr->Put(XLineJointItem(XLINEJOINT_BEVEL)); + break; + case basegfx::B2DLINEJOIN_MITER: + pLineAttr->Put(XLineJointItem(XLINEJOINT_MITER)); + break; + case basegfx::B2DLINEJOIN_ROUND: + pLineAttr->Put(XLineJointItem(XLINEJOINT_ROUND)); + break; + } + + if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance()) + { + pLineAttr->Put(XLineDashItem(String(), maDash)); + } + else + { + pLineAttr->Put(XLineDashItem(String(), XDash(XDASH_RECT))); + } + } + else + bNoLine = TRUE; + + if ( bFill ) + { + if( aVD.IsFillColor() ) + { + pFillAttr->Put(XFillStyleItem(XFILL_SOLID)); + pFillAttr->Put(XFillColorItem(String(), aVD.GetFillColor())); + } + else + pFillAttr->Put(XFillStyleItem(XFILL_NONE)); + } + else + bNoFill = TRUE; + + if ( bText && bFntDirty ) + { + Font aFnt(aVD.GetFont()); + pTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), + aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) ); + pTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), + aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) ); + pTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), + aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) ); + pTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC)); + pTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT)); + sal_uInt32 nHeight = FRound(aFnt.GetSize().Height() * fScaleY); + pTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); + pTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + pTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + pTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH)); + pTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE)); + pTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE)); + pTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT)); + pTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW)); + pTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING)); + pTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM)); + pTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE)); + pTextAttr->Put(SvxColorItem(aFnt.GetColor(), EE_CHAR_COLOR)); + //... svxfont textitem svditext + bFntDirty=FALSE; + } + if (pObj!=NULL) + { + pObj->SetLayer(nLayer); + if (bLine) pObj->SetMergedItemSet(*pLineAttr); + if (bFill) pObj->SetMergedItemSet(*pFillAttr); + if (bText) + { + pObj->SetMergedItemSet(*pTextAttr); + pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_LEFT ) ); + } + } +} + +void ImpSdrGDIMetaFileImport::InsertObj( SdrObject* pObj, sal_Bool bScale ) +{ + if ( bScale && !aScaleRect.IsEmpty() ) + { + if ( bSize ) + pObj->NbcResize( Point(), aScaleX, aScaleY ); + if ( bMov ) + pObj->NbcMove( Size( aOfs.X(), aOfs.Y() ) ); + } + + // #i111954# check object for visibility + // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj + bool bVisible(false); + + if(pObj->HasLineStyle()) + { + bVisible = true; + } + + if(!bVisible && pObj->HasFillStyle()) + { + bVisible = true; + } + + if(!bVisible) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj); + + if(pTextObj && pTextObj->HasText()) + { + bVisible = true; + } + } + + if(!bVisible) + { + SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj); + + if(pGrafObj) + { + // this may be refined to check if the graphic really is visible. It + // is here to ensure that graphic objects without fill, line and text + // get created + bVisible = true; + } + } + + if(!bVisible) + { + SdrObject::Free(pObj); + } + else + { + aTmpList.InsertObject( pObj ); + if ( HAS_BASE( SdrPathObj, pObj ) ) + { + FASTBOOL bClosed=pObj->IsClosedObj(); + bLastObjWasPolyWithoutLine=bNoLine && bClosed; + bLastObjWasLine=!bClosed; + } + else + { + bLastObjWasPolyWithoutLine = FALSE; + bLastObjWasLine = FALSE; + } + } +} + +/**************************************************************************************************/ + +void ImpSdrGDIMetaFileImport::DoAction(MetaPixelAction& /*rAct*/) +{ +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaPointAction& /*rAct*/) +{ +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction& rAct) +{ + // #i73407# reformulation to use new B2DPolygon classes + const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y()); + const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y()); + + if(!aStart.equal(aEnd)) + { + basegfx::B2DPolygon aLine; + const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y())); + + aLine.append(aStart); + aLine.append(aEnd); + aLine.transform(aTransform); + + const LineInfo& rLineInfo = rAct.GetLineInfo(); + const sal_Int32 nNewLineWidth(rLineInfo.GetWidth()); + bool bCreateLineObject(true); + + if(bLastObjWasLine && (nNewLineWidth == nLineWidth) && CheckLastLineMerge(aLine)) + { + bCreateLineObject = false; + } + + if(bCreateLineObject) + { + SdrPathObj* pPath = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aLine)); + nLineWidth = nNewLineWidth; + maLineJoin = rLineInfo.GetLineJoin(); + maDash = XDash(XDASH_RECT, + rLineInfo.GetDotCount(), rLineInfo.GetDotLen(), + rLineInfo.GetDashCount(), rLineInfo.GetDashLen(), + rLineInfo.GetDistance()); + SetAttributes(pPath); + nLineWidth = 0; + maLineJoin = basegfx::B2DLINEJOIN_NONE; + maDash = XDash(); + InsertObj(pPath, false); + } + } +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction& rAct) +{ + SdrRectObj* pRect=new SdrRectObj(rAct.GetRect()); + SetAttributes(pRect); + InsertObj(pRect); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction& rAct) +{ + SdrRectObj* pRect=new SdrRectObj(rAct.GetRect()); + SetAttributes(pRect); + long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2; + if (nRad!=0) { + SfxItemSet aSet(*pLineAttr->GetPool(),SDRATTR_ECKENRADIUS,SDRATTR_ECKENRADIUS); + aSet.Put(SdrEckenradiusItem(nRad)); + pRect->SetMergedItemSet(aSet); + } + InsertObj(pRect); +} + +/**************************************************************************************************/ + +void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction& rAct) +{ + SdrCircObj* pCirc=new SdrCircObj(OBJ_CIRC,rAct.GetRect()); + SetAttributes(pCirc); + InsertObj(pCirc); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction& rAct) +{ + Point aCenter(rAct.GetRect().Center()); + long nStart=GetAngle(rAct.GetStartPoint()-aCenter); + long nEnd=GetAngle(rAct.GetEndPoint()-aCenter); + SdrCircObj* pCirc=new SdrCircObj(OBJ_CARC,rAct.GetRect(),nStart,nEnd); + SetAttributes(pCirc); + InsertObj(pCirc); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction& rAct) +{ + Point aCenter(rAct.GetRect().Center()); + long nStart=GetAngle(rAct.GetStartPoint()-aCenter); + long nEnd=GetAngle(rAct.GetEndPoint()-aCenter); + SdrCircObj* pCirc=new SdrCircObj(OBJ_SECT,rAct.GetRect(),nStart,nEnd); + SetAttributes(pCirc); + InsertObj(pCirc); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction& rAct) +{ + Point aCenter(rAct.GetRect().Center()); + long nStart=GetAngle(rAct.GetStartPoint()-aCenter); + long nEnd=GetAngle(rAct.GetEndPoint()-aCenter); + SdrCircObj* pCirc=new SdrCircObj(OBJ_CCUT,rAct.GetRect(),nStart,nEnd); + SetAttributes(pCirc); + InsertObj(pCirc); +} + +/**************************************************************************************************/ + +bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly) +{ + // #i102706# Do not merge closed polygons + if(rSrcPoly.isClosed()) + { + return false; + } + + // #i73407# reformulation to use new B2DPolygon classes + if(bLastObjWasLine && (aOldLineColor == aVD.GetLineColor()) && rSrcPoly.count()) + { + SdrObject* pTmpObj = aTmpList.GetObj(aTmpList.GetObjCount() - 1); + SdrPathObj* pLastPoly = PTR_CAST(SdrPathObj, pTmpObj); + + if(pLastPoly) + { + if(1L == pLastPoly->GetPathPoly().count()) + { + bool bOk(false); + basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0L)); + + // #i102706# Do not merge closed polygons + if(aDstPoly.isClosed()) + { + return false; + } + + if(aDstPoly.count()) + { + const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1L); + const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1L); + + if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0L)) + { + aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L); + bOk = true; + } + else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(nMaxSrcPnt)) + { + basegfx::B2DPolygon aNew(rSrcPoly); + aNew.append(aDstPoly, 1L, aDstPoly.count() - 1L); + aDstPoly = aNew; + bOk = true; + } + else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(0L)) + { + aDstPoly.flip(); + aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L); + bOk = true; + } + else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt)) + { + basegfx::B2DPolygon aNew(rSrcPoly); + aNew.flip(); + aDstPoly.append(aNew, 1L, aNew.count() - 1L); + bOk = true; + } + } + + if(bOk) + { + pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly)); + } + + return bOk; + } + } + } + + return false; +} + +bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon) +{ + // #i73407# reformulation to use new B2DPolygon classes + if(bLastObjWasPolyWithoutLine) + { + SdrObject* pTmpObj = aTmpList.GetObj(aTmpList.GetObjCount() - 1); + SdrPathObj* pLastPoly = PTR_CAST(SdrPathObj, pTmpObj); + + if(pLastPoly) + { + if(pLastPoly->GetPathPoly() == rPolyPolygon) + { + SetAttributes(NULL); + + if(!bNoLine && bNoFill) + { + pLastPoly->SetMergedItemSet(*pLineAttr); + + return true; + } + } + } + } + + return false; +} + + +void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct ) +{ + // #i73407# reformulation to use new B2DPolygon classes + basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon()); + + if(aSource.count()) + { + const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y())); + aSource.transform(aTransform); + } + + const LineInfo& rLineInfo = rAct.GetLineInfo(); + const sal_Int32 nNewLineWidth(rLineInfo.GetWidth()); + bool bCreateLineObject(true); + + if(bLastObjWasLine && (nNewLineWidth == nLineWidth) && CheckLastLineMerge(aSource)) + { + bCreateLineObject = false; + } + else if(bLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource))) + { + bCreateLineObject = false; + } + + if(bCreateLineObject) + { + SdrPathObj* pPath = new SdrPathObj( + aSource.isClosed() ? OBJ_POLY : OBJ_PLIN, + basegfx::B2DPolyPolygon(aSource)); + nLineWidth = nNewLineWidth; + maLineJoin = rLineInfo.GetLineJoin(); + maDash = XDash(XDASH_RECT, + rLineInfo.GetDotCount(), rLineInfo.GetDotLen(), + rLineInfo.GetDashCount(), rLineInfo.GetDashLen(), + rLineInfo.GetDistance()); + SetAttributes(pPath); + nLineWidth = 0; + maLineJoin = basegfx::B2DLINEJOIN_NONE; + maDash = XDash(); + InsertObj(pPath, false); + } +} + +void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct ) +{ + // #i73407# reformulation to use new B2DPolygon classes + basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon()); + + if(aSource.count()) + { + const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y())); + aSource.transform(aTransform); + + if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource))) + { + // #i73407# make sure polygon is closed, it's a filled primitive + aSource.setClosed(true); + + SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource)); + SetAttributes(pPath); + InsertObj(pPath, false); + } + } +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct) +{ + // #i73407# reformulation to use new B2DPolygon classes + basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon()); + + if(aSource.count()) + { + const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y())); + aSource.transform(aTransform); + + if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource)) + { + // #i73407# make sure polygon is closed, it's a filled primitive + aSource.setClosed(true); + + SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource); + SetAttributes(pPath); + InsertObj(pPath, false); + } + } +} + +/**************************************************************************************************/ + +void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct ) +{ + // calc text box size, add 5% to make it fit safely + + FontMetric aFontMetric( aVD.GetFontMetric() ); + Font aFnt( aVD.GetFont() ); + FontAlign eAlg( aFnt.GetAlign() ); + + sal_Int32 nTextWidth = (sal_Int32)( aVD.GetTextWidth( rStr ) * fScaleX ); + sal_Int32 nTextHeight = (sal_Int32)( aVD.GetTextHeight() * fScaleY ); + //sal_Int32 nDxWidth = 0; + //sal_Int32 nLen = rStr.Len(); + + Point aPos( FRound(rPos.X() * fScaleX + aOfs.X()), FRound(rPos.Y() * fScaleY + aOfs.Y()) ); + Size aSize( nTextWidth, nTextHeight ); + + if ( eAlg == ALIGN_BASELINE ) + aPos.Y() -= FRound(aFontMetric.GetAscent() * fScaleY); + else if ( eAlg == ALIGN_BOTTOM ) + aPos.Y() -= nTextHeight; + + Rectangle aTextRect( aPos, aSize ); + SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect ); + + if ( aFnt.GetWidth() || ( rAct.GetType() == META_STRETCHTEXT_ACTION ) ) + { + pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH ); + pText->SetMergedItem( SdrTextAutoGrowHeightItem( FALSE ) ); + // don't let the margins eat the space needed for the text + pText->SetMergedItem ( SdrTextUpperDistItem (0)); + pText->SetMergedItem ( SdrTextLowerDistItem (0)); + pText->SetMergedItem ( SdrTextRightDistItem (0)); + pText->SetMergedItem ( SdrTextLeftDistItem (0)); + pText->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES ) ); + } + else + pText->SetMergedItem( SdrTextAutoGrowWidthItem( sal_True ) ); + + pText->SetModel( pModel ); + pText->SetLayer( nLayer ); + pText->NbcSetText( rStr ); + SetAttributes( pText, TRUE ); + pText->SetSnapRect( aTextRect ); + + if (!aFnt.IsTransparent()) + { + SfxItemSet aAttr(*pFillAttr->GetPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST); + aAttr.Put(XFillStyleItem(XFILL_SOLID)); + aAttr.Put(XFillColorItem(String(), aFnt.GetFillColor())); + pText->SetMergedItemSet(aAttr); + } + sal_uInt32 nWink = aFnt.GetOrientation(); + if ( nWink ) + { + nWink*=10; + double a=nWink*nPi180; + double nSin=sin(a); + double nCos=cos(a); + pText->NbcRotate(aPos,nWink,nSin,nCos); + } + InsertObj( pText, sal_False ); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction& rAct) +{ + XubString aStr(rAct.GetText()); + aStr.Erase(0,rAct.GetIndex()); + aStr.Erase(rAct.GetLen()); + ImportText( rAct.GetPoint(), aStr, rAct ); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction& rAct) +{ + XubString aStr(rAct.GetText()); + aStr.Erase(0,rAct.GetIndex()); + aStr.Erase(rAct.GetLen()); + ImportText( rAct.GetPoint(), aStr, rAct ); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction& rAct) +{ + XubString aStr(rAct.GetText()); + aStr.Erase(0,rAct.GetIndex()); + aStr.Erase(rAct.GetLen()); + ImportText( rAct.GetPoint(), aStr, rAct ); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction& rAct) +{ + Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel()); + aRect.Right()++; aRect.Bottom()++; + SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect); + InsertObj(pGraf); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction& rAct) +{ + Rectangle aRect(rAct.GetPoint(),rAct.GetSize()); + aRect.Right()++; aRect.Bottom()++; + SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect); + InsertObj(pGraf); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction& rAct) +{ + Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel()); + aRect.Right()++; aRect.Bottom()++; + SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect ); + InsertObj(pGraf); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction& rAct) +{ + Rectangle aRect(rAct.GetPoint(),rAct.GetSize()); + aRect.Right()++; aRect.Bottom()++; + SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect ); + InsertObj(pGraf); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction& rAct ) +{ + // #i73407# reformulation to use new B2DPolygon classes + basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon()); + + if(aSource.count()) + { + const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y())); + aSource.transform(aTransform); + + if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource)) + { + const Hatch& rHatch = rAct.GetHatch(); + SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource); + SfxItemSet aHatchAttr(pModel->GetItemPool(), + XATTR_FILLSTYLE, XATTR_FILLSTYLE, + XATTR_FILLHATCH, XATTR_FILLHATCH, 0, 0 ); + XHatchStyle eStyle; + + switch(rHatch.GetStyle()) + { + case(HATCH_TRIPLE) : + { + eStyle = XHATCH_TRIPLE; + break; + } + + case(HATCH_DOUBLE) : + { + eStyle = XHATCH_DOUBLE; + break; + } + + default: + { + eStyle = XHATCH_SINGLE; + break; + } + } + + SetAttributes(pPath); + aHatchAttr.Put(XFillStyleItem(XFILL_HATCH)); + aHatchAttr.Put(XFillHatchItem(&pModel->GetItemPool(), XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle()))); + pPath->SetMergedItemSet(aHatchAttr); + + InsertObj(pPath, false); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct) +{ + rAct.Execute(&aVD); +} + +void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct) +{ + MapScaling(); + rAct.Execute(&aVD); + bLastObjWasPolyWithoutLine=FALSE; + bLastObjWasLine=FALSE; +} + +void ImpSdrGDIMetaFileImport::MapScaling() +{ + sal_uInt32 i, nAnz = aTmpList.GetObjCount(); + const MapMode& rMap = aVD.GetMapMode(); + Point aMapOrg( rMap.GetOrigin() ); + sal_Bool bMov2 = aMapOrg.X() != 0 || aMapOrg.Y() != 0; + if ( bMov2 ) + { + for ( i = nMapScalingOfs; i < nAnz; i++ ) + { + SdrObject* pObj = aTmpList.GetObj(i); + if ( bMov2 ) + pObj->NbcMove( Size( aMapOrg.X(), aMapOrg.Y() ) ); + } + } + nMapScalingOfs = nAnz; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile* pMtf ) +{ + ByteString aSkipComment; + + if( rAct.GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL ) + { + MetaGradientExAction* pAct = (MetaGradientExAction*) pMtf->NextAction(); + + if( pAct && pAct->GetType() == META_GRADIENTEX_ACTION ) + { + // #i73407# reformulation to use new B2DPolygon classes + basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon()); + + if(aSource.count()) + { + if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource)) + { + const Gradient& rGrad = pAct->GetGradient(); + SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource); + SfxItemSet aGradAttr(pModel->GetItemPool(), + XATTR_FILLSTYLE, XATTR_FILLSTYLE, + XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0 ); + XGradient aXGradient; + + aXGradient.SetGradientStyle((XGradientStyle)rGrad.GetStyle()); + aXGradient.SetStartColor(rGrad.GetStartColor()); + aXGradient.SetEndColor(rGrad.GetEndColor()); + aXGradient.SetAngle((USHORT)rGrad.GetAngle()); + aXGradient.SetBorder(rGrad.GetBorder()); + aXGradient.SetXOffset(rGrad.GetOfsX()); + aXGradient.SetYOffset(rGrad.GetOfsY()); + aXGradient.SetStartIntens(rGrad.GetStartIntensity()); + aXGradient.SetEndIntens(rGrad.GetEndIntensity()); + aXGradient.SetSteps(rGrad.GetSteps()); + + if(aVD.IsLineColor()) + { + // switch line off; when there was one there will be a + // META_POLYLINE_ACTION following creating another object + const Color aLineColor(aVD.GetLineColor()); + aVD.SetLineColor(); + SetAttributes(pPath); + aVD.SetLineColor(aLineColor); + } + else + { + SetAttributes(pPath); + } + + aGradAttr.Put(XFillStyleItem(XFILL_GRADIENT)); + aGradAttr.Put(XFillGradientItem(&pModel->GetItemPool(), aXGradient)); + pPath->SetMergedItemSet(aGradAttr); + + InsertObj(pPath); + } + } + + aSkipComment = "XGRAD_SEQ_END"; + } + } + + if(aSkipComment.Len()) + { + MetaAction* pSkipAct = pMtf->NextAction(); + + while( pSkipAct + && ((pSkipAct->GetType() != META_COMMENT_ACTION ) + || (((MetaCommentAction*)pSkipAct)->GetComment().CompareIgnoreCaseToAscii(aSkipComment.GetBuffer()) != COMPARE_EQUAL))) + { + pSkipAct = pMtf->NextAction(); + } + } +} + +// eof diff --git a/svx/source/svdraw/svdfmtf.hxx b/svx/source/svdraw/svdfmtf.hxx new file mode 100644 index 000000000000..2562b81efa8d --- /dev/null +++ b/svx/source/svdraw/svdfmtf.hxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVDFMTF_HXX +#define _SVDFMTF_HXX + +#include <vcl/metaact.hxx> +#include <vcl/virdev.hxx> +#include <svx/svdobj.hxx> + +//************************************************************ +// Vorausdeklarationen +//************************************************************ + +class SfxItemSet; +class SdrObjList; +class SdrModel; +class SdrPage; +class SdrObject; +class SvdProgressInfo; + +//************************************************************ +// Hilfsklasse SdrObjRefList +//************************************************************ + +class SdrObjRefList +{ + Container aList; +public: + + SdrObjRefList() + : aList(1024,64,64) + {} + + void Clear() { aList.Clear(); } + ULONG GetObjCount() const { return aList.Count(); } + SdrObject* GetObj(ULONG nNum) const { return (SdrObject*)aList.GetObject(nNum); } + SdrObject* operator[](ULONG nNum) const { return (SdrObject*)aList.GetObject(nNum); } + void InsertObject(SdrObject* pObj, ULONG nPos=CONTAINER_APPEND) { aList.Insert(pObj,nPos); } + void RemoveObject(ULONG nPos) { aList.Remove(nPos); } +}; + +//************************************************************ +// Hilfsklasse ImpSdrGDIMetaFileImport +//************************************************************ + +class ImpSdrGDIMetaFileImport +{ +protected: + SdrObjRefList aTmpList; + VirtualDevice aVD; + Rectangle aScaleRect; + ULONG nMapScalingOfs; // ab hier nocht nicht mit MapScaling bearbeitet + SfxItemSet* pLineAttr; + SfxItemSet* pFillAttr; + SfxItemSet* pTextAttr; + SdrPage* pPage; + SdrModel* pModel; + SdrLayerID nLayer; + Color aOldLineColor; + sal_Int32 nLineWidth; + basegfx::B2DLineJoin maLineJoin; + XDash maDash; + + sal_Bool bMov; + sal_Bool bSize; + Point aOfs; + double fScaleX; + double fScaleY; + Fraction aScaleX; + Fraction aScaleY; + + sal_Bool bFntDirty; + + // fuer Optimierung von (PenNULL,Brush,DrawPoly),(Pen,BrushNULL,DrawPoly) -> aus 2 mach ein + sal_Bool bLastObjWasPolyWithoutLine; + sal_Bool bNoLine; + sal_Bool bNoFill; + + // fuer Optimierung mehrerer Linien zu einer Polyline + sal_Bool bLastObjWasLine; + +protected: + void DoAction(MetaPixelAction & rAct); + void DoAction(MetaPointAction & rAct); + void DoAction(MetaLineAction & rAct); + void DoAction(MetaRectAction & rAct); + void DoAction(MetaRoundRectAction & rAct); + void DoAction(MetaEllipseAction & rAct); + void DoAction(MetaArcAction & rAct); + void DoAction(MetaPieAction & rAct); + void DoAction(MetaChordAction & rAct); + void DoAction(MetaPolyLineAction & rAct); + void DoAction(MetaPolygonAction & rAct); + void DoAction(MetaPolyPolygonAction & rAct); + void DoAction(MetaTextAction & rAct); + void DoAction(MetaTextArrayAction & rAct); + void DoAction(MetaStretchTextAction & rAct); + void DoAction(MetaBmpAction & rAct); + void DoAction(MetaBmpScaleAction & rAct); + void DoAction(MetaBmpExAction & rAct); + void DoAction(MetaBmpExScaleAction & rAct); + void DoAction(MetaHatchAction & rAct); + void DoAction(MetaLineColorAction & rAct); + void DoAction(MetaMapModeAction & rAct); + void DoAction(MetaFillColorAction & rAct) { rAct.Execute(&aVD); } + void DoAction(MetaTextColorAction & rAct) { rAct.Execute(&aVD); } + void DoAction(MetaTextFillColorAction & rAct) { rAct.Execute(&aVD); } + void DoAction(MetaFontAction & rAct) { rAct.Execute(&aVD); bFntDirty=TRUE; } + void DoAction(MetaTextAlignAction & rAct) { rAct.Execute(&aVD); bFntDirty=TRUE; } + void DoAction(MetaClipRegionAction & rAct) { rAct.Execute(&aVD); } + void DoAction(MetaRasterOpAction & rAct) { rAct.Execute(&aVD); } + void DoAction(MetaPushAction & rAct) { rAct.Execute(&aVD); } + void DoAction(MetaPopAction & rAct) { rAct.Execute(&aVD); bFntDirty=TRUE; } + void DoAction(MetaMoveClipRegionAction & rAct) { rAct.Execute(&aVD); } + void DoAction(MetaISectRectClipRegionAction& rAct) { rAct.Execute(&aVD); } + void DoAction(MetaISectRegionClipRegionAction& rAct) { rAct.Execute(&aVD); } + void DoAction(MetaCommentAction& rAct, GDIMetaFile* pMtf); + + void ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct ); + void SetAttributes(SdrObject* pObj, FASTBOOL bForceTextAttr=FALSE); + void InsertObj( SdrObject* pObj, sal_Bool bScale = sal_True ); + void MapScaling(); + + // #i73407# reformulation to use new B2DPolygon classes + bool CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly); + bool CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon& rPolyPolygon); + +public: + ImpSdrGDIMetaFileImport(SdrModel& rModel); + ~ImpSdrGDIMetaFileImport(); + ULONG DoImport(const GDIMetaFile& rMtf, SdrObjList& rDestList, ULONG nInsPos=CONTAINER_APPEND, SvdProgressInfo *pProgrInfo = NULL); + void SetLayer(SdrLayerID nLay) { nLayer=nLay; } + SdrLayerID GetLayer() const { return nLayer; } + void SetScaleRect(const Rectangle& rRect) { aScaleRect=rRect; } + const Rectangle& GetScaleRect() const { return aScaleRect; } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif //_SVDFMTF_HXX +// eof diff --git a/svx/source/svdraw/svdglev.cxx b/svx/source/svdraw/svdglev.cxx new file mode 100644 index 000000000000..6eab2ea7ecfa --- /dev/null +++ b/svx/source/svdraw/svdglev.cxx @@ -0,0 +1,422 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdglev.hxx> +#include <math.h> + +#include <svx/svdundo.hxx> +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include <svx/svdpagv.hxx> +#include <svx/svdglue.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdobj.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrGlueEditView::ImpClearVars() +{ +} + +SdrGlueEditView::SdrGlueEditView(SdrModel* pModel1, OutputDevice* pOut): + SdrPolyEditView(pModel1,pOut) +{ + ImpClearVars(); +} + +SdrGlueEditView::~SdrGlueEditView() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrGlueEditView::ImpDoMarkedGluePoints(PGlueDoFunc pDoFunc, BOOL bConst, const void* p1, const void* p2, const void* p3, const void* p4, const void* p5) +{ + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + ULONG nPtAnz=pPts==NULL ? 0 : pPts->GetCount(); + if (nPtAnz!=0) { + SdrGluePointList* pGPL=NULL; + if (bConst) { + const SdrGluePointList* pConstGPL=pObj->GetGluePointList(); + pGPL=(SdrGluePointList*)pConstGPL; + } else { + pGPL=pObj->ForceGluePointList(); + } + if (pGPL!=NULL) + { + if(!bConst && IsUndoEnabled() ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + + for (ULONG nPtNum=0; nPtNum<nPtAnz; nPtNum++) + { + USHORT nPtId=pPts->GetObject(nPtNum); + USHORT nGlueIdx=pGPL->FindGluePoint(nPtId); + if (nGlueIdx!=SDRGLUEPOINT_NOTFOUND) + { + SdrGluePoint& rGP=(*pGPL)[nGlueIdx]; + (*pDoFunc)(rGP,pObj,p1,p2,p3,p4,p5); + } + } + if (!bConst) + { + pObj->SetChanged(); + pObj->BroadcastObjectChange(); + } + } + } + } + if (!bConst && nMarkAnz!=0) pMod->SetChanged(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpGetEscDir(SdrGluePoint& rGP, const SdrObject* /*pObj*/, const void* pbFirst, const void* pnThisEsc, const void* pnRet, const void*, const void*) +{ + USHORT& nRet=*(USHORT*)pnRet; + BOOL& bFirst=*(BOOL*)pbFirst; + if (nRet!=FUZZY) { + USHORT nEsc=rGP.GetEscDir(); + BOOL bOn=(nEsc & *(USHORT*)pnThisEsc)!=0; + if (bFirst) { nRet=bOn; bFirst=FALSE; } + else if (nRet!=bOn) nRet=FUZZY; + } +} + +TRISTATE SdrGlueEditView::IsMarkedGluePointsEscDir(USHORT nThisEsc) const +{ + ForceUndirtyMrkPnt(); + BOOL bFirst=TRUE; + USHORT nRet=FALSE; + ((SdrGlueEditView*)this)->ImpDoMarkedGluePoints(ImpGetEscDir,TRUE,&bFirst,&nThisEsc,&nRet); + return (TRISTATE)nRet; +} + +static void ImpSetEscDir(SdrGluePoint& rGP, const SdrObject* /*pObj*/, const void* pnThisEsc, const void* pbOn, const void*, const void*, const void*) +{ + USHORT nEsc=rGP.GetEscDir(); + if (*(BOOL*)pbOn) nEsc|=*(USHORT*)pnThisEsc; + else nEsc&=~*(USHORT*)pnThisEsc; + rGP.SetEscDir(nEsc); +} + +void SdrGlueEditView::SetMarkedGluePointsEscDir(USHORT nThisEsc, BOOL bOn) +{ + ForceUndirtyMrkPnt(); + BegUndo(ImpGetResStr(STR_EditSetGlueEscDir),GetDescriptionOfMarkedGluePoints()); + ImpDoMarkedGluePoints(ImpSetEscDir,FALSE,&nThisEsc,&bOn); + EndUndo(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpGetPercent(SdrGluePoint& rGP, const SdrObject* /*pObj*/, const void* pbFirst, const void* pnRet, const void*, const void*, const void*) +{ + USHORT& nRet=*(USHORT*)pnRet; + BOOL& bFirst=*(BOOL*)pbFirst; + if (nRet!=FUZZY) { + bool bOn=rGP.IsPercent(); + if (bFirst) { nRet=bOn; bFirst=FALSE; } + else if ((nRet!=0)!=bOn) nRet=FUZZY; + } +} + +TRISTATE SdrGlueEditView::IsMarkedGluePointsPercent() const +{ + ForceUndirtyMrkPnt(); + BOOL bFirst=TRUE; + USHORT nRet=TRUE; + ((SdrGlueEditView*)this)->ImpDoMarkedGluePoints(ImpGetPercent,TRUE,&bFirst,&nRet); + return (TRISTATE)nRet; +} + +static void ImpSetPercent(SdrGluePoint& rGP, const SdrObject* pObj, const void* pbOn, const void*, const void*, const void*, const void*) +{ + Point aPos(rGP.GetAbsolutePos(*pObj)); + rGP.SetPercent(*(BOOL*)pbOn); + rGP.SetAbsolutePos(aPos,*pObj); +} + +void SdrGlueEditView::SetMarkedGluePointsPercent(BOOL bOn) +{ + ForceUndirtyMrkPnt(); + BegUndo(ImpGetResStr(STR_EditSetGluePercent),GetDescriptionOfMarkedGluePoints()); + ImpDoMarkedGluePoints(ImpSetPercent,FALSE,&bOn); + EndUndo(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpGetAlign(SdrGluePoint& rGP, const SdrObject* /*pObj*/, const void* pbFirst, const void* pbDontCare, const void* pbVert, const void* pnRet, const void*) +{ + USHORT& nRet=*(USHORT*)pnRet; + BOOL& bFirst=*(BOOL*)pbFirst; + BOOL& bDontCare=*(BOOL*)pbDontCare; + BOOL bVert=*(BOOL*)pbVert; + if (!bDontCare) { + USHORT nAlg=0; + if (bVert) { + nAlg=rGP.GetVertAlign(); + } else { + nAlg=rGP.GetHorzAlign(); + } + if (bFirst) { nRet=nAlg; bFirst=FALSE; } + else if (nRet!=nAlg) { + if (bVert) { + nRet=SDRVERTALIGN_DONTCARE; + } else { + nRet=SDRHORZALIGN_DONTCARE; + } + bDontCare=TRUE; + } + } +} + +USHORT SdrGlueEditView::GetMarkedGluePointsAlign(BOOL bVert) const +{ + ForceUndirtyMrkPnt(); + BOOL bFirst=TRUE; + BOOL bDontCare=FALSE; + USHORT nRet=0; + ((SdrGlueEditView*)this)->ImpDoMarkedGluePoints(ImpGetAlign,TRUE,&bFirst,&bDontCare,&bVert,&nRet); + return nRet; +} + +static void ImpSetAlign(SdrGluePoint& rGP, const SdrObject* pObj, const void* pbVert, const void* pnAlign, const void*, const void*, const void*) +{ + Point aPos(rGP.GetAbsolutePos(*pObj)); + if (*(BOOL*)pbVert) { // bVert? + rGP.SetVertAlign(*(USHORT*)pnAlign); + } else { + rGP.SetHorzAlign(*(USHORT*)pnAlign); + } + rGP.SetAbsolutePos(aPos,*pObj); +} + +void SdrGlueEditView::SetMarkedGluePointsAlign(BOOL bVert, USHORT nAlign) +{ + ForceUndirtyMrkPnt(); + BegUndo(ImpGetResStr(STR_EditSetGlueAlign),GetDescriptionOfMarkedGluePoints()); + ImpDoMarkedGluePoints(ImpSetAlign,FALSE,&bVert,&nAlign); + EndUndo(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrGlueEditView::IsDeleteMarkedGluePointsPossible() const +{ + return HasMarkedGluePoints(); +} + +void SdrGlueEditView::DeleteMarkedGluePoints() +{ + BrkAction(); + ForceUndirtyMrkPnt(); + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditDelete),GetDescriptionOfMarkedGluePoints(),SDRREPFUNC_OBJ_DELETE); + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + ULONG nPtAnz=pPts==NULL ? 0 : pPts->GetCount(); + if (nPtAnz!=0) + { + SdrGluePointList* pGPL=pObj->ForceGluePointList(); + if (pGPL!=NULL) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + + for (ULONG nPtNum=0; nPtNum<nPtAnz; nPtNum++) + { + USHORT nPtId=pPts->GetObject(nPtNum); + USHORT nGlueIdx=pGPL->FindGluePoint(nPtId); + if (nGlueIdx!=SDRGLUEPOINT_NOTFOUND) + { + pGPL->Delete(nGlueIdx); + } + } + pObj->SetChanged(); + pObj->BroadcastObjectChange(); + } + } + } + if( bUndo ) + EndUndo(); + UnmarkAllGluePoints(); + if (nMarkAnz!=0) + pMod->SetChanged(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrGlueEditView::ImpCopyMarkedGluePoints() +{ + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + BegUndo(); + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + SdrGluePointList* pGPL=pObj->ForceGluePointList(); + ULONG nPtAnz=pPts==NULL ? 0 : pPts->GetCount(); + if (nPtAnz!=0 && pGPL!=NULL) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + + for (ULONG nPtNum=0; nPtNum<nPtAnz; nPtNum++) + { + USHORT nPtId=pPts->GetObject(nPtNum); + USHORT nGlueIdx=pGPL->FindGluePoint(nPtId); + if (nGlueIdx!=SDRGLUEPOINT_NOTFOUND) + { + SdrGluePoint aNewGP((*pGPL)[nGlueIdx]); // GluePoint klonen + USHORT nNewIdx=pGPL->Insert(aNewGP); // und einfuegen + USHORT nNewId=(*pGPL)[nNewIdx].GetId(); // Id des neuen GluePoints ermitteln + pPts->Replace(nNewId,nPtNum); // und diesen markieren (anstelle des alten) + } + } + } + } + if( bUndo ) + EndUndo(); + + if (nMarkAnz!=0) + pMod->SetChanged(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrGlueEditView::ImpTransformMarkedGluePoints(PGlueTrFunc pTrFunc, const void* p1, const void* p2, const void* p3, const void* p4, const void* p5) +{ + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + ULONG nPtAnz=pPts==NULL ? 0 : pPts->GetCount(); + if (nPtAnz!=0) { + SdrGluePointList* pGPL=pObj->ForceGluePointList(); + if (pGPL!=NULL) + { + if( IsUndoEnabled() ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + + for (ULONG nPtNum=0; nPtNum<nPtAnz; nPtNum++) { + USHORT nPtId=pPts->GetObject(nPtNum); + USHORT nGlueIdx=pGPL->FindGluePoint(nPtId); + if (nGlueIdx!=SDRGLUEPOINT_NOTFOUND) { + SdrGluePoint& rGP=(*pGPL)[nGlueIdx]; + Point aPos(rGP.GetAbsolutePos(*pObj)); + (*pTrFunc)(aPos,p1,p2,p3,p4,p5); + rGP.SetAbsolutePos(aPos,*pObj); + } + } + pObj->SetChanged(); + pObj->BroadcastObjectChange(); + } + } + } + if (nMarkAnz!=0) pMod->SetChanged(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpMove(Point& rPt, const void* p1, const void* /*p2*/, const void* /*p3*/, const void* /*p4*/, const void* /*p5*/) +{ + rPt.X()+=((const Size*)p1)->Width(); + rPt.Y()+=((const Size*)p1)->Height(); +} + +void SdrGlueEditView::MoveMarkedGluePoints(const Size& rSiz, bool bCopy) +{ + ForceUndirtyMrkPnt(); + XubString aStr(ImpGetResStr(STR_EditMove)); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr,GetDescriptionOfMarkedGluePoints(),SDRREPFUNC_OBJ_MOVE); + if (bCopy) ImpCopyMarkedGluePoints(); + ImpTransformMarkedGluePoints(ImpMove,&rSiz); + EndUndo(); + AdjustMarkHdl(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpResize(Point& rPt, const void* p1, const void* p2, const void* p3, const void* /*p4*/, const void* /*p5*/) +{ + ResizePoint(rPt,*(const Point*)p1,*(const Fraction*)p2,*(const Fraction*)p3); +} + +void SdrGlueEditView::ResizeMarkedGluePoints(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy) +{ + ForceUndirtyMrkPnt(); + XubString aStr(ImpGetResStr(STR_EditResize)); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr,GetDescriptionOfMarkedGluePoints(),SDRREPFUNC_OBJ_RESIZE); + if (bCopy) ImpCopyMarkedGluePoints(); + ImpTransformMarkedGluePoints(ImpResize,&rRef,&xFact,&yFact); + EndUndo(); + AdjustMarkHdl(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpRotate(Point& rPt, const void* p1, const void* /*p2*/, const void* p3, const void* p4, const void* /*p5*/) +{ + RotatePoint(rPt,*(const Point*)p1,*(const double*)p3,*(const double*)p4); +} + +void SdrGlueEditView::RotateMarkedGluePoints(const Point& rRef, long nWink, bool bCopy) +{ + ForceUndirtyMrkPnt(); + XubString aStr(ImpGetResStr(STR_EditRotate)); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr,GetDescriptionOfMarkedGluePoints(),SDRREPFUNC_OBJ_ROTATE); + if (bCopy) ImpCopyMarkedGluePoints(); + double nSin=sin(nWink*nPi180); + double nCos=cos(nWink*nPi180); + ImpTransformMarkedGluePoints(ImpRotate,&rRef,&nWink,&nSin,&nCos); + EndUndo(); + AdjustMarkHdl(); +} + diff --git a/svx/source/svdraw/svdglue.cxx b/svx/source/svdraw/svdglue.cxx new file mode 100644 index 000000000000..634d7060e735 --- /dev/null +++ b/svx/source/svdraw/svdglue.cxx @@ -0,0 +1,450 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <tools/debug.hxx> + +#include <svx/svdglue.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdtrans.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrGluePoint::SetReallyAbsolute(FASTBOOL bOn, const SdrObject& rObj) +{ + if ( bReallyAbsolute != bOn ) + { + if ( bOn ) + { + aPos=GetAbsolutePos(rObj); + bReallyAbsolute=bOn; + } + else + { + bReallyAbsolute=bOn; + Point aPt(aPos); + SetAbsolutePos(aPt,rObj); + } + } +} + +Point SdrGluePoint::GetAbsolutePos(const SdrObject& rObj) const +{ + if (bReallyAbsolute) return aPos; + Rectangle aSnap(rObj.GetSnapRect()); + Rectangle aBound(rObj.GetSnapRect()); + Point aPt(aPos); + + Point aOfs(aSnap.Center()); + switch (GetHorzAlign()) { + case SDRHORZALIGN_LEFT : aOfs.X()=aSnap.Left(); break; + case SDRHORZALIGN_RIGHT : aOfs.X()=aSnap.Right(); break; + } + switch (GetVertAlign()) { + case SDRVERTALIGN_TOP : aOfs.Y()=aSnap.Top(); break; + case SDRVERTALIGN_BOTTOM: aOfs.Y()=aSnap.Bottom(); break; + } + if (!bNoPercent) { + long nXMul=aSnap.Right()-aSnap.Left(); + long nYMul=aSnap.Bottom()-aSnap.Top(); + long nXDiv=10000; + long nYDiv=10000; + if (nXMul!=nXDiv) { + aPt.X()*=nXMul; + aPt.X()/=nXDiv; + } + if (nYMul!=nYDiv) { + aPt.Y()*=nYMul; + aPt.Y()/=nYDiv; + } + } + aPt+=aOfs; + // Und nun auf's BoundRect des Objekts begrenzen + if (aPt.X()<aBound.Left ()) aPt.X()=aBound.Left (); + if (aPt.X()>aBound.Right ()) aPt.X()=aBound.Right (); + if (aPt.Y()<aBound.Top ()) aPt.Y()=aBound.Top (); + if (aPt.Y()>aBound.Bottom()) aPt.Y()=aBound.Bottom(); + return aPt; +} + +void SdrGluePoint::SetAbsolutePos(const Point& rNewPos, const SdrObject& rObj) +{ + if (bReallyAbsolute) { + aPos=rNewPos; + return; + } + Rectangle aSnap(rObj.GetSnapRect()); + Point aPt(rNewPos); + + Point aOfs(aSnap.Center()); + switch (GetHorzAlign()) { + case SDRHORZALIGN_LEFT : aOfs.X()=aSnap.Left(); break; + case SDRHORZALIGN_RIGHT : aOfs.X()=aSnap.Right(); break; + } + switch (GetVertAlign()) { + case SDRVERTALIGN_TOP : aOfs.Y()=aSnap.Top(); break; + case SDRVERTALIGN_BOTTOM: aOfs.Y()=aSnap.Bottom(); break; + } + aPt-=aOfs; + if (!bNoPercent) { + long nXMul=aSnap.Right()-aSnap.Left(); + long nYMul=aSnap.Bottom()-aSnap.Top(); + if (nXMul==0) nXMul=1; + if (nYMul==0) nYMul=1; + long nXDiv=10000; + long nYDiv=10000; + if (nXMul!=nXDiv) { + aPt.X()*=nXDiv; + aPt.X()/=nXMul; + } + if (nYMul!=nYDiv) { + aPt.Y()*=nYDiv; + aPt.Y()/=nYMul; + } + } + aPos=aPt; +} + +long SdrGluePoint::GetAlignAngle() const +{ + switch (nAlign) { + case SDRHORZALIGN_CENTER|SDRVERTALIGN_CENTER: return 0; // Invalid! + case SDRHORZALIGN_RIGHT |SDRVERTALIGN_CENTER: return 0; + case SDRHORZALIGN_RIGHT |SDRVERTALIGN_TOP : return 4500; + case SDRHORZALIGN_CENTER|SDRVERTALIGN_TOP : return 9000; + case SDRHORZALIGN_LEFT |SDRVERTALIGN_TOP : return 13500; + case SDRHORZALIGN_LEFT |SDRVERTALIGN_CENTER: return 18000; + case SDRHORZALIGN_LEFT |SDRVERTALIGN_BOTTOM: return 22500; + case SDRHORZALIGN_CENTER|SDRVERTALIGN_BOTTOM: return 27000; + case SDRHORZALIGN_RIGHT |SDRVERTALIGN_BOTTOM: return 31500; + } // switch + return 0; +} + +void SdrGluePoint::SetAlignAngle(long nWink) +{ + nWink=NormAngle360(nWink); + if (nWink>=33750 || nWink<2250) nAlign=SDRHORZALIGN_RIGHT |SDRVERTALIGN_CENTER; + else if (nWink< 6750) nAlign=SDRHORZALIGN_RIGHT |SDRVERTALIGN_TOP ; + else if (nWink<11250) nAlign=SDRHORZALIGN_CENTER|SDRVERTALIGN_TOP ; + else if (nWink<15750) nAlign=SDRHORZALIGN_LEFT |SDRVERTALIGN_TOP ; + else if (nWink<20250) nAlign=SDRHORZALIGN_LEFT |SDRVERTALIGN_CENTER; + else if (nWink<24750) nAlign=SDRHORZALIGN_LEFT |SDRVERTALIGN_BOTTOM; + else if (nWink<29250) nAlign=SDRHORZALIGN_CENTER|SDRVERTALIGN_BOTTOM; + else if (nWink<33750) nAlign=SDRHORZALIGN_RIGHT |SDRVERTALIGN_BOTTOM; +} + +long SdrGluePoint::EscDirToAngle(USHORT nEsc) const +{ + switch (nEsc) { + case SDRESC_RIGHT : return 0; + case SDRESC_TOP : return 9000; + case SDRESC_LEFT : return 18000; + case SDRESC_BOTTOM: return 27000; + } // switch + return 0; +} + +USHORT SdrGluePoint::EscAngleToDir(long nWink) const +{ + nWink=NormAngle360(nWink); + if (nWink>=31500 || nWink<4500) return SDRESC_RIGHT; + if (nWink<13500) return SDRESC_TOP; + if (nWink<22500) return SDRESC_LEFT; + if (nWink<31500) return SDRESC_BOTTOM; + return 0; +} + +void SdrGluePoint::Rotate(const Point& rRef, long nWink, double sn, double cs, const SdrObject* pObj) +{ + Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos()); + RotatePoint(aPt,rRef,sn,cs); + // Bezugskante drehen + if(nAlign != (SDRHORZALIGN_CENTER|SDRVERTALIGN_CENTER)) + { + SetAlignAngle(GetAlignAngle()+nWink); + } + // Austrittsrichtungen drehen + USHORT nEscDir0=nEscDir; + USHORT nEscDir1=0; + if ((nEscDir0&SDRESC_LEFT )!=0) nEscDir1|=EscAngleToDir(EscDirToAngle(SDRESC_LEFT )+nWink); + if ((nEscDir0&SDRESC_TOP )!=0) nEscDir1|=EscAngleToDir(EscDirToAngle(SDRESC_TOP )+nWink); + if ((nEscDir0&SDRESC_RIGHT )!=0) nEscDir1|=EscAngleToDir(EscDirToAngle(SDRESC_RIGHT )+nWink); + if ((nEscDir0&SDRESC_BOTTOM)!=0) nEscDir1|=EscAngleToDir(EscDirToAngle(SDRESC_BOTTOM)+nWink); + nEscDir=nEscDir1; + if (pObj!=NULL) SetAbsolutePos(aPt,*pObj); else SetPos(aPt); +} + +void SdrGluePoint::Mirror(const Point& rRef1, const Point& rRef2, const SdrObject* pObj) +{ + Point aPt(rRef2); aPt-=rRef1; + long nWink=GetAngle(aPt); + Mirror(rRef1,rRef2,nWink,pObj); +} + +void SdrGluePoint::Mirror(const Point& rRef1, const Point& rRef2, long nWink, const SdrObject* pObj) +{ + Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos()); + MirrorPoint(aPt,rRef1,rRef2); + // Bezugskante spiegeln + if(nAlign != (SDRHORZALIGN_CENTER|SDRVERTALIGN_CENTER)) + { + long nAW=GetAlignAngle(); + nAW+=2*(nWink-nAW); + SetAlignAngle(nAW); + } + // Austrittsrichtungen spiegeln + USHORT nEscDir0=nEscDir; + USHORT nEscDir1=0; + if ((nEscDir0&SDRESC_LEFT)!=0) { + long nEW=EscDirToAngle(SDRESC_LEFT); + nEW+=2*(nWink-nEW); + nEscDir1|=EscAngleToDir(nEW); + } + if ((nEscDir0&SDRESC_TOP)!=0) { + long nEW=EscDirToAngle(SDRESC_TOP); + nEW+=2*(nWink-nEW); + nEscDir1|=EscAngleToDir(nEW); + } + if ((nEscDir0&SDRESC_RIGHT)!=0) { + long nEW=EscDirToAngle(SDRESC_RIGHT); + nEW+=2*(nWink-nEW); + nEscDir1|=EscAngleToDir(nEW); + } + if ((nEscDir0&SDRESC_BOTTOM)!=0) { + long nEW=EscDirToAngle(SDRESC_BOTTOM); + nEW+=2*(nWink-nEW); + nEscDir1|=EscAngleToDir(nEW); + } + nEscDir=nEscDir1; + if (pObj!=NULL) SetAbsolutePos(aPt,*pObj); else SetPos(aPt); +} + +void SdrGluePoint::Shear(const Point& rRef, long /*nWink*/, double tn, FASTBOOL bVShear, const SdrObject* pObj) +{ + Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos()); + ShearPoint(aPt,rRef,tn,bVShear); + if (pObj!=NULL) SetAbsolutePos(aPt,*pObj); else SetPos(aPt); +} + +void SdrGluePoint::Draw(OutputDevice& rOut, const SdrObject* pObj) const +{ + Color aBackPenColor(COL_WHITE); + Color aForePenColor(COL_LIGHTBLUE); + + bool bMapMerk=rOut.IsMapModeEnabled(); + Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos()); + aPt=rOut.LogicToPixel(aPt); + rOut.EnableMapMode(FALSE); + long x=aPt.X(),y=aPt.Y(); // Groesse erstmal fest auf 7 Pixel + + rOut.SetLineColor( aBackPenColor ); + rOut.DrawLine(Point(x-2,y-3),Point(x+3,y+2)); + rOut.DrawLine(Point(x-3,y-2),Point(x+2,y+3)); + rOut.DrawLine(Point(x-3,y+2),Point(x+2,y-3)); + rOut.DrawLine(Point(x-2,y+3),Point(x+3,y-2)); + + if (bNoPercent) + { + switch (GetHorzAlign()) + { + case SDRHORZALIGN_LEFT : rOut.DrawLine(Point(x-3,y-1),Point(x-3,y+1)); break; + case SDRHORZALIGN_RIGHT : rOut.DrawLine(Point(x+3,y-1),Point(x+3,y+1)); break; + } + + switch (GetVertAlign()) + { + case SDRVERTALIGN_TOP : rOut.DrawLine(Point(x-1,y-3),Point(x+1,y-3)); break; + case SDRVERTALIGN_BOTTOM: rOut.DrawLine(Point(x-1,y+3),Point(x+1,y+3)); break; + } + } + + rOut.SetLineColor( aForePenColor ); + rOut.DrawLine(Point(x-2,y-2),Point(x+2,y+2)); + rOut.DrawLine(Point(x-2,y+2),Point(x+2,y-2)); + rOut.EnableMapMode(bMapMerk); +} + +void SdrGluePoint::Invalidate(Window& rWin, const SdrObject* pObj) const +{ + bool bMapMerk=rWin.IsMapModeEnabled(); + Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos()); + aPt=rWin.LogicToPixel(aPt); + rWin.EnableMapMode(FALSE); + long x=aPt.X(),y=aPt.Y(); // Groesse erstmal fest auf 7 Pixel + + // #111096# + // do not erase background, that causes flicker (!) + rWin.Invalidate(Rectangle(Point(x-3,y-3),Point(x+3,y+3)), INVALIDATE_NOERASE); + + rWin.EnableMapMode(bMapMerk); +} + +FASTBOOL SdrGluePoint::IsHit(const Point& rPnt, const OutputDevice& rOut, const SdrObject* pObj) const +{ + Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos()); + Size aSiz=rOut.PixelToLogic(Size(3,3)); + Rectangle aRect(aPt.X()-aSiz.Width(),aPt.Y()-aSiz.Height(),aPt.X()+aSiz.Width(),aPt.Y()+aSiz.Height()); + return aRect.IsInside(rPnt); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrGluePointList::Clear() +{ + USHORT nAnz=GetCount(); + for (USHORT i=0; i<nAnz; i++) { + delete GetObject(i); + } + aList.Clear(); +} + +void SdrGluePointList::operator=(const SdrGluePointList& rSrcList) +{ + if (GetCount()!=0) Clear(); + USHORT nAnz=rSrcList.GetCount(); + for (USHORT i=0; i<nAnz; i++) { + Insert(rSrcList[i]); + } +} + +// Die Id's der Klebepunkte in der Liste sind stets streng monoton steigend! +// Ggf. wird dem neuen Klebepunkt eine neue Id zugewiesen (wenn diese bereits +// vergeben ist). Die Id 0 ist reserviert. +USHORT SdrGluePointList::Insert(const SdrGluePoint& rGP) +{ + SdrGluePoint* pGP=new SdrGluePoint(rGP); + USHORT nId=pGP->GetId(); + USHORT nAnz=GetCount(); + USHORT nInsPos=nAnz; + USHORT nLastId=nAnz!=0 ? GetObject(nAnz-1)->GetId() : 0; + DBG_ASSERT(nLastId>=nAnz,"SdrGluePointList::Insert(): nLastId<nAnz"); + FASTBOOL bHole=nLastId>nAnz; + if (nId<=nLastId) { + if (!bHole || nId==0) { + nId=nLastId+1; + } else { + FASTBOOL bBrk=FALSE; + for (USHORT nNum=0; nNum<nAnz && !bBrk; nNum++) { + const SdrGluePoint* pGP2=GetObject(nNum); + USHORT nTmpId=pGP2->GetId(); + if (nTmpId==nId) { + nId=nLastId+1; // bereits vorhanden + bBrk=TRUE; + } + if (nTmpId>nId) { + nInsPos=nNum; // Hier einfuegen (einsortieren) + bBrk=TRUE; + } + } + } + pGP->SetId(nId); + } + aList.Insert(pGP,nInsPos); + return nInsPos; +} + +void SdrGluePointList::Invalidate(Window& rWin, const SdrObject* pObj) const +{ + USHORT nAnz=GetCount(); + for (USHORT nNum=0; nNum<nAnz; nNum++) { + GetObject(nNum)->Invalidate(rWin,pObj); + } +} + +USHORT SdrGluePointList::FindGluePoint(USHORT nId) const +{ + // Hier noch einen optimaleren Suchalgorithmus implementieren. + // Die Liste sollte stets sortiert sein!!!! + USHORT nAnz=GetCount(); + USHORT nRet=SDRGLUEPOINT_NOTFOUND; + for (USHORT nNum=0; nNum<nAnz && nRet==SDRGLUEPOINT_NOTFOUND; nNum++) { + const SdrGluePoint* pGP=GetObject(nNum); + if (pGP->GetId()==nId) nRet=nNum; + } + return nRet; +} + +USHORT SdrGluePointList::HitTest(const Point& rPnt, const OutputDevice& rOut, const SdrObject* pObj, FASTBOOL bBack, FASTBOOL bNext, USHORT nId0) const +{ + USHORT nAnz=GetCount(); + USHORT nRet=SDRGLUEPOINT_NOTFOUND; + USHORT nNum=bBack ? 0 : nAnz; + while ((bBack ? nNum<nAnz : nNum>0) && nRet==SDRGLUEPOINT_NOTFOUND) { + if (!bBack) nNum--; + const SdrGluePoint* pGP=GetObject(nNum); + if (bNext) { + if (pGP->GetId()==nId0) bNext=FALSE; + } else { + if (pGP->IsHit(rPnt,rOut,pObj)) nRet=nNum; + } + if (bBack) nNum++; + } + return nRet; +} + +void SdrGluePointList::SetReallyAbsolute(FASTBOOL bOn, const SdrObject& rObj) +{ + USHORT nAnz=GetCount(); + for (USHORT nNum=0; nNum<nAnz; nNum++) { + GetObject(nNum)->SetReallyAbsolute(bOn,rObj); + } +} + +void SdrGluePointList::Rotate(const Point& rRef, long nWink, double sn, double cs, const SdrObject* pObj) +{ + USHORT nAnz=GetCount(); + for (USHORT nNum=0; nNum<nAnz; nNum++) { + GetObject(nNum)->Rotate(rRef,nWink,sn,cs,pObj); + } +} + +void SdrGluePointList::Mirror(const Point& rRef1, const Point& rRef2, const SdrObject* pObj) +{ + Point aPt(rRef2); aPt-=rRef1; + long nWink=GetAngle(aPt); + Mirror(rRef1,rRef2,nWink,pObj); +} + +void SdrGluePointList::Mirror(const Point& rRef1, const Point& rRef2, long nWink, const SdrObject* pObj) +{ + USHORT nAnz=GetCount(); + for (USHORT nNum=0; nNum<nAnz; nNum++) { + GetObject(nNum)->Mirror(rRef1,rRef2,nWink,pObj); + } +} + +void SdrGluePointList::Shear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear, const SdrObject* pObj) +{ + USHORT nAnz=GetCount(); + for (USHORT nNum=0; nNum<nAnz; nNum++) { + GetObject(nNum)->Shear(rRef,nWink,tn,bVShear,pObj); + } +} + +// eof diff --git a/svx/source/svdraw/svdhdl.cxx b/svx/source/svdraw/svdhdl.cxx new file mode 100644 index 000000000000..47a04241e5bb --- /dev/null +++ b/svx/source/svdraw/svdhdl.cxx @@ -0,0 +1,2417 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <algorithm> + +#include <svx/svdhdl.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdmrkv.hxx> +#include <vcl/window.hxx> + +#include <vcl/virdev.hxx> +#include <tools/poly.hxx> +#include <vcl/bmpacc.hxx> + +#include <svx/sxekitm.hxx> +#include "svdstr.hrc" +#include "svdglob.hxx" + +#include <svx/svdmodel.hxx> +#include "gradtrns.hxx" +#include <svx/xflgrit.hxx> +#include <svx/svdundo.hxx> +#include <svx/dialmgr.hxx> +#include <svx/xflftrit.hxx> + +// #105678# +#include <svx/svdopath.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/sdr/overlay/overlayanimatedbitmapex.hxx> +#include <svx/sdr/overlay/overlaybitmapex.hxx> +#include <svx/sdr/overlay/overlayline.hxx> +#include <svx/sdr/overlay/overlaytriangle.hxx> +#include <svx/sdr/overlay/overlayhatchrect.hxx> +#include <svx/sdrpagewindow.hxx> +#include <sdrpaintwindow.hxx> +#include <vcl/svapp.hxx> +#include <svx/sdr/overlay/overlaypolypolygon.hxx> +#include <vcl/lazydelete.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i15222# +// Due to the ressource problems in Win95/98 with bitmap ressources i +// will change this handle bitmap provinging class. Old version was splitting +// and preparing all small handle bitmaps in device bitmap format, now this will +// be done on the fly. Thus, tehre is only the one big bitmap remembered. With +// three source bitmaps, this will be 3 system bitmap ressources instead of hundreds. +// The price for that needs to be evaluated. Maybe we will need another change here +// if this is too expensive. +class SdrHdlBitmapSet +{ + // the bitmap holding all infos + BitmapEx maMarkersBitmap; + + // the cropped Bitmaps for reusage + ::std::vector< BitmapEx > maRealMarkers; + + // elpers + BitmapEx& impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const Rectangle& rRectangle); + +public: + SdrHdlBitmapSet(UINT16 nResId); + ~SdrHdlBitmapSet(); + + const BitmapEx& GetBitmapEx(BitmapMarkerKind eKindOfMarker, UINT16 nInd=0); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#define KIND_COUNT (14) +#define INDEX_COUNT (6) +#define INDIVIDUAL_COUNT (4) + +SdrHdlBitmapSet::SdrHdlBitmapSet(UINT16 nResId) +: maMarkersBitmap(), + // 14 kinds (BitmapMarkerKind) use index [0..5], 4 extra + maRealMarkers((KIND_COUNT * INDEX_COUNT) + INDIVIDUAL_COUNT) +{ + // #101928# change color used for transparent parts to 0x00ff00ff (ImageList standard) + const Color aColTransparent(0x00ff00ff); + const Bitmap aBitmap(ResId(nResId, *ImpGetResMgr())); + const Bitmap aMask(aBitmap.CreateMask(aColTransparent)); + + // create a real BitmapEx with an AlphaMask + maMarkersBitmap = BitmapEx(aBitmap, aMask); + // maMarkersBitmap = BitmapEx(aBitmap, aColTransparent); +} + +SdrHdlBitmapSet::~SdrHdlBitmapSet() +{ +} + +BitmapEx& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const Rectangle& rRectangle) +{ + BitmapEx& rTargetBitmap = maRealMarkers[nIndex]; + + if(rTargetBitmap.IsEmpty()) + { + rTargetBitmap = maMarkersBitmap; + rTargetBitmap.Crop(rRectangle); + } + + return rTargetBitmap; +} + +// change getting of bitmap to use the big ressource bitmap +const BitmapEx& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker, UINT16 nInd) +{ + // fill in size and source position in maMarkersBitmap + const sal_uInt16 nYPos(nInd * 11); + + switch(eKindOfMarker) + { + default: + { + DBG_ERROR( "unknown kind of marker" ); + // no break here, return Rect_7x7 as default + } + case Rect_7x7: + { + return impGetOrCreateTargetBitmap((0 * INDEX_COUNT) + nInd, Rectangle(Point(0, nYPos), Size(7, 7))); + } + + case Rect_9x9: + { + return impGetOrCreateTargetBitmap((1 * INDEX_COUNT) + nInd, Rectangle(Point(7, nYPos), Size(9, 9))); + } + + case Rect_11x11: + { + return impGetOrCreateTargetBitmap((2 * INDEX_COUNT) + nInd, Rectangle(Point(16, nYPos), Size(11, 11))); + } + + case Rect_13x13: + { + const sal_uInt16 nIndex((3 * INDEX_COUNT) + nInd); + + switch(nInd) + { + case 0: + { + return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(72, 66), Size(13, 13))); + } + case 1: + { + return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(85, 66), Size(13, 13))); + } + case 2: + { + return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(72, 78), Size(13, 13))); + } + case 3: + { + return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(85, 78), Size(13, 13))); + } + case 4: + { + return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(98, 78), Size(13, 13))); + } + default: // case 5: + { + return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(98, 66), Size(13, 13))); + } + } + } + + case Circ_7x7: + { + return impGetOrCreateTargetBitmap((4 * INDEX_COUNT) + nInd, Rectangle(Point(27, nYPos), Size(7, 7))); + } + + case Circ_9x9: + case Customshape1: + { + return impGetOrCreateTargetBitmap((5 * INDEX_COUNT) + nInd, Rectangle(Point(34, nYPos), Size(9, 9))); + } + + case Circ_11x11: + { + return impGetOrCreateTargetBitmap((6 * INDEX_COUNT) + nInd, Rectangle(Point(43, nYPos), Size(11, 11))); + } + + case Elli_7x9: + { + return impGetOrCreateTargetBitmap((7 * INDEX_COUNT) + nInd, Rectangle(Point(54, nYPos), Size(7, 9))); + } + + case Elli_9x11: + { + return impGetOrCreateTargetBitmap((8 * INDEX_COUNT) + nInd, Rectangle(Point(61, nYPos), Size(9, 11))); + } + + case Elli_9x7: + { + return impGetOrCreateTargetBitmap((9 * INDEX_COUNT) + nInd, Rectangle(Point(70, nYPos), Size(9, 7))); + } + + case Elli_11x9: + { + return impGetOrCreateTargetBitmap((10 * INDEX_COUNT) + nInd, Rectangle(Point(79, nYPos), Size(11, 9))); + } + + case RectPlus_7x7: + { + return impGetOrCreateTargetBitmap((11 * INDEX_COUNT) + nInd, Rectangle(Point(90, nYPos), Size(7, 7))); + } + + case RectPlus_9x9: + { + return impGetOrCreateTargetBitmap((12 * INDEX_COUNT) + nInd, Rectangle(Point(97, nYPos), Size(9, 9))); + } + + case RectPlus_11x11: + { + return impGetOrCreateTargetBitmap((13 * INDEX_COUNT) + nInd, Rectangle(Point(106, nYPos), Size(11, 11))); + } + + case Crosshair: + { + return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 0, Rectangle(Point(0, 68), Size(15, 15))); + } + + case Glue: + { + return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 1, Rectangle(Point(15, 74), Size(9, 9))); + } + + case Anchor: // #101688# AnchorTR for SW + case AnchorTR: + { + return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 2, Rectangle(Point(24, 68), Size(24, 23))); + } + + // #98388# add AnchorPressed to be able to aninate anchor control + case AnchorPressed: + case AnchorPressedTR: + { + return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 3, Rectangle(Point(48, 68), Size(24, 23))); + } + } + + // cannot happen since all pathes return something; return Rect_7x7 as default (see switch) + return maRealMarkers[0]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrHdlBitmapSet& getSimpleSet() +{ + static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aSimpleSet(new SdrHdlBitmapSet(SIP_SA_MARKERS)); + return *aSimpleSet.get(); +} + +SdrHdlBitmapSet& getModernSet() +{ + static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aModernSet(new SdrHdlBitmapSet(SIP_SA_FINE_MARKERS)); + return *aModernSet.get(); +} + +SdrHdlBitmapSet& getHighContrastSet() +{ + static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aHighContrastSet(new SdrHdlBitmapSet(SIP_SA_ACCESSIBILITY_MARKERS)); + return *aHighContrastSet.get(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrHdl::SdrHdl(): + pObj(NULL), + pPV(NULL), + pHdlList(NULL), + eKind(HDL_MOVE), + nDrehWink(0), + nObjHdlNum(0), + nPolyNum(0), + nPPntNum(0), + nSourceHdlNum(0), + bSelect(FALSE), + b1PixMore(FALSE), + bPlusHdl(FALSE), + mbMoveOutside(false), + mbMouseOver(false) +{ +} + +SdrHdl::SdrHdl(const Point& rPnt, SdrHdlKind eNewKind): + pObj(NULL), + pPV(NULL), + pHdlList(NULL), + aPos(rPnt), + eKind(eNewKind), + nDrehWink(0), + nObjHdlNum(0), + nPolyNum(0), + nPPntNum(0), + nSourceHdlNum(0), + bSelect(FALSE), + b1PixMore(FALSE), + bPlusHdl(FALSE), + mbMoveOutside(false), + mbMouseOver(false) +{ +} + +SdrHdl::~SdrHdl() +{ + GetRidOfIAObject(); +} + +void SdrHdl::Set1PixMore(BOOL bJa) +{ + if(b1PixMore != bJa) + { + b1PixMore = bJa; + + // create new display + Touch(); + } +} + +void SdrHdl::SetMoveOutside( bool bMoveOutside ) +{ + if(mbMoveOutside != bMoveOutside) + { + mbMoveOutside = bMoveOutside; + + // create new display + Touch(); + } +} + +void SdrHdl::SetDrehWink(long n) +{ + if(nDrehWink != n) + { + nDrehWink = n; + + // create new display + Touch(); + } +} + +void SdrHdl::SetPos(const Point& rPnt) +{ + if(aPos != rPnt) + { + // remember new position + aPos = rPnt; + + // create new display + Touch(); + } +} + +void SdrHdl::SetSelected(BOOL bJa) +{ + if(bSelect != bJa) + { + // remember new value + bSelect = bJa; + + // create new display + Touch(); + } +} + +void SdrHdl::SetHdlList(SdrHdlList* pList) +{ + if(pHdlList != pList) + { + // rememver list + pHdlList = pList; + + // now its possible to create graphic representation + Touch(); + } +} + +void SdrHdl::SetObj(SdrObject* pNewObj) +{ + if(pObj != pNewObj) + { + // remember new object + pObj = pNewObj; + + // graphic representation may have changed + Touch(); + } +} + +void SdrHdl::Touch() +{ + // force update of graphic representation + CreateB2dIAObject(); +} + +void SdrHdl::GetRidOfIAObject() +{ + //OLMaIAOGroup.Delete(); + + // OVERLAYMANAGER + maOverlayGroup.clear(); +} + +void SdrHdl::CreateB2dIAObject() +{ + // first throw away old one + GetRidOfIAObject(); + + if(pHdlList && pHdlList->GetView() && !pHdlList->GetView()->areMarkHandlesHidden()) + { + BitmapColorIndex eColIndex = LightGreen; + BitmapMarkerKind eKindOfMarker = Rect_7x7; + + BOOL bRot = pHdlList->IsRotateShear(); + if(pObj) + eColIndex = (bSelect) ? Cyan : LightCyan; + if(bRot) + { + // Drehhandles in Rot + if(pObj && bSelect) + eColIndex = Red; + else + eColIndex = LightRed; + } + + switch(eKind) + { + case HDL_MOVE: + { + eKindOfMarker = (b1PixMore) ? Rect_9x9 : Rect_7x7; + break; + } + case HDL_UPLFT: + case HDL_UPRGT: + case HDL_LWLFT: + case HDL_LWRGT: + { + // corner handles + if(bRot) + { + eKindOfMarker = Circ_7x7; + } + else + { + eKindOfMarker = Rect_7x7; + } + break; + } + case HDL_UPPER: + case HDL_LOWER: + { + // Upper/Lower handles + if(bRot) + { + eKindOfMarker = Elli_9x7; + } + else + { + eKindOfMarker = Rect_7x7; + } + break; + } + case HDL_LEFT: + case HDL_RIGHT: + { + // Left/Right handles + if(bRot) + { + eKindOfMarker = Elli_7x9; + } + else + { + eKindOfMarker = Rect_7x7; + } + break; + } + case HDL_POLY: + { + if(bRot) + { + eKindOfMarker = (b1PixMore) ? Circ_9x9 : Circ_7x7; + } + else + { + eKindOfMarker = (b1PixMore) ? Rect_9x9 : Rect_7x7; + } + break; + } + case HDL_BWGT: // weight at poly + { + eKindOfMarker = Circ_7x7; + break; + } + case HDL_CIRC: + { + eKindOfMarker = Rect_11x11; + break; + } + case HDL_REF1: + case HDL_REF2: + { + eKindOfMarker = Crosshair; + break; + } + case HDL_GLUE: + { + eKindOfMarker = Glue; + break; + } + case HDL_ANCHOR: + { + eKindOfMarker = Anchor; + break; + } + case HDL_USER: + { + break; + } + // #101688# top right anchor for SW + case HDL_ANCHOR_TR: + { + eKindOfMarker = AnchorTR; + break; + } + + // for SJ and the CustomShapeHandles: + case HDL_CUSTOMSHAPE1: + { + eKindOfMarker = Customshape1; + eColIndex = Yellow; + break; + } + default: + break; + } + + SdrMarkView* pView = pHdlList->GetView(); + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b]; + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + Point aMoveOutsideOffset(0, 0); + + // add offset if necessary + if(pHdlList->IsMoveOutside() || mbMoveOutside) + { + OutputDevice& rOutDev = rPageWindow.GetPaintWindow().GetOutputDevice(); + Size aOffset = rOutDev.PixelToLogic(Size(4, 4)); + + if(eKind == HDL_UPLFT || eKind == HDL_UPPER || eKind == HDL_UPRGT) + aMoveOutsideOffset.Y() -= aOffset.Width(); + if(eKind == HDL_LWLFT || eKind == HDL_LOWER || eKind == HDL_LWRGT) + aMoveOutsideOffset.Y() += aOffset.Height(); + if(eKind == HDL_UPLFT || eKind == HDL_LEFT || eKind == HDL_LWLFT) + aMoveOutsideOffset.X() -= aOffset.Width(); + if(eKind == HDL_UPRGT || eKind == HDL_RIGHT || eKind == HDL_LWRGT) + aMoveOutsideOffset.X() += aOffset.Height(); + } + + if(rPageWindow.GetOverlayManager()) + { + basegfx::B2DPoint aPosition(aPos.X(), aPos.Y()); + ::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject( + aPosition, + eColIndex, + eKindOfMarker, + aMoveOutsideOffset); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } +} + +BitmapMarkerKind SdrHdl::GetNextBigger(BitmapMarkerKind eKnd) const +{ + BitmapMarkerKind eRetval(eKnd); + + switch(eKnd) + { + case Rect_7x7: eRetval = Rect_9x9; break; + case Rect_9x9: eRetval = Rect_11x11; break; + case Rect_11x11: eRetval = Rect_13x13; break; + //case Rect_13x13: eRetval = ; break; + + case Circ_7x7: eRetval = Circ_9x9; break; + case Circ_9x9: eRetval = Circ_11x11; break; + //case Circ_11x11: eRetval = ; break; + + case Elli_7x9: eRetval = Elli_9x11; break; + //case Elli_9x11: eRetval = ; break; + + case Elli_9x7: eRetval = Elli_11x9; break; + //case Elli_11x9: eRetval = ; break; + + case RectPlus_7x7: eRetval = RectPlus_9x9; break; + case RectPlus_9x9: eRetval = RectPlus_11x11; break; + //case RectPlus_11x11: eRetval = ; break; + + //case Crosshair: eRetval = ; break; + //case Glue: eRetval = ; break; + + // #98388# let anchor blink with it's pressed state + case Anchor: eRetval = AnchorPressed; break; + + // #101688# same for AnchorTR + case AnchorTR: eRetval = AnchorPressedTR; break; + default: + break; + } + + return eRetval; +} + +// #101928# +BitmapEx SdrHdl::ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd, sal_Bool bFine, sal_Bool bIsHighContrast) +{ + if(bIsHighContrast) + { + return getHighContrastSet().GetBitmapEx(eKindOfMarker, nInd); + } + else + { + if(bFine) + { + return getModernSet().GetBitmapEx(eKindOfMarker, nInd); + } + else + { + return getSimpleSet().GetBitmapEx(eKindOfMarker, nInd); + } + } +} + +::sdr::overlay::OverlayObject* SdrHdl::CreateOverlayObject( + const basegfx::B2DPoint& rPos, + BitmapColorIndex eColIndex, BitmapMarkerKind eKindOfMarker, Point aMoveOutsideOffset) +{ + ::sdr::overlay::OverlayObject* pRetval = 0L; + sal_Bool bIsFineHdl(pHdlList->IsFineHdl()); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + sal_Bool bIsHighContrast(rStyleSettings.GetHighContrastMode()); + + // support bigger sizes + sal_Bool bForceBiggerSize(sal_False); + + if(pHdlList->GetHdlSize() > 3) + { + bForceBiggerSize = sal_True; + } + + // #101928# ...for high contrast, too. + if(!bForceBiggerSize && bIsHighContrast) + { + // #107925# + // ...but not for anchors, else they will not blink when activated + if(Anchor != eKindOfMarker && AnchorTR != eKindOfMarker) + { + bForceBiggerSize = sal_True; + } + } + + if(bForceBiggerSize) + { + eKindOfMarker = GetNextBigger(eKindOfMarker); + } + + // #97016# II This handle has the focus, visualize it + if(IsFocusHdl() && pHdlList && pHdlList->GetFocusHdl() == this) + { + // create animated handle + BitmapMarkerKind eNextBigger = GetNextBigger(eKindOfMarker); + + if(eNextBigger == eKindOfMarker) + { + // this may happen for the not supported getting-bigger types. + // Choose an alternative here + switch(eKindOfMarker) + { + case Rect_13x13: eNextBigger = Rect_11x11; break; + case Circ_11x11: eNextBigger = Elli_11x9; break; + case Elli_9x11: eNextBigger = Elli_11x9; break; + case Elli_11x9: eNextBigger = Elli_9x11; break; + case RectPlus_11x11: eNextBigger = Rect_13x13; break; + + case Crosshair: + eNextBigger = Glue; + break; + + case Glue: + eNextBigger = Crosshair; + break; + default: + break; + } + } + + // create animated hdl + // #101928# use ImpGetBitmapEx(...) now + BitmapEx aBmpEx1 = ImpGetBitmapEx(eKindOfMarker, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast); + BitmapEx aBmpEx2 = ImpGetBitmapEx(eNextBigger, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast); + + // #i53216# Use system cursor blink time. Use the unsigned value. + const sal_uInt32 nBlinkTime((sal_uInt32)Application::GetSettings().GetStyleSettings().GetCursorBlinkTime()); + + if(eKindOfMarker == Anchor || eKindOfMarker == AnchorPressed) + { + // #98388# when anchor is used take upper left as reference point inside the handle + pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime); + } + else if(eKindOfMarker == AnchorTR || eKindOfMarker == AnchorPressedTR) + { + // #101688# AnchorTR for SW, take top right as (0,0) + pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime, + (UINT16)(aBmpEx1.GetSizePixel().Width() - 1), 0, + (UINT16)(aBmpEx2.GetSizePixel().Width() - 1), 0); + } + else + { + // create centered handle as default + pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime, + (UINT16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, + (UINT16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1, + (UINT16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1, + (UINT16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1); + } + } + else + { + // create normal handle + // #101928# use ImpGetBitmapEx(...) now + BitmapEx aBmpEx = ImpGetBitmapEx(eKindOfMarker, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast); + + if(eKindOfMarker == Anchor || eKindOfMarker == AnchorPressed) + { + // #98388# upper left as reference point inside the handle for AnchorPressed, too + pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx); + } + else if(eKindOfMarker == AnchorTR || eKindOfMarker == AnchorPressedTR) + { + // #101688# AnchorTR for SW, take top right as (0,0) + pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx, + (UINT16)(aBmpEx.GetSizePixel().Width() - 1), 0); + } + else + { + sal_uInt16 nCenX((sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1L) >> 1); + sal_uInt16 nCenY((sal_uInt16)(aBmpEx.GetSizePixel().Height() - 1L) >> 1); + + if(aMoveOutsideOffset.X() > 0) + { + nCenX = 0; + } + else if(aMoveOutsideOffset.X() < 0) + { + nCenX = (sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1); + } + + if(aMoveOutsideOffset.Y() > 0) + { + nCenY = 0; + } + else if(aMoveOutsideOffset.Y() < 0) + { + nCenY = (sal_uInt16)(aBmpEx.GetSizePixel().Height() - 1); + } + + // create centered handle as default + pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx, nCenX, nCenY); + } + } + + return pRetval; +} + +bool SdrHdl::IsHdlHit(const Point& rPnt) const +{ + // OVERLAYMANAGER + basegfx::B2DPoint aPosition(rPnt.X(), rPnt.Y()); + return maOverlayGroup.isHitLogic(aPosition); +} + +Pointer SdrHdl::GetPointer() const +{ + PointerStyle ePtr=POINTER_MOVE; + const BOOL bSize=eKind>=HDL_UPLFT && eKind<=HDL_LWRGT; + const BOOL bRot=pHdlList!=NULL && pHdlList->IsRotateShear(); + const BOOL bDis=pHdlList!=NULL && pHdlList->IsDistortShear(); + if (bSize && pHdlList!=NULL && (bRot || bDis)) { + switch (eKind) { + case HDL_UPLFT: case HDL_UPRGT: + case HDL_LWLFT: case HDL_LWRGT: ePtr=bRot ? POINTER_ROTATE : POINTER_REFHAND; break; + case HDL_LEFT : case HDL_RIGHT: ePtr=POINTER_VSHEAR; break; + case HDL_UPPER: case HDL_LOWER: ePtr=POINTER_HSHEAR; break; + default: + break; + } + } else { + // Fuer Resize von gedrehten Rechtecken die Mauszeiger etwas mitdrehen + if (bSize && nDrehWink!=0) { + long nHdlWink=0; + switch (eKind) { + case HDL_LWRGT: nHdlWink=31500; break; + case HDL_LOWER: nHdlWink=27000; break; + case HDL_LWLFT: nHdlWink=22500; break; + case HDL_LEFT : nHdlWink=18000; break; + case HDL_UPLFT: nHdlWink=13500; break; + case HDL_UPPER: nHdlWink=9000; break; + case HDL_UPRGT: nHdlWink=4500; break; + case HDL_RIGHT: nHdlWink=0; break; + default: + break; + } + nHdlWink+=nDrehWink+2249; // und etwas drauf (zum runden) + while (nHdlWink<0) nHdlWink+=36000; + while (nHdlWink>=36000) nHdlWink-=36000; + nHdlWink/=4500; + switch ((BYTE)nHdlWink) { + case 0: ePtr=POINTER_ESIZE; break; + case 1: ePtr=POINTER_NESIZE; break; + case 2: ePtr=POINTER_NSIZE; break; + case 3: ePtr=POINTER_NWSIZE; break; + case 4: ePtr=POINTER_WSIZE; break; + case 5: ePtr=POINTER_SWSIZE; break; + case 6: ePtr=POINTER_SSIZE; break; + case 7: ePtr=POINTER_SESIZE; break; + } // switch + } else { + switch (eKind) { + case HDL_UPLFT: ePtr=POINTER_NWSIZE; break; + case HDL_UPPER: ePtr=POINTER_NSIZE; break; + case HDL_UPRGT: ePtr=POINTER_NESIZE; break; + case HDL_LEFT : ePtr=POINTER_WSIZE; break; + case HDL_RIGHT: ePtr=POINTER_ESIZE; break; + case HDL_LWLFT: ePtr=POINTER_SWSIZE; break; + case HDL_LOWER: ePtr=POINTER_SSIZE; break; + case HDL_LWRGT: ePtr=POINTER_SESIZE; break; + case HDL_POLY : ePtr=POINTER_MOVEPOINT; break; + case HDL_CIRC : ePtr=POINTER_HAND; break; + case HDL_REF1 : ePtr=POINTER_REFHAND; break; + case HDL_REF2 : ePtr=POINTER_REFHAND; break; + case HDL_BWGT : ePtr=POINTER_MOVEBEZIERWEIGHT; break; + case HDL_GLUE : ePtr=POINTER_MOVEPOINT; break; + case HDL_CUSTOMSHAPE1 : ePtr=POINTER_HAND; break; + default: + break; + } + } + } + return Pointer(ePtr); +} + +// #97016# II +BOOL SdrHdl::IsFocusHdl() const +{ + switch(eKind) + { + case HDL_UPLFT: // Oben links + case HDL_UPPER: // Oben + case HDL_UPRGT: // Oben rechts + case HDL_LEFT: // Links + case HDL_RIGHT: // Rechts + case HDL_LWLFT: // Unten links + case HDL_LOWER: // Unten + case HDL_LWRGT: // Unten rechts + { + // if it's a activated TextEdit, it's moved to extended points + if(pHdlList && pHdlList->IsMoveOutside()) + return FALSE; + else + return TRUE; + } + + case HDL_MOVE: // Handle zum Verschieben des Objekts + case HDL_POLY: // Punktselektion an Polygon oder Bezierkurve + case HDL_BWGT: // Gewicht an einer Bezierkurve + case HDL_CIRC: // Winkel an Kreissegmenten, Eckenradius am Rect + case HDL_REF1: // Referenzpunkt 1, z.B. Rotationsmitte + case HDL_REF2: // Referenzpunkt 2, z.B. Endpunkt der Spiegelachse + //case HDL_MIRX: // Die Spiegelachse selbst + case HDL_GLUE: // GluePoint + + // #98388# do NOT activate here, let SW implement their own SdrHdl and + // overload IsFocusHdl() there to make the anchor accessible + //case HDL_ANCHOR: // anchor symbol (SD, SW) + // #101688# same for AnchorTR + //case HDL_ANCHOR_TR: // anchor symbol (SD, SW) + + //case HDL_TRNS: // interactive transparence + //case HDL_GRAD: // interactive gradient + //case HDL_COLR: // interactive color + + // for SJ and the CustomShapeHandles: + case HDL_CUSTOMSHAPE1: + + case HDL_USER: + { + return TRUE; + } + + default: + { + return FALSE; + } + } +} + +void SdrHdl::onMouseEnter(const MouseEvent& /*rMEvt*/) +{ +} + +void SdrHdl::onMouseLeave() +{ +} + +bool SdrHdl::isMouseOver() const +{ + return mbMouseOver; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// class SdrHdlColor + +SdrHdlColor::SdrHdlColor(const Point& rRef, Color aCol, const Size& rSize, BOOL bLum) +: SdrHdl(rRef, HDL_COLR), + aMarkerSize(rSize), + bUseLuminance(bLum) +{ + if(IsUseLuminance()) + aCol = GetLuminance(aCol); + + // remember color + aMarkerColor = aCol; +} + +SdrHdlColor::~SdrHdlColor() +{ +} + +void SdrHdlColor::CreateB2dIAObject() +{ + // first throw away old one + GetRidOfIAObject(); + + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden()) + { + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b]; + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + Bitmap aBmpCol(CreateColorDropper(aMarkerColor)); + basegfx::B2DPoint aPosition(aPos.X(), aPos.Y()); + ::sdr::overlay::OverlayObject* pNewOverlayObject = new + ::sdr::overlay::OverlayBitmapEx( + aPosition, + BitmapEx(aBmpCol), + (UINT16)(aBmpCol.GetSizePixel().Width() - 1) >> 1, + (UINT16)(aBmpCol.GetSizePixel().Height() - 1) >> 1 + ); + DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!"); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } + } +} + +Bitmap SdrHdlColor::CreateColorDropper(Color aCol) +{ + // get the Bitmap + Bitmap aRetval(aMarkerSize, 24); + aRetval.Erase(aCol); + + // get write access + BitmapWriteAccess* pWrite = aRetval.AcquireWriteAccess(); + DBG_ASSERT(pWrite, "Got NO write access to a new Bitmap !!!"); + + if(pWrite) + { + // draw outer border + INT32 nWidth = aMarkerSize.Width(); + INT32 nHeight = aMarkerSize.Height(); + + pWrite->SetLineColor(Color(COL_LIGHTGRAY)); + pWrite->DrawLine(Point(0, 0), Point(0, nHeight - 1)); + pWrite->DrawLine(Point(1, 0), Point(nWidth - 1, 0)); + pWrite->SetLineColor(Color(COL_GRAY)); + pWrite->DrawLine(Point(1, nHeight - 1), Point(nWidth - 1, nHeight - 1)); + pWrite->DrawLine(Point(nWidth - 1, 1), Point(nWidth - 1, nHeight - 2)); + + // draw lighter UpperLeft + const Color aLightColor( + (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetRed() + (sal_Int16)0x0040), (sal_Int16)0x00ff)), + (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetGreen() + (sal_Int16)0x0040), (sal_Int16)0x00ff)), + (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetBlue() + (sal_Int16)0x0040), (sal_Int16)0x00ff))); + pWrite->SetLineColor(aLightColor); + pWrite->DrawLine(Point(1, 1), Point(1, nHeight - 2)); + pWrite->DrawLine(Point(2, 1), Point(nWidth - 2, 1)); + + // draw darker LowerRight + const Color aDarkColor( + (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetRed() - (sal_Int16)0x0040), (sal_Int16)0x0000)), + (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetGreen() - (sal_Int16)0x0040), (sal_Int16)0x0000)), + (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetBlue() - (sal_Int16)0x0040), (sal_Int16)0x0000))); + pWrite->SetLineColor(aDarkColor); + pWrite->DrawLine(Point(2, nHeight - 2), Point(nWidth - 2, nHeight - 2)); + pWrite->DrawLine(Point(nWidth - 2, 2), Point(nWidth - 2, nHeight - 3)); + + // get rid of write access + delete pWrite; + } + + return aRetval; +} + +Color SdrHdlColor::GetLuminance(const Color& rCol) +{ + UINT8 aLum = rCol.GetLuminance(); + Color aRetval(aLum, aLum, aLum); + return aRetval; +} + +void SdrHdlColor::CallColorChangeLink() +{ + aColorChangeHdl.Call(this); +} + +void SdrHdlColor::SetColor(Color aNew, BOOL bCallLink) +{ + if(IsUseLuminance()) + aNew = GetLuminance(aNew); + + if(aMarkerColor != aNew) + { + // remember new color + aMarkerColor = aNew; + + // create new display + Touch(); + + // tell about change + if(bCallLink) + CallColorChangeLink(); + } +} + +void SdrHdlColor::SetSize(const Size& rNew) +{ + if(rNew != aMarkerSize) + { + // remember new size + aMarkerSize = rNew; + + // create new display + Touch(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// class SdrHdlGradient + +SdrHdlGradient::SdrHdlGradient(const Point& rRef1, const Point& rRef2, BOOL bGrad) +: SdrHdl(rRef1, bGrad ? HDL_GRAD : HDL_TRNS), + pColHdl1(NULL), + pColHdl2(NULL), + a2ndPos(rRef2), + bGradient(bGrad) +{ +} + +SdrHdlGradient::~SdrHdlGradient() +{ +} + +void SdrHdlGradient::Set2ndPos(const Point& rPnt) +{ + if(a2ndPos != rPnt) + { + // remember new position + a2ndPos = rPnt; + + // create new display + Touch(); + } +} + +void SdrHdlGradient::CreateB2dIAObject() +{ + // first throw away old one + GetRidOfIAObject(); + + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden()) + { + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + // striped line in between + basegfx::B2DVector aVec(a2ndPos.X() - aPos.X(), a2ndPos.Y() - aPos.Y()); + double fVecLen = aVec.getLength(); + double fLongPercentArrow = (1.0 - 0.05) * fVecLen; + double fHalfArrowWidth = (0.05 * 0.5) * fVecLen; + aVec.normalize(); + basegfx::B2DVector aPerpend(-aVec.getY(), aVec.getX()); + INT32 nMidX = (INT32)(aPos.X() + aVec.getX() * fLongPercentArrow); + INT32 nMidY = (INT32)(aPos.Y() + aVec.getY() * fLongPercentArrow); + Point aMidPoint(nMidX, nMidY); + + basegfx::B2DPoint aPosition(aPos.X(), aPos.Y()); + basegfx::B2DPoint aMidPos(aMidPoint.X(), aMidPoint.Y()); + + ::sdr::overlay::OverlayObject* pNewOverlayObject = new + ::sdr::overlay::OverlayLineStriped( + aPosition, aMidPos + ); + DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!"); + + pNewOverlayObject->setBaseColor(IsGradient() ? Color(COL_BLACK) : Color(COL_BLUE)); + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + + // arrowhead + Point aLeft(aMidPoint.X() + (INT32)(aPerpend.getX() * fHalfArrowWidth), + aMidPoint.Y() + (INT32)(aPerpend.getY() * fHalfArrowWidth)); + Point aRight(aMidPoint.X() - (INT32)(aPerpend.getX() * fHalfArrowWidth), + aMidPoint.Y() - (INT32)(aPerpend.getY() * fHalfArrowWidth)); + + basegfx::B2DPoint aPositionLeft(aLeft.X(), aLeft.Y()); + basegfx::B2DPoint aPositionRight(aRight.X(), aRight.Y()); + basegfx::B2DPoint aPosition2(a2ndPos.X(), a2ndPos.Y()); + + pNewOverlayObject = new + ::sdr::overlay::OverlayTriangle( + aPositionLeft, + aPosition2, + aPositionRight, + IsGradient() ? Color(COL_BLACK) : Color(COL_BLUE) + ); + DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!"); + + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } +} + +IMPL_LINK(SdrHdlGradient, ColorChangeHdl, SdrHdl*, /*pHdl*/) +{ + if(GetObj()) + FromIAOToItem(GetObj(), TRUE, TRUE); + return 0; +} + +void SdrHdlGradient::FromIAOToItem(SdrObject* _pObj, BOOL bSetItemOnObject, BOOL bUndo) +{ + // from IAO positions and colors to gradient + const SfxItemSet& rSet = _pObj->GetMergedItemSet(); + + GradTransformer aGradTransformer; + GradTransGradient aOldGradTransGradient; + GradTransGradient aGradTransGradient; + GradTransVector aGradTransVector; + + String aString; + + aGradTransVector.maPositionA = basegfx::B2DPoint(GetPos().X(), GetPos().Y()); + aGradTransVector.maPositionB = basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y()); + if(pColHdl1) + aGradTransVector.aCol1 = pColHdl1->GetColor(); + if(pColHdl2) + aGradTransVector.aCol2 = pColHdl2->GetColor(); + + if(IsGradient()) + aOldGradTransGradient.aGradient = ((XFillGradientItem&)rSet.Get(XATTR_FILLGRADIENT)).GetGradientValue(); + else + aOldGradTransGradient.aGradient = ((XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE)).GetGradientValue(); + + // transform vector data to gradient + aGradTransformer.VecToGrad(aGradTransVector, aGradTransGradient, aOldGradTransGradient, _pObj, bMoveSingleHandle, bMoveFirstHandle); + + if(bSetItemOnObject) + { + SdrModel* pModel = _pObj->GetModel(); + SfxItemSet aNewSet(pModel->GetItemPool()); + + if(IsGradient()) + { + aString = String(); + XFillGradientItem aNewGradItem(aString, aGradTransGradient.aGradient); + aNewSet.Put(aNewGradItem); + } + else + { + aString = String(); + XFillFloatTransparenceItem aNewTransItem(aString, aGradTransGradient.aGradient); + aNewSet.Put(aNewTransItem); + } + + if(bUndo && pModel->IsUndoEnabled()) + { + pModel->BegUndo(SVX_RESSTR(IsGradient() ? SIP_XA_FILLGRADIENT : SIP_XA_FILLTRANSPARENCE)); + pModel->AddUndo(pModel->GetSdrUndoFactory().CreateUndoAttrObject(*_pObj)); + pModel->EndUndo(); + } + + pObj->SetMergedItemSetAndBroadcast(aNewSet); + } + + // back transformation, set values on pIAOHandle + aGradTransformer.GradToVec(aGradTransGradient, aGradTransVector, _pObj); + + SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY()))); + Set2ndPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY()))); + if(pColHdl1) + { + pColHdl1->SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY()))); + pColHdl1->SetColor(aGradTransVector.aCol1); + } + if(pColHdl2) + { + pColHdl2->SetPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY()))); + pColHdl2->SetColor(aGradTransVector.aCol2); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrHdlLine::~SdrHdlLine() {} + +void SdrHdlLine::CreateB2dIAObject() +{ + // first throw away old one + GetRidOfIAObject(); + + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden() && pHdl1 && pHdl2) + { + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + basegfx::B2DPoint aPosition1(pHdl1->GetPos().X(), pHdl1->GetPos().Y()); + basegfx::B2DPoint aPosition2(pHdl2->GetPos().X(), pHdl2->GetPos().Y()); + + ::sdr::overlay::OverlayObject* pNewOverlayObject = new + ::sdr::overlay::OverlayLineStriped( + aPosition1, + aPosition2 + ); + DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!"); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + // color(?) + pNewOverlayObject->setBaseColor(Color(COL_LIGHTRED)); + + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } + } +} + +Pointer SdrHdlLine::GetPointer() const +{ + return Pointer(POINTER_REFHAND); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrHdlBezWgt::~SdrHdlBezWgt() {} + +void SdrHdlBezWgt::CreateB2dIAObject() +{ + // call parent + SdrHdl::CreateB2dIAObject(); + + // create lines + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden()) + { + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + basegfx::B2DPoint aPosition1(pHdl1->GetPos().X(), pHdl1->GetPos().Y()); + basegfx::B2DPoint aPosition2(aPos.X(), aPos.Y()); + + if(!aPosition1.equal(aPosition2)) + { + ::sdr::overlay::OverlayObject* pNewOverlayObject = new + ::sdr::overlay::OverlayLineStriped( + aPosition1, + aPosition2 + ); + DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!"); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + // line part is not hittable + pNewOverlayObject->setHittable(sal_False); + + // color(?) + pNewOverlayObject->setBaseColor(Color(COL_LIGHTBLUE)); + + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon& rWireframePoly) +{ + aWireframePoly = rWireframePoly; +} + +void E3dVolumeMarker::CreateB2dIAObject() +{ + // create lines + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden()) + { + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager() && aWireframePoly.count()) + { + ::sdr::overlay::OverlayObject* pNewOverlayObject = new + ::sdr::overlay::OverlayPolyPolygonStriped(aWireframePoly); + DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!"); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + pNewOverlayObject->setBaseColor(Color(COL_BLACK)); + + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } + } + } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ImpEdgeHdl::~ImpEdgeHdl() +{ +} + +void ImpEdgeHdl::CreateB2dIAObject() +{ + if(nObjHdlNum <= 1 && pObj) + { + // first throw away old one + GetRidOfIAObject(); + + BitmapColorIndex eColIndex = LightCyan; + BitmapMarkerKind eKindOfMarker = Rect_7x7; + + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden()) + { + const SdrEdgeObj* pEdge = (SdrEdgeObj*)pObj; + + if(pEdge->GetConnectedNode(nObjHdlNum == 0) != NULL) + eColIndex = LightRed; + + if(nPPntNum < 2) + { + // Handle with plus sign inside + eKindOfMarker = Circ_7x7; + } + + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + basegfx::B2DPoint aPosition(aPos.X(), aPos.Y()); + + ::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject( + aPosition, + eColIndex, + eKindOfMarker); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } + } + } + else + { + // call parent + SdrHdl::CreateB2dIAObject(); + } +} + +void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode) +{ + if(eLineCode != eCode) + { + // remember new value + eLineCode = eCode; + + // create new display + Touch(); + } +} + +Pointer ImpEdgeHdl::GetPointer() const +{ + SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pObj); + if (pEdge==NULL) + return SdrHdl::GetPointer(); + if (nObjHdlNum<=1) + return Pointer(POINTER_MOVEPOINT); //Pointer(POINTER_DRAW_CONNECT); + if (IsHorzDrag()) + return Pointer(POINTER_ESIZE); + else + return Pointer(POINTER_SSIZE); +} + +BOOL ImpEdgeHdl::IsHorzDrag() const +{ + SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pObj); + if (pEdge==NULL) + return FALSE; + if (nObjHdlNum<=1) + return FALSE; + + SdrEdgeKind eEdgeKind = ((SdrEdgeKindItem&)(pEdge->GetObjectItem(SDRATTR_EDGEKIND))).GetValue(); + + const SdrEdgeInfoRec& rInfo=pEdge->aEdgeInfo; + if (eEdgeKind==SDREDGE_ORTHOLINES || eEdgeKind==SDREDGE_BEZIER) + { + return !rInfo.ImpIsHorzLine(eLineCode,*pEdge->pEdgeTrack); + } + else if (eEdgeKind==SDREDGE_THREELINES) + { + long nWink=nObjHdlNum==2 ? rInfo.nAngle1 : rInfo.nAngle2; + if (nWink==0 || nWink==18000) + return TRUE; + else + return FALSE; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ImpMeasureHdl::~ImpMeasureHdl() +{ +} + +void ImpMeasureHdl::CreateB2dIAObject() +{ + // first throw away old one + GetRidOfIAObject(); + + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden()) + { + BitmapColorIndex eColIndex = LightCyan; + BitmapMarkerKind eKindOfMarker = Rect_9x9; + + if(nObjHdlNum > 1) + { + eKindOfMarker = Rect_7x7; + } + + if(bSelect) + { + eColIndex = Cyan; + } + + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + basegfx::B2DPoint aPosition(aPos.X(), aPos.Y()); + + ::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject( + aPosition, + eColIndex, + eKindOfMarker); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } + } +} + +Pointer ImpMeasureHdl::GetPointer() const +{ + switch (nObjHdlNum) + { + case 0: case 1: return Pointer(POINTER_HAND); + case 2: case 3: return Pointer(POINTER_MOVEPOINT); + case 4: case 5: return SdrHdl::GetPointer(); // wird dann entsprechend gedreht + } // switch + return Pointer(POINTER_NOTALLOWED); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ImpTextframeHdl::ImpTextframeHdl(const Rectangle& rRect) : + SdrHdl(rRect.TopLeft(),HDL_MOVE), + maRect(rRect) +{ +} + +void ImpTextframeHdl::CreateB2dIAObject() +{ + // first throw away old one + GetRidOfIAObject(); + + if(pHdlList) + { + SdrMarkView* pView = pHdlList->GetView(); + + if(pView && !pView->areMarkHandlesHidden()) + { + SdrPageView* pPageView = pView->GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + const basegfx::B2DPoint aTopLeft(maRect.Left(), maRect.Top()); + const basegfx::B2DPoint aBottomRight(maRect.Right(), maRect.Bottom()); + const svtools::ColorConfig aColorConfig; + const Color aHatchCol( aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor ); + + ::sdr::overlay::OverlayHatchRect* pNewOverlayObject = new ::sdr::overlay::OverlayHatchRect( + aTopLeft, + aBottomRight, + aHatchCol, + 3.0, + 3.0, + 45 * F_PI180, + nDrehWink * -F_PI18000); + pNewOverlayObject->setHittable(false); + + // OVERLAYMANAGER + if(pNewOverlayObject) + { + rPageWindow.GetOverlayManager()->add(*pNewOverlayObject); + maOverlayGroup.append(*pNewOverlayObject); + } + } + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpSdrHdlListSorter: public ContainerSorter { +public: + ImpSdrHdlListSorter(Container& rNewCont): ContainerSorter(rNewCont) {} + virtual int Compare(const void* pElem1, const void* pElem2) const; +}; + +int ImpSdrHdlListSorter::Compare(const void* pElem1, const void* pElem2) const +{ + SdrHdlKind eKind1=((SdrHdl*)pElem1)->GetKind(); + SdrHdlKind eKind2=((SdrHdl*)pElem2)->GetKind(); + // Level 1: Erst normale Handles, dann Glue, dann User, dann Plushandles, dann Retpunkt-Handles + unsigned n1=1; + unsigned n2=1; + if (eKind1!=eKind2) + { + if (eKind1==HDL_REF1 || eKind1==HDL_REF2 || eKind1==HDL_MIRX) n1=5; + else if (eKind1==HDL_GLUE) n1=2; + else if (eKind1==HDL_USER) n1=3; + else if (eKind1==HDL_SMARTTAG) n1=0; + if (eKind2==HDL_REF1 || eKind2==HDL_REF2 || eKind2==HDL_MIRX) n2=5; + else if (eKind2==HDL_GLUE) n2=2; + else if (eKind2==HDL_USER) n2=3; + else if (eKind2==HDL_SMARTTAG) n2=0; + } + if (((SdrHdl*)pElem1)->IsPlusHdl()) n1=4; + if (((SdrHdl*)pElem2)->IsPlusHdl()) n2=4; + if (n1==n2) + { + // Level 2: PageView (Pointer) + SdrPageView* pPV1=((SdrHdl*)pElem1)->GetPageView(); + SdrPageView* pPV2=((SdrHdl*)pElem2)->GetPageView(); + if (pPV1==pPV2) + { + // Level 3: Position (x+y) + SdrObject* pObj1=((SdrHdl*)pElem1)->GetObj(); + SdrObject* pObj2=((SdrHdl*)pElem2)->GetObj(); + if (pObj1==pObj2) + { + sal_uInt32 nNum1=((SdrHdl*)pElem1)->GetObjHdlNum(); + sal_uInt32 nNum2=((SdrHdl*)pElem2)->GetObjHdlNum(); + if (nNum1==nNum2) + { // #48763# + if (eKind1==eKind2) + return (long)pElem1<(long)pElem2 ? -1 : 1; // Notloesung, um immer die gleiche Sortierung zu haben + return (USHORT)eKind1<(USHORT)eKind2 ? -1 : 1; + } + else + return nNum1<nNum2 ? -1 : 1; + } + else + { + return (long)pObj1<(long)pObj2 ? -1 : 1; + } + } + else + { + return (long)pPV1<(long)pPV2 ? -1 : 1; + } + } + else + { + return n1<n2 ? -1 : 1; + } +} + +SdrMarkView* SdrHdlList::GetView() const +{ + return pView; +} + +// #105678# Help struct for re-sorting handles +struct ImplHdlAndIndex +{ + SdrHdl* mpHdl; + sal_uInt32 mnIndex; +}; + +// #105678# Help method for sorting handles taking care of OrdNums, keeping order in +// single objects and re-sorting polygon handles intuitively +extern "C" int __LOADONCALLAPI ImplSortHdlFunc( const void* pVoid1, const void* pVoid2 ) +{ + const ImplHdlAndIndex* p1 = (ImplHdlAndIndex*)pVoid1; + const ImplHdlAndIndex* p2 = (ImplHdlAndIndex*)pVoid2; + + if(p1->mpHdl->GetObj() == p2->mpHdl->GetObj()) + { + if(p1->mpHdl->GetObj() && p1->mpHdl->GetObj()->ISA(SdrPathObj)) + { + // same object and a path object + if((p1->mpHdl->GetKind() == HDL_POLY || p1->mpHdl->GetKind() == HDL_BWGT) + && (p2->mpHdl->GetKind() == HDL_POLY || p2->mpHdl->GetKind() == HDL_BWGT)) + { + // both handles are point or control handles + if(p1->mpHdl->GetPolyNum() == p2->mpHdl->GetPolyNum()) + { + if(p1->mpHdl->GetPointNum() < p2->mpHdl->GetPointNum()) + { + return -1; + } + else + { + return 1; + } + } + else if(p1->mpHdl->GetPolyNum() < p2->mpHdl->GetPolyNum()) + { + return -1; + } + else + { + return 1; + } + } + } + } + else + { + if(!p1->mpHdl->GetObj()) + { + return -1; + } + else if(!p2->mpHdl->GetObj()) + { + return 1; + } + else + { + // different objects, use OrdNum for sort + const sal_uInt32 nOrdNum1 = p1->mpHdl->GetObj()->GetOrdNum(); + const sal_uInt32 nOrdNum2 = p2->mpHdl->GetObj()->GetOrdNum(); + + if(nOrdNum1 < nOrdNum2) + { + return -1; + } + else + { + return 1; + } + } + } + + // fallback to indices + if(p1->mnIndex < p2->mnIndex) + { + return -1; + } + else + { + return 1; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #97016# II + +void SdrHdlList::TravelFocusHdl(sal_Bool bForward) +{ + // security correction + if(mnFocusIndex != CONTAINER_ENTRY_NOTFOUND && mnFocusIndex >= GetHdlCount()) + mnFocusIndex = CONTAINER_ENTRY_NOTFOUND; + + if(aList.Count()) + { + // take care of old handle + const ULONG nOldHdlNum(mnFocusIndex); + SdrHdl* pOld = GetHdl(nOldHdlNum); + //SDOsal_Bool bRefresh(sal_False); + + if(pOld) + { + // switch off old handle + mnFocusIndex = CONTAINER_ENTRY_NOTFOUND; + pOld->Touch(); + //SDObRefresh = sal_True; + } + + // #105678# Alloc pointer array for sorted handle list + ImplHdlAndIndex* pHdlAndIndex = new ImplHdlAndIndex[aList.Count()]; + + // #105678# build sorted handle list + sal_uInt32 a; + for( a = 0; a < aList.Count(); a++) + { + pHdlAndIndex[a].mpHdl = (SdrHdl*)aList.GetObject(a); + pHdlAndIndex[a].mnIndex = a; + } + + // #105678# qsort all entries + qsort(pHdlAndIndex, aList.Count(), sizeof(ImplHdlAndIndex), ImplSortHdlFunc); + + // #105678# look for old num in sorted array + ULONG nOldHdl(nOldHdlNum); + + if(nOldHdlNum != CONTAINER_ENTRY_NOTFOUND) + { + for(a = 0; a < aList.Count(); a++) + { + if(pHdlAndIndex[a].mpHdl == pOld) + { + nOldHdl = a; + break; + } + } + } + + // #105678# build new HdlNum + ULONG nNewHdl(nOldHdl); + + // #105678# do the focus travel + if(bForward) + { + if(nOldHdl != CONTAINER_ENTRY_NOTFOUND) + { + if(nOldHdl == aList.Count() - 1) + { + // end forward run + nNewHdl = CONTAINER_ENTRY_NOTFOUND; + } + else + { + // simply the next handle + nNewHdl++; + } + } + else + { + // start forward run at first entry + nNewHdl = 0; + } + } + else + { + if(nOldHdl == CONTAINER_ENTRY_NOTFOUND) + { + // start backward run at last entry + nNewHdl = aList.Count() - 1; + + } + else + { + if(nOldHdl == 0) + { + // end backward run + nNewHdl = CONTAINER_ENTRY_NOTFOUND; + } + else + { + // simply the previous handle + nNewHdl--; + } + } + } + + // #105678# build new HdlNum + sal_uInt32 nNewHdlNum(nNewHdl); + + // look for old num in sorted array + if(nNewHdl != CONTAINER_ENTRY_NOTFOUND) + { + SdrHdl* pNew = pHdlAndIndex[nNewHdl].mpHdl; + + for(a = 0; a < aList.Count(); a++) + { + if((SdrHdl*)aList.GetObject(a) == pNew) + { + nNewHdlNum = a; + break; + } + } + } + + // take care of next handle + if(nOldHdlNum != nNewHdlNum) + { + mnFocusIndex = nNewHdlNum; + SdrHdl* pNew = GetHdl(mnFocusIndex); + + if(pNew) + { + pNew->Touch(); + //SDObRefresh = sal_True; + } + } + + // #105678# free mem again + delete [] pHdlAndIndex; + } +} + +SdrHdl* SdrHdlList::GetFocusHdl() const +{ + if(mnFocusIndex != CONTAINER_ENTRY_NOTFOUND && mnFocusIndex < GetHdlCount()) + return GetHdl(mnFocusIndex); + else + return 0L; +} + +void SdrHdlList::SetFocusHdl(SdrHdl* pNew) +{ + if(pNew) + { + SdrHdl* pActual = GetFocusHdl(); + + if(!pActual || pActual != pNew) + { + ULONG nNewHdlNum = GetHdlNum(pNew); + + if(nNewHdlNum != CONTAINER_ENTRY_NOTFOUND) + { + //SDOsal_Bool bRefresh(sal_False); + mnFocusIndex = nNewHdlNum; + + if(pActual) + { + pActual->Touch(); + //SDObRefresh = sal_True; + } + + if(pNew) + { + pNew->Touch(); + //SDObRefresh = sal_True; + } + + //OLMif(bRefresh) + //OLM{ + //OLM if(pView) + //OLM pView->RefreshAllIAOManagers(); + //OLM} + } + } + } +} + +void SdrHdlList::ResetFocusHdl() +{ + SdrHdl* pHdl = GetFocusHdl(); + + mnFocusIndex = CONTAINER_ENTRY_NOTFOUND; + + if(pHdl) + { + pHdl->Touch(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrHdlList::SdrHdlList(SdrMarkView* pV) +: mnFocusIndex(CONTAINER_ENTRY_NOTFOUND), + pView(pV), + aList(1024,32,32) +{ + nHdlSize = 3; + bRotateShear = FALSE; + bMoveOutside = FALSE; + bDistortShear = FALSE; + bFineHandles = FALSE; +} + +SdrHdlList::~SdrHdlList() +{ + Clear(); +} + +void SdrHdlList::SetHdlSize(USHORT nSiz) +{ + if(nHdlSize != nSiz) + { + // remember new value + nHdlSize = nSiz; + + // propagate change to IAOs + for(UINT32 i=0; i<GetHdlCount(); i++) + { + SdrHdl* pHdl = GetHdl(i); + pHdl->Touch(); + } + } +} + +void SdrHdlList::SetMoveOutside(BOOL bOn) +{ + if(bMoveOutside != bOn) + { + // remember new value + bMoveOutside = bOn; + + // propagate change to IAOs + for(UINT32 i=0; i<GetHdlCount(); i++) + { + SdrHdl* pHdl = GetHdl(i); + pHdl->Touch(); + } + } +} + +void SdrHdlList::SetRotateShear(BOOL bOn) +{ + bRotateShear = bOn; +} + +void SdrHdlList::SetDistortShear(BOOL bOn) +{ + bDistortShear = bOn; +} + +void SdrHdlList::SetFineHdl(BOOL bOn) +{ + if(bFineHandles != bOn) + { + // remember new state + bFineHandles = bOn; + + // propagate change to IAOs + for(UINT32 i=0; i<GetHdlCount(); i++) + { + SdrHdl* pHdl = GetHdl(i); + pHdl->Touch(); + } + } +} + +SdrHdl* SdrHdlList::RemoveHdl(ULONG nNum) +{ + SdrHdl* pRetval = (SdrHdl*)aList.Remove(nNum); + + return pRetval; +} + +void SdrHdlList::Clear() +{ + for (ULONG i=0; i<GetHdlCount(); i++) + { + SdrHdl* pHdl=GetHdl(i); + delete pHdl; + } + aList.Clear(); + + bRotateShear=FALSE; + bDistortShear=FALSE; +} + +void SdrHdlList::Sort() +{ + // #97016# II: remember current focused handle + SdrHdl* pPrev = GetFocusHdl(); + + ImpSdrHdlListSorter aSort(aList); + aSort.DoSort(); + + // #97016# II: get now and compare + SdrHdl* pNow = GetFocusHdl(); + + if(pPrev != pNow) + { + //SDOsal_Bool bRefresh(sal_False); + + if(pPrev) + { + pPrev->Touch(); + //SDObRefresh = sal_True; + } + + if(pNow) + { + pNow->Touch(); + //SDObRefresh = sal_True; + } + } +} + +ULONG SdrHdlList::GetHdlNum(const SdrHdl* pHdl) const +{ + if (pHdl==NULL) + return CONTAINER_ENTRY_NOTFOUND; + ULONG nPos=aList.GetPos(pHdl); + return nPos; +} + +void SdrHdlList::AddHdl(SdrHdl* pHdl, BOOL bAtBegin) +{ + if (pHdl!=NULL) + { + if (bAtBegin) + { + aList.Insert(pHdl,ULONG(0)); + } + else + { + aList.Insert(pHdl,CONTAINER_APPEND); + } + pHdl->SetHdlList(this); + } +} + +SdrHdl* SdrHdlList::IsHdlListHit(const Point& rPnt, BOOL bBack, BOOL bNext, SdrHdl* pHdl0) const +{ + SdrHdl* pRet=NULL; + ULONG nAnz=GetHdlCount(); + ULONG nNum=bBack ? 0 : nAnz; + while ((bBack ? nNum<nAnz : nNum>0) && pRet==NULL) + { + if (!bBack) + nNum--; + SdrHdl* pHdl=GetHdl(nNum); + if (bNext) + { + if (pHdl==pHdl0) + bNext=FALSE; + } + else + { + if (pHdl->IsHdlHit(rPnt)) + pRet=pHdl; + } + if (bBack) + nNum++; + } + return pRet; +} + +SdrHdl* SdrHdlList::GetHdl(SdrHdlKind eKind1) const +{ + SdrHdl* pRet=NULL; + for (ULONG i=0; i<GetHdlCount() && pRet==NULL; i++) + { + SdrHdl* pHdl=GetHdl(i); + if (pHdl->GetKind()==eKind1) + pRet=pHdl; + } + return pRet; +} + +// -------------------------------------------------------------------- +// SdrCropHdl +// -------------------------------------------------------------------- + +SdrCropHdl::SdrCropHdl(const Point& rPnt, SdrHdlKind eNewKind) +: SdrHdl( rPnt, eNewKind ) +{ +} + +// -------------------------------------------------------------------- + +BitmapEx SdrCropHdl::GetHandlesBitmap( bool bIsFineHdl, bool bIsHighContrast ) +{ + if( bIsHighContrast ) + { + static BitmapEx* pHighContrastBitmap = 0; + if( pHighContrastBitmap == 0 ) + pHighContrastBitmap = new BitmapEx(ResId(SIP_SA_ACCESSIBILITY_CROP_MARKERS, *ImpGetResMgr())); + return *pHighContrastBitmap; + } + else if( bIsFineHdl ) + { + static BitmapEx* pModernBitmap = 0; + if( pModernBitmap == 0 ) + pModernBitmap = new BitmapEx(ResId(SIP_SA_CROP_FINE_MARKERS, *ImpGetResMgr())); + return *pModernBitmap; + } + else + { + static BitmapEx* pSimpleBitmap = 0; + if( pSimpleBitmap == 0 ) + pSimpleBitmap = new BitmapEx(ResId(SIP_SA_CROP_MARKERS, *ImpGetResMgr())); + return *pSimpleBitmap; + } +} + +// -------------------------------------------------------------------- + +BitmapEx SdrCropHdl::GetBitmapForHandle( const BitmapEx& rBitmap, int nSize ) +{ + int nPixelSize = 0, nX = 0, nY = 0, nOffset = 0; + + if( nSize <= 3 ) + { + nPixelSize = 13; + nOffset = 0; + } + else if( nSize <=4 ) + { + nPixelSize = 17; + nOffset = 36; + } + else + { + nPixelSize = 21; + nOffset = 84; + } + + switch( eKind ) + { + case HDL_UPLFT: nX = 0; nY = 0; break; + case HDL_UPPER: nX = 1; nY = 0; break; + case HDL_UPRGT: nX = 2; nY = 0; break; + case HDL_LEFT: nX = 0; nY = 1; break; + case HDL_RIGHT: nX = 2; nY = 1; break; + case HDL_LWLFT: nX = 0; nY = 2; break; + case HDL_LOWER: nX = 1; nY = 2; break; + case HDL_LWRGT: nX = 2; nY = 2; break; + default: break; + } + + Rectangle aSourceRect( Point( nX * (nPixelSize-1) + nOffset, nY * (nPixelSize-1)), Size(nPixelSize, nPixelSize) ); + + BitmapEx aRetval(rBitmap); + aRetval.Crop(aSourceRect); + return aRetval; +} + +// -------------------------------------------------------------------- + +void SdrCropHdl::CreateB2dIAObject() +{ + // first throw away old one + GetRidOfIAObject(); + + SdrMarkView* pView = pHdlList ? pHdlList->GetView() : 0; + SdrPageView* pPageView = pView ? pView->GetSdrPageView() : 0; + + if( pPageView && !pView->areMarkHandlesHidden() ) + { + sal_Bool bIsFineHdl(pHdlList->IsFineHdl()); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + sal_Bool bIsHighContrast(rStyleSettings.GetHighContrastMode()); + int nHdlSize = pHdlList->GetHdlSize(); + if( bIsHighContrast ) + nHdlSize = 4; + + const BitmapEx aHandlesBitmap( GetHandlesBitmap( bIsFineHdl, bIsHighContrast ) ); + BitmapEx aBmpEx1( GetBitmapForHandle( aHandlesBitmap, nHdlSize ) ); + + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b]; + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + if(rPageWindow.GetOverlayManager()) + { + basegfx::B2DPoint aPosition(aPos.X(), aPos.Y()); + + ::sdr::overlay::OverlayObject* pOverlayObject = 0L; + + // animate focused handles + if(IsFocusHdl() && (pHdlList->GetFocusHdl() == this)) + { + if( nHdlSize >= 2 ) + nHdlSize = 1; + + BitmapEx aBmpEx2( GetBitmapForHandle( aHandlesBitmap, nHdlSize + 1 ) ); + + const sal_uInt32 nBlinkTime = sal::static_int_cast<sal_uInt32>(rStyleSettings.GetCursorBlinkTime()); + + pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBmpEx1, aBmpEx2, nBlinkTime, + (UINT16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, + (UINT16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1, + (UINT16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1, + (UINT16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1); + } + else + { + // create centered handle as default + pOverlayObject = new ::sdr::overlay::OverlayBitmapEx(aPosition, aBmpEx1, + (UINT16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, + (UINT16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1); + } + + // OVERLAYMANAGER + if(pOverlayObject) + { + rPageWindow.GetOverlayManager()->add(*pOverlayObject); + maOverlayGroup.append(*pOverlayObject); + } + } + } + } + } +} + +// -------------------------------------------------------------------- diff --git a/svx/source/svdraw/svdhlpln.cxx b/svx/source/svdraw/svdhlpln.cxx new file mode 100644 index 000000000000..2813b6f032f1 --- /dev/null +++ b/svx/source/svdraw/svdhlpln.cxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdhlpln.hxx> +#include <tools/color.hxx> + +#include <vcl/outdev.hxx> +#include <vcl/window.hxx> +#include <tools/poly.hxx> +#include <vcl/lineinfo.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Pointer SdrHelpLine::GetPointer() const +{ + switch (eKind) { + case SDRHELPLINE_VERTICAL : return Pointer(POINTER_ESIZE); + case SDRHELPLINE_HORIZONTAL: return Pointer(POINTER_SSIZE); + default : return Pointer(POINTER_MOVE); + } // switch +} + +FASTBOOL SdrHelpLine::IsHit(const Point& rPnt, USHORT nTolLog, const OutputDevice& rOut) const +{ + Size a1Pix(rOut.PixelToLogic(Size(1,1))); + FASTBOOL bXHit=rPnt.X()>=aPos.X()-nTolLog && rPnt.X()<=aPos.X()+nTolLog+a1Pix.Width(); + FASTBOOL bYHit=rPnt.Y()>=aPos.Y()-nTolLog && rPnt.Y()<=aPos.Y()+nTolLog+a1Pix.Height(); + switch (eKind) { + case SDRHELPLINE_VERTICAL : return bXHit; + case SDRHELPLINE_HORIZONTAL: return bYHit; + case SDRHELPLINE_POINT: { + if (bXHit || bYHit) { + Size aRad(rOut.PixelToLogic(Size(SDRHELPLINE_POINT_PIXELSIZE,SDRHELPLINE_POINT_PIXELSIZE))); + return rPnt.X()>=aPos.X()-aRad.Width() && rPnt.X()<=aPos.X()+aRad.Width()+a1Pix.Width() && + rPnt.Y()>=aPos.Y()-aRad.Height() && rPnt.Y()<=aPos.Y()+aRad.Height()+a1Pix.Height(); + } + } break; + } // switch + return FALSE; +} + +Rectangle SdrHelpLine::GetBoundRect(const OutputDevice& rOut) const +{ + Rectangle aRet(aPos,aPos); + Point aOfs(rOut.GetMapMode().GetOrigin()); + Size aSiz(rOut.GetOutputSize()); + switch (eKind) { + case SDRHELPLINE_VERTICAL : aRet.Top()=-aOfs.Y(); aRet.Bottom()=-aOfs.Y()+aSiz.Height(); break; + case SDRHELPLINE_HORIZONTAL: aRet.Left()=-aOfs.X(); aRet.Right()=-aOfs.X()+aSiz.Width(); break; + case SDRHELPLINE_POINT : { + Size aRad(rOut.PixelToLogic(Size(SDRHELPLINE_POINT_PIXELSIZE,SDRHELPLINE_POINT_PIXELSIZE))); + aRet.Left() -=aRad.Width(); + aRet.Right() +=aRad.Width(); + aRet.Top() -=aRad.Height(); + aRet.Bottom()+=aRad.Height(); + } break; + } // switch + return aRet; +} + +bool SdrHelpLine::IsVisibleEqual( const SdrHelpLine& rHelpLine, const OutputDevice& rOut ) const +{ + if( eKind == rHelpLine.eKind) + { + Point aPt1(rOut.LogicToPixel(aPos)), aPt2(rOut.LogicToPixel(rHelpLine.aPos)); + switch( eKind ) + { + case SDRHELPLINE_POINT: + return aPt1 == aPt2; + case SDRHELPLINE_VERTICAL: + return aPt1.X() == aPt2.X(); + case SDRHELPLINE_HORIZONTAL: + return aPt1.Y() == aPt2.Y(); + } + } + return false; +} + +void SdrHelpLineList::Clear() +{ + USHORT nAnz=GetCount(); + for (USHORT i=0; i<nAnz; i++) { + delete GetObject(i); + } + aList.Clear(); +} + +void SdrHelpLineList::operator=(const SdrHelpLineList& rSrcList) +{ + Clear(); + USHORT nAnz=rSrcList.GetCount(); + for (USHORT i=0; i<nAnz; i++) { + Insert(rSrcList[i]); + } +} + +bool SdrHelpLineList::operator==(const SdrHelpLineList& rSrcList) const +{ + FASTBOOL bEqual=FALSE; + USHORT nAnz=GetCount(); + if (nAnz==rSrcList.GetCount()) { + bEqual=TRUE; + for (USHORT i=0; i<nAnz && bEqual; i++) { + if (*GetObject(i)!=*rSrcList.GetObject(i)) { + bEqual=FALSE; + } + } + } + return bEqual; +} + +USHORT SdrHelpLineList::HitTest(const Point& rPnt, USHORT nTolLog, const OutputDevice& rOut) const +{ + USHORT nAnz=GetCount(); + for (USHORT i=nAnz; i>0;) { + i--; + if (GetObject(i)->IsHit(rPnt,nTolLog,rOut)) return i; + } + return SDRHELPLINE_NOTFOUND; +} + +// eof diff --git a/svx/source/svdraw/svdibrow.cxx b/svx/source/svdraw/svdibrow.cxx new file mode 100644 index 000000000000..fa3dbe852b3a --- /dev/null +++ b/svx/source/svdraw/svdibrow.cxx @@ -0,0 +1,1299 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <editeng/eeitem.hxx> + +#include "svdibrow.hxx" + +#ifndef _STDLIB_H +#include <stdlib.h> +#define _STDLIB_H +#endif + +#include "svditext.hxx" +#include <editeng/flditem.hxx> +#include <editeng/editdata.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdattrx.hxx> +#include <svx/svdview.hxx> +#include <svx/xenum.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xtextit0.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbtoxy.hxx> +#include <svx/xftshit.hxx> +#include <editeng/colritem.hxx> + + +#include "editeng/fontitem.hxx" +#include <editeng/fhgtitem.hxx> + +#include <editeng/charscaleitem.hxx> +#include <svl/whiter.hxx> +#include <svl/flagitem.hxx> +#include <svl/ptitem.hxx> +#include <svl/rectitem.hxx> + +#include <svl/rngitem.hxx> +#include <sdrpaintwindow.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define ITEMBROWSER_WHICHCOL_ID 1 +#define ITEMBROWSER_STATECOL_ID 2 +#define ITEMBROWSER_TYPECOL_ID 3 +#define ITEMBROWSER_NAMECOL_ID 4 +#define ITEMBROWSER_VALUECOL_ID 5 + +enum ItemType { + ITEM_DONTKNOW, ITEM_BYTE, ITEM_INT16, ITEM_UINT16, ITEM_INT32, ITEM_UINT32, + ITEM_ENUM, ITEM_BOOL, ITEM_FLAG, ITEM_STRING, ITEM_POINT, ITEM_RECT, ITEM_RANGE, ITEM_LRANGE, + ITEM_FRACTION, + ITEM_XCOLOR, + ITEM_COLOR, + ITEM_FONT, ITEM_FONTHEIGHT, ITEM_FONTWIDTH, ITEM_FIELD +}; + +class ImpItemListRow +{ +public: + XubString aName; + XubString aValue; + SfxItemState eState; + UINT16 nWhichId; + + TypeId pType; + ItemType eItemType; + + INT32 nVal; + INT32 nMin; + INT32 nMax; + + BOOL bComment; + BOOL bIsNum; + BOOL bCanNum; + +public: + ImpItemListRow() + : eState(SFX_ITEM_UNKNOWN), + nWhichId(0), + pType(NULL), + eItemType(ITEM_DONTKNOW), + nVal(0), + nMin(0), + nMax(0), + bComment(FALSE), + bIsNum(FALSE), + bCanNum(FALSE) + {} + + XubString GetItemTypeStr() const; + BOOL operator==(const ImpItemListRow& rEntry) const; + BOOL operator!=(const ImpItemListRow& rEntry) const { return !operator==(rEntry); } +}; + +XubString ImpItemListRow::GetItemTypeStr() const +{ + XubString aStr; + + switch(eItemType) + { + case ITEM_BYTE : aStr.AppendAscii("Byte"); break; + case ITEM_INT16 : aStr.AppendAscii("Int16"); break; + case ITEM_UINT16 : aStr.AppendAscii("UInt16"); break; + case ITEM_INT32 : aStr.AppendAscii("Int32"); break; + case ITEM_UINT32 : aStr.AppendAscii("UInt32"); break; + case ITEM_ENUM : aStr.AppendAscii("Enum"); break; + case ITEM_BOOL : aStr.AppendAscii("Bool"); break; + case ITEM_FLAG : aStr.AppendAscii("Flag"); break; + case ITEM_STRING : aStr.AppendAscii("String"); break; + case ITEM_POINT : aStr.AppendAscii("Point"); break; + case ITEM_RECT : aStr.AppendAscii("Rectangle");break; + case ITEM_RANGE : aStr.AppendAscii("Range"); break; + case ITEM_LRANGE : aStr.AppendAscii("LRange"); break; + case ITEM_FRACTION : aStr.AppendAscii("Fraction"); break; + case ITEM_XCOLOR : aStr.AppendAscii("XColor"); break; + case ITEM_COLOR : aStr.AppendAscii("Color"); break; + case ITEM_FONT : aStr.AppendAscii("Font"); break; + case ITEM_FONTHEIGHT:aStr.AppendAscii("FontHeight");break; + case ITEM_FONTWIDTH :aStr.AppendAscii("FontWidth"); break; + case ITEM_FIELD :aStr.AppendAscii("Field"); break; + default: break; + } + + return aStr; +} + +BOOL ImpItemListRow::operator==(const ImpItemListRow& rEntry) const +{ + return (aName.Equals(rEntry.aName) + && aValue.Equals(rEntry.aValue) + && eState==rEntry.eState + && nWhichId==rEntry.nWhichId + && bComment==rEntry.bComment + && bIsNum==rEntry.bIsNum + && bCanNum==rEntry.bCanNum + && pType==rEntry.pType + && eItemType==rEntry.eItemType + && nVal==rEntry.nVal + && nMin==rEntry.nMin + && nMax==rEntry.nMax); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpItemEdit: public Edit +{ + _SdrItemBrowserControl* pBrowse; + +public: + ImpItemEdit(Window* pParent, _SdrItemBrowserControl* pBrowse_, WinBits nBits=0) + : Edit(pParent, nBits), + pBrowse(pBrowse_) + {} + + virtual ~ImpItemEdit(); + virtual void KeyInput(const KeyEvent& rEvt); +}; + +__EXPORT ImpItemEdit::~ImpItemEdit() +{ +} + +void __EXPORT ImpItemEdit::KeyInput(const KeyEvent& rKEvt) +{ + _SdrItemBrowserControl* pBrowseMerk = pBrowse; + + UINT16 nKeyCode(rKEvt.GetKeyCode().GetCode() + rKEvt.GetKeyCode().GetModifier()); + + if(nKeyCode == KEY_RETURN) + { + pBrowseMerk->EndChangeEntry(); + pBrowseMerk->GrabFocus(); + } + else if(nKeyCode == KEY_ESCAPE) + { + pBrowseMerk->BrkChangeEntry(); + pBrowseMerk->GrabFocus(); + } + else if(nKeyCode == KEY_UP || nKeyCode == KEY_DOWN) + { + pBrowseMerk->EndChangeEntry(); + pBrowseMerk->GrabFocus(); + pBrowseMerk->KeyInput(rKEvt); + } + else + Edit::KeyInput(rKEvt); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define MYBROWSEMODE (BROWSER_THUMBDRAGGING|BROWSER_KEEPHIGHLIGHT|BROWSER_NO_HSCROLL|BROWSER_HIDECURSOR) + +_SdrItemBrowserControl::_SdrItemBrowserControl(Window* pParent, WinBits nBits): + BrowseBox(pParent,nBits,MYBROWSEMODE), + aList(1024,16,16) +{ + ImpCtor(); +} + +__EXPORT _SdrItemBrowserControl::~_SdrItemBrowserControl() +{ + if(pEditControl) + delete pEditControl; + + if(pAktChangeEntry) + delete pAktChangeEntry; + + Clear(); +} + +void _SdrItemBrowserControl::ImpCtor() +{ + pEditControl = NULL; + pAktChangeEntry = NULL; + nLastWhichOfs = 0; + nLastWhich = 0; + nLastWhichOben = 0; // not implemented yet + nLastWhichUnten = 0; // not implemented yet + bWhichesButNames = FALSE; + bDontHideIneffectiveItems = FALSE; + bDontSortItems = FALSE; + bShowWhichIds = FALSE; + bShowRealValues = FALSE; + bShowWhichIds = TRUE; // not implemented yet + bShowRealValues = TRUE; // not implemented yet + + rtl_TextEncoding aTextEncoding = gsl_getSystemTextEncoding(); + + InsertDataColumn( + ITEMBROWSER_WHICHCOL_ID, + String("Which", aTextEncoding), + GetTextWidth(String(" Which ", aTextEncoding)) + 2); + InsertDataColumn( + ITEMBROWSER_STATECOL_ID, + String("State", aTextEncoding), + Max(GetTextWidth(String(" State ", aTextEncoding)) + 2 , + GetTextWidth(String("DontCare", aTextEncoding)) + 2)); + InsertDataColumn( + ITEMBROWSER_TYPECOL_ID , + String("Type", aTextEncoding), + GetTextWidth(String(" Type_ ", aTextEncoding)) + 2); + InsertDataColumn( + ITEMBROWSER_NAMECOL_ID , + String("Name", aTextEncoding), + 150); + InsertDataColumn( + ITEMBROWSER_VALUECOL_ID, + String("Value", aTextEncoding), + GetTextWidth(String("12345678901234567890", aTextEncoding))); + SetDataRowHeight( + GetTextHeight()); + + long nWdt=GetColumnWidth(ITEMBROWSER_WHICHCOL_ID)+ + GetColumnWidth(ITEMBROWSER_STATECOL_ID)+ + GetColumnWidth(ITEMBROWSER_TYPECOL_ID )+ + GetColumnWidth(ITEMBROWSER_NAMECOL_ID )+ + GetColumnWidth(ITEMBROWSER_VALUECOL_ID); + + long nHgt=GetTitleHeight()+16*GetDataRowHeight(); + + SetOutputSizePixel(Size(nWdt,nHgt)); +} + +void _SdrItemBrowserControl::Clear() +{ + ULONG nAnz=aList.Count(); + for (ULONG nNum=0; nNum<nAnz; nNum++) { + delete ImpGetEntry(nNum); + } + aList.Clear(); + BrowseBox::Clear(); +} + +long __EXPORT _SdrItemBrowserControl::GetRowCount() const +{ + return aList.Count(); +} + +BOOL __EXPORT _SdrItemBrowserControl::SeekRow(long nRow) +{ + nAktPaintRow=nRow; + return TRUE; +} + +String _SdrItemBrowserControl::GetCellText(long _nRow, USHORT _nColId) const +{ + String sRet; + if ( _nRow >= 0 && _nRow < (sal_Int32)aList.Count() ) + { + ImpItemListRow* pEntry = ImpGetEntry(_nRow); + if ( pEntry ) + { + if ( pEntry->bComment ) + { + if (_nColId == ITEMBROWSER_NAMECOL_ID) + sRet = pEntry->aName; + } + else + { + rtl_TextEncoding aTextEncoding = gsl_getSystemTextEncoding(); + + sRet = XubString("???", aTextEncoding); + switch (_nColId) + { + case ITEMBROWSER_WHICHCOL_ID: + sRet = UniString::CreateFromInt32(pEntry->nWhichId); break; + case ITEMBROWSER_STATECOL_ID: + { + switch (pEntry->eState) + { + case SFX_ITEM_UNKNOWN : sRet=String("Uknown", aTextEncoding); break; + case SFX_ITEM_DISABLED: sRet=String("Disabled", aTextEncoding); break; + case SFX_ITEM_DONTCARE: sRet=String("DontCare", aTextEncoding); break; + case SFX_ITEM_SET : sRet=String("Set", aTextEncoding); break; + case SFX_ITEM_DEFAULT : sRet=String("Default", aTextEncoding); break; + } // switch + } break; + case ITEMBROWSER_TYPECOL_ID: sRet = pEntry->GetItemTypeStr(); break; + case ITEMBROWSER_NAMECOL_ID: sRet = pEntry->aName; break; + case ITEMBROWSER_VALUECOL_ID: sRet = pEntry->aValue; break; + } // switch + } + } + } + return sRet; +} + +void __EXPORT _SdrItemBrowserControl::PaintField(OutputDevice& rDev, const Rectangle& rRect, USHORT nColumnId) const +{ + if (nAktPaintRow<0 || (ULONG)nAktPaintRow>=aList.Count()) { + return; + } + Rectangle aR(rRect); + aR.Bottom()++; + ImpItemListRow* pEntry=ImpGetEntry(nAktPaintRow); + if (pEntry->bComment) + { + if (nColumnId==ITEMBROWSER_NAMECOL_ID) + { + rDev.SetLineColor(); + rDev.SetFillColor( Color( COL_LIGHTGRAY ) ); + aR.Left()=0; + aR.Right()=rDev.GetOutputSize().Width(); + rDev.DrawRect(aR); + rDev.DrawText(rRect.TopLeft(),pEntry->aName); + } + } else { + rDev.SetClipRegion(aR); + rDev.DrawText(aR.TopLeft(),GetCellText(nAktPaintRow,nColumnId)); + rDev.SetClipRegion(); + } +} + +ULONG _SdrItemBrowserControl::GetCurrentPos() const +{ + ULONG nRet=CONTAINER_ENTRY_NOTFOUND; + if (GetSelectRowCount()==1) { + long nPos=((BrowseBox*)this)->FirstSelectedRow(); + if (nPos>=0 && (ULONG)nPos<aList.Count()) { + nRet=(ULONG)nPos; + } + } + return nRet; +} + +USHORT _SdrItemBrowserControl::GetCurrentWhich() const +{ + USHORT nRet=0; + ULONG nPos=GetCurrentPos(); + if (nPos!=CONTAINER_ENTRY_NOTFOUND) { + nRet=ImpGetEntry(nPos)->nWhichId; + } + return nRet; +} + +void __EXPORT _SdrItemBrowserControl::DoubleClick(const BrowserMouseEvent&) +{ + ULONG nPos=GetCurrentPos(); + if (nPos!=CONTAINER_ENTRY_NOTFOUND) { + BegChangeEntry(nPos); + } +} + +void __EXPORT _SdrItemBrowserControl::KeyInput(const KeyEvent& rKEvt) +{ + USHORT nKeyCode=rKEvt.GetKeyCode().GetCode()+rKEvt.GetKeyCode().GetModifier(); + FASTBOOL bAusgewertet=FALSE; + ULONG nPos=GetCurrentPos(); + if (nPos!=CONTAINER_ENTRY_NOTFOUND) { + if (nKeyCode==KEY_RETURN) { + if (BegChangeEntry(nPos)) bAusgewertet=TRUE; + } else if (nKeyCode==KEY_ESCAPE) { + // ... + } else if (rKEvt.GetKeyCode().GetModifier()==KEY_SHIFT+KEY_MOD1+KEY_MOD2) { // Strg + if (nKeyCode==KEY_SHIFT+KEY_MOD1+KEY_MOD2+KEY_W) { + bWhichesButNames=!bWhichesButNames; + SetDirty(); + } + if (nKeyCode==KEY_SHIFT+KEY_MOD1+KEY_MOD2+KEY_I) { + bDontHideIneffectiveItems=!bDontHideIneffectiveItems; + SetDirty(); + } + if (nKeyCode==KEY_SHIFT+KEY_MOD1+KEY_MOD2+KEY_S) { + bDontSortItems=!bDontSortItems; + SetDirty(); + } + } + } + if (!bAusgewertet) BrowseBox::KeyInput(rKEvt); +} + +void _SdrItemBrowserControl::SetDirty() +{ + aSetDirtyHdl.Call(this); +} + +Rectangle _SdrItemBrowserControl::GetFieldCharacterBounds(sal_Int32 /*_nRow*/,sal_Int32 /*_nColumnPos*/,sal_Int32 /*nIndex*/) +{ + // no accessibility implementation required + return Rectangle(); +} + +sal_Int32 _SdrItemBrowserControl::GetFieldIndexAtPoint(sal_Int32 /*_nRow*/,sal_Int32 /*_nColumnPos*/,const Point& /*_rPoint*/) +{ + // no accessibility implementation required + return -1; +} + +void __EXPORT _SdrItemBrowserControl::Select() +{ + EndChangeEntry(); + BrowseBox::Select(); + ImpSaveWhich(); +} + +void _SdrItemBrowserControl::ImpSaveWhich() +{ + USHORT nWh=GetCurrentWhich(); + if (nWh!=0) { + long nPos=GetCurrentPos(); + long nTop=GetTopRow(); + long nBtm=GetTopRow()+GetVisibleRows()+1; + nLastWhich=nWh; + nLastWhichOfs=nPos-nTop; + if (nTop<0) nTop=0; + if (nBtm>=(long)aList.Count()) nBtm=aList.Count()-1; + nLastWhichOben=ImpGetEntry(nTop)->nWhichId; + nLastWhichUnten=ImpGetEntry(nBtm)->nWhichId; + } +} + +void _SdrItemBrowserControl::ImpRestoreWhich() +{ + if (nLastWhich!=0) { + FASTBOOL bFnd=FALSE; + USHORT nBestMinWh=0,nBestMaxWh=0xFFFF; // not implemented yet + ULONG nBestMinPos=0,nBestMaxPos=0xFFFFFFFF; // not implemented yet + ULONG nAnz=aList.Count(); + ULONG nNum; + for (nNum=0; nNum<nAnz && !bFnd; nNum++) { + ImpItemListRow* pEntry=ImpGetEntry(nNum); + if (!pEntry->bComment) { + USHORT nWh=pEntry->nWhichId; + if (nWh==nLastWhich) bFnd=TRUE; + else if (nWh<nLastWhich && nWh>nBestMinWh) nBestMinPos=nNum; + else if (nWh>nLastWhich && nWh<nBestMaxWh) nBestMaxPos=nNum; + } + } + if (bFnd) { + long nPos=nNum-1; + long nWhichOfs=nPos-GetTopRow(); + if (nWhichOfs!=nLastWhichOfs) { + ScrollRows(nWhichOfs-nLastWhichOfs); + } + GoToRow(nPos); + } + } +} + +FASTBOOL _SdrItemBrowserControl::BegChangeEntry(ULONG nPos) +{ + BrkChangeEntry(); + FASTBOOL bRet=FALSE; + ImpItemListRow* pEntry=ImpGetEntry(nPos); + if (pEntry!=NULL && !pEntry->bComment) { + SetMode(MYBROWSEMODE & ~BROWSER_KEEPHIGHLIGHT); + pEditControl=new ImpItemEdit(&GetDataWindow(),this,0/*|WB_BORDER|WB_3DLOOK*/); + Rectangle aRect(GetFieldRectPixel(nPos,ITEMBROWSER_VALUECOL_ID,FALSE)); + aRect.Left()+=2; // Kleiner Offset fuer's Edit, damit's pixelgenau stimmt + aRect.Right()--; + pEditControl->SetPosSizePixel(aRect.TopLeft(),aRect.GetSize()); + pEditControl->SetText(pEntry->aValue); + pEditControl->SetBackground( Wallpaper(Color(COL_LIGHTGRAY))); + Font aFont(pEditControl->GetFont()); + aFont.SetFillColor(Color(COL_LIGHTGRAY)); + pEditControl->SetFont(aFont); + pEditControl->Show(); + pEditControl->GrabFocus(); + pEditControl->SetSelection(Selection(SELECTION_MIN,SELECTION_MAX)); + Window* pParent=GetParent(); + aWNamMerk=pParent->GetText(); + XubString aNeuNam(aWNamMerk); + aNeuNam += sal_Unicode(' '); + aNeuNam += pEntry->GetItemTypeStr(); + if (pEntry->bCanNum) { + aNeuNam.AppendAscii(": "); + aNeuNam += UniString::CreateFromInt32(pEntry->nMin); + aNeuNam.AppendAscii(".."); + aNeuNam += UniString::CreateFromInt32(pEntry->nMax); + } + aNeuNam.AppendAscii(" - Type 'del' to reset to default."); + pParent->SetText(aNeuNam); + pAktChangeEntry=new ImpItemListRow(*pEntry); + bRet=TRUE; + } + return bRet; +} + +FASTBOOL _SdrItemBrowserControl::EndChangeEntry() +{ + FASTBOOL bRet=FALSE; + if (pEditControl!=NULL) { + aEntryChangedHdl.Call(this); + delete pEditControl; + pEditControl=NULL; + delete pAktChangeEntry; + pAktChangeEntry=NULL; + Window* pParent=GetParent(); + pParent->SetText(aWNamMerk); + SetMode(MYBROWSEMODE); + bRet=TRUE; + } + return bRet; +} + +void _SdrItemBrowserControl::BrkChangeEntry() +{ + if (pEditControl!=NULL) { + delete pEditControl; + pEditControl=NULL; + delete pAktChangeEntry; + pAktChangeEntry=NULL; + Window* pParent=GetParent(); + pParent->SetText(aWNamMerk); + SetMode(MYBROWSEMODE); + } +} + +void _SdrItemBrowserControl::ImpSetEntry(const ImpItemListRow& rEntry, ULONG nEntryNum) +{ + ImpItemListRow* pAktEntry=ImpGetEntry(nEntryNum); + if (pAktEntry==NULL) { + aList.Insert(new ImpItemListRow(rEntry),CONTAINER_APPEND); + RowInserted(nEntryNum); + } else if (*pAktEntry!=rEntry) { + FASTBOOL bStateDiff=rEntry.eState!=pAktEntry->eState; + FASTBOOL bValueDiff=!rEntry.aValue.Equals(pAktEntry->aValue); + FASTBOOL bAllDiff=TRUE; + if (bStateDiff || bValueDiff) { + // Checken, ob nur State und/oder Value geaendert + ImpItemListRow aTest(rEntry); + aTest.eState=pAktEntry->eState; + aTest.aValue=pAktEntry->aValue; + if (aTest==*pAktEntry) bAllDiff=FALSE; + } + *pAktEntry=rEntry; + if (bAllDiff) { + RowModified(nEntryNum); + } else { + if (bStateDiff) RowModified(nEntryNum,ITEMBROWSER_STATECOL_ID); + if (bValueDiff) RowModified(nEntryNum,ITEMBROWSER_VALUECOL_ID); + } + } +} + +FASTBOOL ImpGetItem(const SfxItemSet& rSet, USHORT nWhich, const SfxPoolItem*& rpItem) +{ + SfxItemState eState=rSet.GetItemState(nWhich,TRUE,&rpItem); + if (eState==SFX_ITEM_DEFAULT) { + rpItem=&rSet.Get(nWhich); + } + return (eState==SFX_ITEM_DEFAULT || eState==SFX_ITEM_SET) && rpItem!=NULL; +} + +FASTBOOL IsItemIneffective(USHORT nWhich, const SfxItemSet* pSet, USHORT& rIndent) +{ + rIndent=0; + if (pSet==NULL) return FALSE; + const SfxPoolItem* pItem=NULL; + FASTBOOL bRet=FALSE; + switch (nWhich) { + case XATTR_LINEDASH : + case XATTR_LINEWIDTH : + case XATTR_LINECOLOR : + case XATTR_LINESTART : + case XATTR_LINEEND : + case XATTR_LINESTARTWIDTH : + case XATTR_LINEENDWIDTH : + case XATTR_LINESTARTCENTER : + case XATTR_LINEENDCENTER : + case XATTR_LINETRANSPARENCE : { + rIndent=1; + if (ImpGetItem(*pSet,XATTR_LINESTYLE,pItem)) { + XLineStyle eLineStyle=((const XLineStyleItem*)pItem)->GetValue(); + if (eLineStyle==XLINE_NONE) return TRUE; + if (eLineStyle!=XLINE_DASH && nWhich==XATTR_LINEDASH) return TRUE; + } + if (nWhich==XATTR_LINESTART || nWhich==XATTR_LINESTARTCENTER) { + rIndent=2; + if (ImpGetItem(*pSet,XATTR_LINESTARTWIDTH,pItem)) { + INT32 nWdt=((const XLineStartWidthItem*)pItem)->GetValue(); + if (nWdt==0) return TRUE; + } + } + if (nWhich==XATTR_LINEEND || nWhich==XATTR_LINEENDCENTER) { + rIndent=2; + if (ImpGetItem(*pSet,XATTR_LINEENDWIDTH,pItem)) { + INT32 nWdt=((const XLineEndWidthItem*)pItem)->GetValue(); + if (nWdt==0) return TRUE; + } + } + } break; + case XATTR_FILLCOLOR : /*nur bei Style=Color*/ + case XATTR_FILLGRADIENT : /*nur bei Style=Gradient*/ + case XATTR_FILLHATCH : /*nur bei Style=Hatch*/ + case XATTR_FILLTRANSPARENCE : /*nur bei Style=Color*/ + case XATTR_GRADIENTSTEPCOUNT : /*nur bei Style=Gradient*/ + case XATTR_FILLBACKGROUND : /*nur bei Style=Hatch*/ + { + rIndent=1; + if (ImpGetItem(*pSet,XATTR_FILLSTYLE,pItem)) { + XFillStyle eFillStyle=((const XFillStyleItem*)pItem)->GetValue(); + if (eFillStyle==XFILL_NONE) return TRUE; + // Transparenz z.Zt. nur fuer SolidFill + if (eFillStyle!=XFILL_SOLID && (nWhich==XATTR_FILLCOLOR || nWhich==XATTR_FILLTRANSPARENCE)) return TRUE; + if (eFillStyle!=XFILL_GRADIENT && (nWhich==XATTR_FILLGRADIENT || nWhich==XATTR_GRADIENTSTEPCOUNT)) return TRUE; + if (eFillStyle!=XFILL_HATCH && (nWhich==XATTR_FILLHATCH || nWhich==XATTR_FILLBACKGROUND)) return TRUE; + } + } break; + case XATTR_FILLBITMAP : + case XATTR_FILLBMP_TILE : + case XATTR_FILLBMP_POS : /* z.Zt. nur wenn TILE=TRUE */ + case XATTR_FILLBMP_SIZEX : /* nur wenn nicht Stretch */ + case XATTR_FILLBMP_SIZEY : /* nur wenn nicht Stretch */ + case XATTR_FILLBMP_SIZELOG : /* nur wenn SIZELOG=FALSE zum ruecksetzen auf TRUE (alt) -> doch noch in Gebrauch */ + case XATTR_FILLBMP_TILEOFFSETX : /* nur wenn TILE=TRUE */ + case XATTR_FILLBMP_TILEOFFSETY : /* nur wenn TILE=TRUE */ + case XATTR_FILLBMP_STRETCH : /* nur wenn TILE=FALSE */ + case XATTR_FILLBMP_POSOFFSETX : /* nur wenn TILE=TRUE*/ + case XATTR_FILLBMP_POSOFFSETY : { /* nur wenn TILE=TRUE*/ + rIndent=1; + if (ImpGetItem(*pSet,XATTR_FILLSTYLE,pItem)) { + XFillStyle eFillStyle=((const XFillStyleItem*)pItem)->GetValue(); + if (eFillStyle!=XFILL_BITMAP) return TRUE; + } + if (nWhich==XATTR_FILLBITMAP || nWhich==XATTR_FILLBMP_TILE) { + return FALSE; // immer anwaehlbar + } + FASTBOOL bTileTRUE=FALSE; + FASTBOOL bTileFALSE=FALSE; + FASTBOOL bStretchTRUE=FALSE; + FASTBOOL bStretchFALSE=FALSE; + if (ImpGetItem(*pSet,XATTR_FILLBMP_TILE,pItem)) { + bTileTRUE=((const XFillBmpTileItem*)pItem)->GetValue(); + bTileFALSE=!bTileTRUE; + } + if (ImpGetItem(*pSet,XATTR_FILLBMP_STRETCH,pItem)) { + bStretchTRUE=((const XFillBmpStretchItem*)pItem)->GetValue(); + bStretchFALSE=!bStretchTRUE; + } + // Stretch nicht anwaehlbar, wenn Tile=TRUE + if (nWhich==XATTR_FILLBMP_STRETCH) return bTileTRUE; + // und uebrig bleiben 7+1 Item (Unterattribute) + rIndent=2; + // Pos (enum) nicht anwaehlbar, wenn Tile=FALSE + if (nWhich==XATTR_FILLBMP_POS) return bTileFALSE; + // SizeXY nicht anwaehlbar bei Stretch=TRUE + if (nWhich==XATTR_FILLBMP_SIZEX || nWhich==XATTR_FILLBMP_SIZEY) { + return bTileFALSE && bStretchTRUE; + } + // 2 Items speziell fuer Tile + if (nWhich==XATTR_FILLBMP_POSOFFSETX || nWhich==XATTR_FILLBMP_POSOFFSETY) { + return bTileFALSE; + } + // Noch 2 Items speziell fuer Tile die sich jedoch gegenseitig ausschliessen + if (nWhich==XATTR_FILLBMP_TILEOFFSETX || nWhich==XATTR_FILLBMP_TILEOFFSETY) { + if (bTileFALSE) return TRUE; + USHORT nX=0,nY=0; + FASTBOOL bX=FALSE,bY=FALSE; + if (ImpGetItem(*pSet,XATTR_FILLBMP_TILEOFFSETX,pItem)) { + nX=((const XFillBmpTileOffsetXItem*)pItem)->GetValue(); + bX=TRUE; + } + if (ImpGetItem(*pSet,XATTR_FILLBMP_TILEOFFSETY,pItem)) { + nY=((const XFillBmpTileOffsetYItem*)pItem)->GetValue(); + bY=TRUE; + } + if (nWhich==XATTR_FILLBMP_TILEOFFSETX) { + if (nX!=0 || !bX) return FALSE; + if (nY!=0) return TRUE; + } else { + if (nY!=0 || !bY) return FALSE; + if (nX!=0) return TRUE; + } + } + // SizeLog nicht anwaehlbar bei Stretch=TRUE + // und sonst auch nur wenn es auf SizeLog=FALSE gesetzt ist. + // -> wohl doch noch in Gebrauch + // (TRUE ist der statische PoolDefault) + if (nWhich==XATTR_FILLBMP_SIZELOG) { + if (bTileFALSE && bStretchTRUE) return TRUE; + } + } break; + + case XATTR_FORMTXTADJUST : + case XATTR_FORMTXTDISTANCE : + case XATTR_FORMTXTSTART : + case XATTR_FORMTXTMIRROR : + case XATTR_FORMTXTOUTLINE : + case XATTR_FORMTXTSHADOW : + case XATTR_FORMTXTSHDWCOLOR : + case XATTR_FORMTXTSHDWXVAL : + case XATTR_FORMTXTSHDWYVAL : + case XATTR_FORMTXTSTDFORM : + case XATTR_FORMTXTHIDEFORM : + case XATTR_FORMTXTSHDWTRANSP: { + rIndent=1; + if (ImpGetItem(*pSet,XATTR_FORMTXTSTYLE,pItem)) { + XFormTextStyle eStyle=((const XFormTextStyleItem*)pItem)->GetValue(); + if (eStyle==XFT_NONE) return TRUE; + } + if ((nWhich>=XATTR_FORMTXTSHDWCOLOR && nWhich<=XATTR_FORMTXTSHDWYVAL) || nWhich>=XATTR_FORMTXTSHDWTRANSP) { + rIndent=2; + if (ImpGetItem(*pSet,XATTR_FORMTXTSHADOW,pItem)) { + XFormTextShadow eShadow=((const XFormTextShadowItem*)pItem)->GetValue(); + if (eShadow==XFTSHADOW_NONE) return TRUE; + } + } + } break; + + case SDRATTR_SHADOWCOLOR : + case SDRATTR_SHADOWXDIST : + case SDRATTR_SHADOWYDIST : + case SDRATTR_SHADOWTRANSPARENCE: + case SDRATTR_SHADOW3D : + case SDRATTR_SHADOWPERSP : { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_SHADOW,pItem)) { + FASTBOOL bShadow=((const SdrShadowItem*)pItem)->GetValue(); + if (!bShadow) return TRUE; + } + } break; + + case SDRATTR_CAPTIONANGLE: { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_CAPTIONFIXEDANGLE,pItem)) { + FASTBOOL bFixed=((const SdrCaptionFixedAngleItem*)pItem)->GetValue(); + if (!bFixed) return TRUE; + } + } break; + case SDRATTR_CAPTIONESCREL: + case SDRATTR_CAPTIONESCABS: { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_CAPTIONESCISREL,pItem)) { + FASTBOOL bRel=((const SdrCaptionEscIsRelItem*)pItem)->GetValue(); + if (bRel && nWhich==SDRATTR_CAPTIONESCABS) return TRUE; + if (!bRel && nWhich==SDRATTR_CAPTIONESCREL) return TRUE; + } + } break; + case SDRATTR_CAPTIONLINELEN: { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_CAPTIONFITLINELEN,pItem)) { + FASTBOOL bFit=((const SdrCaptionFitLineLenItem*)pItem)->GetValue(); + if (bFit) return TRUE; + } + } break; + + case SDRATTR_TEXT_MINFRAMEHEIGHT: + case SDRATTR_TEXT_MAXFRAMEHEIGHT: { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_TEXT_AUTOGROWHEIGHT,pItem)) { + FASTBOOL bAutoGrow=((const SdrTextAutoGrowHeightItem*)pItem)->GetValue(); + if (!bAutoGrow) return TRUE; + } + } break; + case SDRATTR_TEXT_MINFRAMEWIDTH: + case SDRATTR_TEXT_MAXFRAMEWIDTH: { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_TEXT_AUTOGROWWIDTH,pItem)) { + FASTBOOL bAutoGrow=((const SdrTextAutoGrowWidthItem*)pItem)->GetValue(); + if (!bAutoGrow) return TRUE; + } + } break; + case SDRATTR_TEXT_VERTADJUST: + case SDRATTR_TEXT_HORZADJUST: { + if (ImpGetItem(*pSet,SDRATTR_TEXT_FITTOSIZE,pItem)) { + SdrFitToSizeType eFit=((const SdrTextFitToSizeTypeItem*)pItem)->GetValue(); + if (eFit!=SDRTEXTFIT_NONE) return TRUE; + } + } break; + + case SDRATTR_TEXT_ANIDIRECTION : + case SDRATTR_TEXT_ANISTARTINSIDE: + case SDRATTR_TEXT_ANISTOPINSIDE : + case SDRATTR_TEXT_ANICOUNT : + case SDRATTR_TEXT_ANIDELAY : + case SDRATTR_TEXT_ANIAMOUNT : { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_TEXT_ANIKIND,pItem)) { + SdrTextAniKind eAniKind=((const SdrTextAniKindItem*)pItem)->GetValue(); + if (eAniKind==SDRTEXTANI_NONE) return TRUE; + if (eAniKind==SDRTEXTANI_BLINK && (nWhich==SDRATTR_TEXT_ANIDIRECTION || nWhich==SDRATTR_TEXT_ANIAMOUNT)) return TRUE; + if (eAniKind==SDRTEXTANI_SLIDE && (nWhich==SDRATTR_TEXT_ANISTARTINSIDE || nWhich==SDRATTR_TEXT_ANISTOPINSIDE)) return TRUE; + } + } break; + + case SDRATTR_EDGELINEDELTAANZ: return TRUE; + case SDRATTR_EDGELINE1DELTA: + case SDRATTR_EDGELINE2DELTA: + case SDRATTR_EDGELINE3DELTA: { + if (ImpGetItem(*pSet,SDRATTR_EDGEKIND,pItem)) { + SdrEdgeKind eKind=((const SdrEdgeKindItem*)pItem)->GetValue(); + if (eKind==SDREDGE_THREELINES) { + if (nWhich>SDRATTR_EDGELINE2DELTA) return TRUE; + else return FALSE; + } + if (eKind!=SDREDGE_ORTHOLINES && eKind!=SDREDGE_BEZIER) return TRUE; + } + if (ImpGetItem(*pSet,SDRATTR_EDGELINEDELTAANZ,pItem)) { + UINT16 nAnz=((const SdrEdgeLineDeltaAnzItem*)pItem)->GetValue(); + if (nAnz==0) return TRUE; + if (nAnz==1 && nWhich>SDRATTR_EDGELINE1DELTA) return TRUE; + if (nAnz==2 && nWhich>SDRATTR_EDGELINE2DELTA) return TRUE; + if (nAnz==3 && nWhich>SDRATTR_EDGELINE3DELTA) return TRUE; + } + } break; + + case SDRATTR_CIRCSTARTANGLE: + case SDRATTR_CIRCENDANGLE : { + rIndent=1; + if (ImpGetItem(*pSet,SDRATTR_CIRCKIND,pItem)) { + SdrCircKind eKind=((const SdrCircKindItem*)pItem)->GetValue(); + if (eKind==SDRCIRC_FULL) return TRUE; + } + } break; + } // switch + return bRet; +} + +USHORT ImpSortWhich(USHORT nWhich) +{ + switch (nWhich) { + // Line + case XATTR_LINESTART : nWhich=XATTR_LINETRANSPARENCE ; break; + case XATTR_LINEEND : nWhich=XATTR_LINESTARTWIDTH ; break; + case XATTR_LINESTARTWIDTH : nWhich=XATTR_LINESTART ; break; + case XATTR_LINEENDWIDTH : nWhich=XATTR_LINESTARTCENTER ; break; + case XATTR_LINESTARTCENTER : nWhich=XATTR_LINEENDWIDTH ; break; + case XATTR_LINEENDCENTER : nWhich=XATTR_LINEEND ; break; + case XATTR_LINETRANSPARENCE : nWhich=XATTR_LINEENDCENTER ; break; + + // Fill + case XATTR_FILLBMP_POS : nWhich=XATTR_FILLBMP_STRETCH ; break; + case XATTR_FILLBMP_SIZEX : nWhich=XATTR_FILLBMP_POS ; break; + case XATTR_FILLBMP_SIZEY : nWhich=XATTR_FILLBMP_SIZEX ; break; + case XATTR_FILLBMP_SIZELOG : nWhich=XATTR_FILLBMP_SIZEY ; break; + case XATTR_FILLBMP_TILEOFFSETX : nWhich=XATTR_FILLBMP_SIZELOG ; break; + case XATTR_FILLBMP_TILEOFFSETY : nWhich=XATTR_FILLBMP_TILEOFFSETX ; break; + case XATTR_FILLBMP_STRETCH : nWhich=XATTR_FILLBMP_TILEOFFSETY ; break; + + // Fontwork + case XATTR_FORMTXTSHADOW : nWhich=XATTR_FORMTXTSTDFORM ; break; + case XATTR_FORMTXTSHDWCOLOR : nWhich=XATTR_FORMTXTHIDEFORM ; break; + case XATTR_FORMTXTSHDWXVAL : nWhich=XATTR_FORMTXTSHADOW ; break; + case XATTR_FORMTXTSHDWYVAL : nWhich=XATTR_FORMTXTSHDWCOLOR ; break; + case XATTR_FORMTXTSTDFORM : nWhich=XATTR_FORMTXTSHDWXVAL ; break; + case XATTR_FORMTXTHIDEFORM : nWhich=XATTR_FORMTXTSHDWYVAL ; break; + + // Misc + case SDRATTR_TEXT_MINFRAMEHEIGHT: nWhich=SDRATTR_TEXT_FITTOSIZE ; break; + case SDRATTR_TEXT_AUTOGROWHEIGHT: nWhich=SDRATTR_TEXT_LEFTDIST ; break; + case SDRATTR_TEXT_FITTOSIZE : nWhich=SDRATTR_TEXT_RIGHTDIST ; break; + case SDRATTR_TEXT_LEFTDIST : nWhich=SDRATTR_TEXT_UPPERDIST ; break; + case SDRATTR_TEXT_RIGHTDIST : nWhich=SDRATTR_TEXT_LOWERDIST ; break; + case SDRATTR_TEXT_UPPERDIST : nWhich=SDRATTR_TEXT_AUTOGROWWIDTH ; break; + case SDRATTR_TEXT_LOWERDIST : nWhich=SDRATTR_TEXT_MINFRAMEWIDTH ; break; + case SDRATTR_TEXT_VERTADJUST : nWhich=SDRATTR_TEXT_MAXFRAMEWIDTH ; break; + case SDRATTR_TEXT_MAXFRAMEHEIGHT: nWhich=SDRATTR_TEXT_AUTOGROWHEIGHT; break; + case SDRATTR_TEXT_MINFRAMEWIDTH : nWhich=SDRATTR_TEXT_MINFRAMEHEIGHT; break; + case SDRATTR_TEXT_MAXFRAMEWIDTH : nWhich=SDRATTR_TEXT_MAXFRAMEHEIGHT; break; + case SDRATTR_TEXT_AUTOGROWWIDTH : nWhich=SDRATTR_TEXT_HORZADJUST ; break; + case SDRATTR_TEXT_HORZADJUST : nWhich=SDRATTR_TEXT_VERTADJUST ; break; + } // switch + return nWhich; +} + +#define INSERTCOMMENT(nStartId,nEndId,aStr) \ + { if (nWhich0<nStartId && nWhich>=nStartId && nWhich<=nEndId) aCommentStr=aStr; } + +void _SdrItemBrowserControl::SetAttributes(const SfxItemSet* pSet, const SfxItemSet* p2ndSet) +{ + SetMode(MYBROWSEMODE & ~BROWSER_KEEPHIGHLIGHT); + if (pSet!=NULL) { + rtl_TextEncoding aTextEncoding = gsl_getSystemTextEncoding(); + USHORT nEntryNum=0; + SfxWhichIter aIter(*pSet); + const SfxItemPool* pPool=pSet->GetPool(); + USHORT nWhich0=0; + USHORT nWhich=aIter.FirstWhich(); + while (nWhich!=0) { + // Nun erstmal etwas umsortieren + // Geht nur, solange keine InvalidItems, d.h. keine Luecken + // an dieser Stelle im Set sind + if (!bDontSortItems) nWhich=ImpSortWhich(nWhich); + SfxItemState eState=pSet->GetItemState(nWhich); + if (p2ndSet!=NULL) { + SfxItemState e2ndState=p2ndSet->GetItemState(nWhich); + if (eState==SFX_ITEM_DEFAULT) eState=SFX_ITEM_DISABLED; + else if (e2ndState==SFX_ITEM_DEFAULT) eState=SFX_ITEM_DEFAULT; + } + if (eState!=SFX_ITEM_DISABLED) { + const SfxPoolItem& rItem=pSet->Get(nWhich); + USHORT nIndent=0; + if (!HAS_BASE(SfxVoidItem,&rItem) && !HAS_BASE(SfxSetItem,&rItem) && (!IsItemIneffective(nWhich,pSet,nIndent) || bDontHideIneffectiveItems)) { + XubString aCommentStr; + + INSERTCOMMENT(XATTR_LINE_FIRST,XATTR_LINE_LAST,String("L I N I E", aTextEncoding)); + INSERTCOMMENT(XATTR_FILL_FIRST,XATTR_FILL_LAST,String("F L Ä C H E", aTextEncoding)); + INSERTCOMMENT(XATTR_TEXT_FIRST,XATTR_TEXT_LAST,String("F O N T W O R K", aTextEncoding)); + INSERTCOMMENT(SDRATTR_SHADOW_FIRST,SDRATTR_SHADOW_LAST,String("S C H A T T E N", aTextEncoding)); + INSERTCOMMENT(SDRATTR_CAPTION_FIRST,SDRATTR_CAPTION_LAST,String("L E G E N D E", aTextEncoding)); + INSERTCOMMENT(SDRATTR_MISC_FIRST,SDRATTR_MISC_LAST,String("V E R S C H I E D E N E S", aTextEncoding)); + INSERTCOMMENT(SDRATTR_EDGE_FIRST,SDRATTR_EDGE_LAST,String("V E R B I N D E R", aTextEncoding)); + INSERTCOMMENT(SDRATTR_MEASURE_FIRST,SDRATTR_MEASURE_LAST,String("B E M A S S U N G", aTextEncoding)); + INSERTCOMMENT(SDRATTR_CIRC_FIRST,SDRATTR_CIRC_LAST,String("K R E I S", aTextEncoding)); + INSERTCOMMENT(SDRATTR_NOTPERSIST_FIRST,SDRATTR_NOTPERSIST_LAST,String("N O T P E R S I S T", aTextEncoding)); + INSERTCOMMENT(SDRATTR_MOVEX,SDRATTR_VERTSHEARONE,String("Transformationen auf alle Objekte einzeln", aTextEncoding)); + INSERTCOMMENT(SDRATTR_RESIZEXALL,SDRATTR_VERTSHEARALL,String("Transformationen auf alle Objekte gemeinsam", aTextEncoding)); + INSERTCOMMENT(SDRATTR_TRANSFORMREF1X,SDRATTR_TRANSFORMREF2Y,String("View-Referenzpunkte", aTextEncoding)); + INSERTCOMMENT(SDRATTR_GRAF_FIRST,SDRATTR_GRAF_LAST,String("G R A F I K", aTextEncoding)); + INSERTCOMMENT(EE_ITEMS_START,EE_ITEMS_END,String("E D I T E N G I N E", aTextEncoding)); + INSERTCOMMENT(EE_ITEMS_END+1,EE_ITEMS_END+1,String("... by Joe Merten, JME Engineering Berlin ...", aTextEncoding)); + + if(aCommentStr.Len()) + { + ImpItemListRow aEntry; + aEntry.bComment=TRUE; + aEntry.aName=aCommentStr; + ImpSetEntry(aEntry,nEntryNum); + nEntryNum++; + } + nWhich0=nWhich; + ImpItemListRow aEntry; + SdrItemPool::TakeItemName(nWhich, aEntry.aName); + nIndent*=2; + + while(nIndent > 0) + { + aEntry.aName.Insert(sal_Unicode(' '), 0); + nIndent--; + } + + aEntry.eState=eState; + aEntry.nWhichId=nWhich; + if (!IsInvalidItem(&rItem)) { + aEntry.pType=rItem.Type(); + aEntry.nMax=0x7FFFFFFF; + aEntry.nMin=-aEntry.nMax; + aEntry.nVal=-4711; + if (HAS_BASE(SfxByteItem ,&rItem)) aEntry.eItemType=ITEM_BYTE; + else if (HAS_BASE(SfxInt16Item ,&rItem)) aEntry.eItemType=ITEM_INT16; + else if (HAS_BASE(SfxUInt16Item ,&rItem)) aEntry.eItemType=ITEM_UINT16; + else if (HAS_BASE(SfxInt32Item ,&rItem)) aEntry.eItemType=ITEM_INT32; + else if (HAS_BASE(SfxUInt32Item ,&rItem)) aEntry.eItemType=ITEM_UINT32; + else if (HAS_BASE(SfxEnumItemInterface,&rItem)) aEntry.eItemType=ITEM_ENUM; + else if (HAS_BASE(SfxBoolItem ,&rItem)) aEntry.eItemType=ITEM_BOOL; + else if (HAS_BASE(SfxFlagItem ,&rItem)) aEntry.eItemType=ITEM_FLAG; + else if (HAS_BASE(XColorItem ,&rItem)) aEntry.eItemType=ITEM_XCOLOR; + else if (HAS_BASE(SfxStringItem ,&rItem)) aEntry.eItemType=ITEM_STRING; + else if (HAS_BASE(SfxPointItem ,&rItem)) aEntry.eItemType=ITEM_POINT; + else if (HAS_BASE(SfxRectangleItem,&rItem)) aEntry.eItemType=ITEM_RECT; + else if (HAS_BASE(SfxRangeItem ,&rItem)) aEntry.eItemType=ITEM_RANGE; + else if (HAS_BASE(SdrFractionItem ,&rItem)) aEntry.eItemType=ITEM_FRACTION; + else if (HAS_BASE(SvxColorItem ,&rItem)) aEntry.eItemType=ITEM_COLOR; + else if (HAS_BASE(SvxFontItem ,&rItem)) aEntry.eItemType=ITEM_FONT; + else if (HAS_BASE(SvxFontHeightItem,&rItem))aEntry.eItemType=ITEM_FONTHEIGHT; + else if (HAS_BASE(SvxCharScaleWidthItem,&rItem)) aEntry.eItemType=ITEM_FONTWIDTH; + else if (HAS_BASE(SvxFieldItem ,&rItem)) aEntry.eItemType=ITEM_FIELD; + switch (aEntry.eItemType) { + case ITEM_BYTE : aEntry.bIsNum=TRUE; aEntry.nVal=((SfxByteItem &)rItem).GetValue(); aEntry.nMin=0; aEntry.nMax=255; break; + case ITEM_INT16 : aEntry.bIsNum=TRUE; aEntry.nVal=((SfxInt16Item &)rItem).GetValue(); aEntry.nMin=-32767; aEntry.nMax=32767; break; + case ITEM_UINT16 : aEntry.bIsNum=TRUE; aEntry.nVal=((SfxUInt16Item&)rItem).GetValue(); aEntry.nMin=0; aEntry.nMax=65535; break; + case ITEM_INT32 : aEntry.bIsNum=TRUE; aEntry.nVal=((SfxInt32Item &)rItem).GetValue(); break; + case ITEM_UINT32 : aEntry.bIsNum=TRUE; aEntry.nVal=((SfxUInt32Item&)rItem).GetValue(); aEntry.nMin=0; /*aEntry.nMax=0xFF...*/;break; + case ITEM_ENUM : aEntry.bCanNum=TRUE; aEntry.nVal=((SfxEnumItemInterface&)rItem).GetEnumValue(); aEntry.nMin=0; aEntry.nMax=((SfxEnumItemInterface&)rItem).GetValueCount()-1; break; + case ITEM_BOOL : aEntry.bCanNum=TRUE; aEntry.nVal=((SfxBoolItem &)rItem).GetValue(); aEntry.nMin=0; aEntry.nMax=1; break; + case ITEM_FLAG : aEntry.bCanNum=TRUE; aEntry.nVal=((SfxFlagItem &)rItem).GetValue(); aEntry.nMin=0; aEntry.nMax=0xFFFF; break; + case ITEM_FONTHEIGHT: aEntry.bCanNum=TRUE; aEntry.nVal=((SvxFontHeightItem&)rItem).GetHeight(); aEntry.nMin=0; break; + case ITEM_FONTWIDTH : aEntry.bCanNum=TRUE; aEntry.nVal=((SvxCharScaleWidthItem&)rItem).GetValue(); aEntry.nMin=0; aEntry.nMax=0xFFFF;break; + default: break; + } // switch + if (aEntry.bIsNum) aEntry.bCanNum=TRUE; + FASTBOOL bGetPres=TRUE; + if (bGetPres) { + rItem.GetPresentation(SFX_ITEM_PRESENTATION_NAMELESS, + pPool->GetMetric(nWhich), + SFX_MAPUNIT_MM,aEntry.aValue); + if (aEntry.bCanNum) { + aEntry.aValue.InsertAscii(": ",0); + aEntry.aValue.Insert(UniString::CreateFromInt32(aEntry.nVal),0); + } + } else { + if (aEntry.eItemType==ITEM_BOOL) aEntry.aValue.AppendAscii(aEntry.nVal!=0 ? "True" : "False"); + else if (aEntry.bCanNum) aEntry.aValue = UniString::CreateFromInt32(aEntry.nVal); + else if (aEntry.eItemType==ITEM_STRING) aEntry.aValue=((SfxStringItem&)rItem).GetValue(); + else if (aEntry.eItemType==ITEM_ENUM && nWhich!=EE_CHAR_WEIGHT) aEntry.aValue=((SfxEnumItemInterface&)rItem).GetValueTextByPos((BOOL)aEntry.nVal); + else aEntry.aValue = String("GPF", aTextEncoding); + } + } else { + aEntry.aValue = String("InvalidItem", aTextEncoding); + } + ImpSetEntry(aEntry,nEntryNum); + nEntryNum++; + } + } + nWhich=aIter.NextWhich(); + } // while + + if (aList.Count()>nEntryNum) { // evtl. noch zuviele Eintraege + ULONG nTooMuch=aList.Count()-nEntryNum; + for (ULONG nNum=0; nNum<nTooMuch; nNum++) { + delete ImpGetEntry(nEntryNum); + aList.Remove(nEntryNum); + } + RowRemoved(nEntryNum,nTooMuch); + } + } else { + Clear(); // wenn pSet==NULL + } + ImpRestoreWhich(); + SetMode(MYBROWSEMODE); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +_SdrItemBrowserWindow::_SdrItemBrowserWindow(Window* pParent, WinBits nBits): + FloatingWindow(pParent,nBits), + aBrowse(this) +{ + SetOutputSizePixel(aBrowse.GetSizePixel()); + SetText(String("Joe's ItemBrowser", gsl_getSystemTextEncoding())); + aBrowse.Show(); +} + +__EXPORT _SdrItemBrowserWindow::~_SdrItemBrowserWindow() +{ +} + +void __EXPORT _SdrItemBrowserWindow::Resize() +{ + aBrowse.SetSizePixel(GetOutputSizePixel()); +} + +void __EXPORT _SdrItemBrowserWindow::GetFocus() +{ + aBrowse.GrabFocus(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrItemBrowser::SdrItemBrowser(SdrView& rView): + _SdrItemBrowserWindow(ImpGetViewWin(rView)), + pView(&rView), + bDirty(FALSE) +{ + aIdleTimer.SetTimeoutHdl(LINK(this,SdrItemBrowser,IdleHdl)); + GetBrowserControl().SetEntryChangedHdl(LINK(this,SdrItemBrowser,ChangedHdl)); + GetBrowserControl().SetSetDirtyHdl(LINK(this,SdrItemBrowser,SetDirtyHdl)); + SetDirty(); +} + +Window* SdrItemBrowser::ImpGetViewWin(SdrView& rView) +{ + const sal_uInt32 nWinCount(rView.PaintWindowCount()); + + for(sal_uInt32 a(0L); a < nWinCount; a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + + if(OUTDEV_WINDOW == pCandidate->GetOutputDevice().GetOutDevType()) + { + return (Window*)(&pCandidate->GetOutputDevice()); + } + } + + return 0L; +} + +void SdrItemBrowser::ForceParent() +{ + Window* pWin=ImpGetViewWin(*pView); + if (pWin!=NULL) SetParent(pWin); +} + +void SdrItemBrowser::SetDirty() +{ + if (!bDirty) { + bDirty=TRUE; + aIdleTimer.SetTimeout(1); + aIdleTimer.Start(); + } +} + +void SdrItemBrowser::Undirty() +{ + aIdleTimer.Stop(); + bDirty = FALSE; + +// SfxItemSet aSet(pView->GetAttributes()); + SfxItemSet aSet(pView->GetModel()->GetItemPool()); + pView->GetAttributes(aSet); + + if(pView->AreObjectsMarked()) + { + // SfxItemSet a2ndSet(pView->GetAttributes(TRUE)); + SfxItemSet a2ndSet(pView->GetModel()->GetItemPool()); + pView->GetAttributes(a2ndSet, TRUE); + + SetAttributes(&aSet,&a2ndSet); + } + else + { + SetAttributes(&aSet); + } +} + +IMPL_LINK(SdrItemBrowser,IdleHdl,Timer*,EMPTYARG) +{ + Undirty(); + return 0; +} + +IMPL_LINK(SdrItemBrowser,ChangedHdl,_SdrItemBrowserControl*,pBrowse) +{ + const ImpItemListRow* pEntry=pBrowse->GetAktChangeEntry(); + if (pEntry!=NULL) + { +// SfxItemSet aSet(pView->GetAttributes()); + SfxItemSet aSet(pView->GetModel()->GetItemPool()); + pView->GetAttributes(aSet); + + SfxItemSet aNewSet(*aSet.GetPool(),pEntry->nWhichId,pEntry->nWhichId); + XubString aNewText(pBrowse->GetNewEntryValue()); + BOOL bDel( aNewText.EqualsAscii("del") + || aNewText.EqualsAscii("Del") + || aNewText.EqualsAscii("DEL") + || aNewText.EqualsAscii("default") + || aNewText.EqualsAscii("Default") + || aNewText.EqualsAscii("DEFAULT")); + + if (!bDel) { + SfxPoolItem* pNewItem=aSet.Get(pEntry->nWhichId).Clone(); + long nLongVal=0; + nLongVal = aNewText.ToInt32(); + if (pEntry->bCanNum) { + if (nLongVal>pEntry->nMax) nLongVal=pEntry->nMax; + if (nLongVal<pEntry->nMin) nLongVal=pEntry->nMin; + } + FASTBOOL bPair=FALSE; + FASTBOOL bPairX=TRUE; + FASTBOOL bPairY=FALSE; + USHORT nSepLen=1; + long nLongX = aNewText.ToInt32(); + long nLongY=0; + xub_StrLen nPos = aNewText.Search(sal_Unicode('/')); + if (nPos==STRING_NOTFOUND) nPos=aNewText.Search(sal_Unicode(':')); + if (nPos==STRING_NOTFOUND) nPos=aNewText.Search(sal_Unicode(' ')); + if (nPos==STRING_NOTFOUND) { nPos=aNewText.SearchAscii(".."); if (nPos!=STRING_NOTFOUND) nSepLen=2; } + if (nPos!=STRING_NOTFOUND) { + bPair=TRUE; + bPairX=nPos>0; + XubString s(aNewText); + s.Erase(0,nPos+nSepLen); + bPairY = (BOOL)aNewText.Len(); + nLongY = s.ToInt32(); + } + switch (pEntry->eItemType) { + case ITEM_BYTE : ((SfxByteItem *)pNewItem)->SetValue((BYTE )nLongVal); break; + case ITEM_INT16 : ((SfxInt16Item *)pNewItem)->SetValue((INT16 )nLongVal); break; + case ITEM_UINT16: ((SfxUInt16Item*)pNewItem)->SetValue((UINT16)nLongVal); break; + case ITEM_INT32: { + if(HAS_BASE(SdrAngleItem, pNewItem)) + { + aNewText.SearchAndReplace(sal_Unicode(','), sal_Unicode('.')); + double nVal = aNewText.ToFloat(); + nLongVal = (long)(nVal * 100 + 0.5); + } + ((SfxInt32Item *)pNewItem)->SetValue((INT32)nLongVal); + } break; + case ITEM_UINT32: ((SfxUInt32Item*)pNewItem)->SetValue(aNewText.ToInt32()); break; + case ITEM_ENUM : ((SfxEnumItemInterface*)pNewItem)->SetEnumValue((USHORT)nLongVal); break; + case ITEM_BOOL: { + aNewText.ToUpperAscii(); + if (aNewText.EqualsAscii("TRUE")) nLongVal=1; + if (aNewText.EqualsAscii("JA")) nLongVal=1; + if (aNewText.EqualsAscii("AN")) nLongVal=1; + if (aNewText.EqualsAscii("EIN")) nLongVal=1; + if (aNewText.EqualsAscii("ON")) nLongVal=1; + if (aNewText.EqualsAscii("YES")) nLongVal=1; + ((SfxBoolItem*)pNewItem)->SetValue((BOOL)nLongVal); + } break; + case ITEM_FLAG : ((SfxFlagItem *)pNewItem)->SetValue((USHORT)nLongVal); break; + case ITEM_STRING: ((SfxStringItem*)pNewItem)->SetValue(aNewText); break; + case ITEM_POINT : ((SfxPointItem*)pNewItem)->SetValue(Point(nLongX,nLongY)); break; + case ITEM_RECT : break; + case ITEM_RANGE : { + ((SfxRangeItem*)pNewItem)->From()=(USHORT)nLongX; + ((SfxRangeItem*)pNewItem)->From()=(USHORT)nLongY; + } break; + case ITEM_LRANGE : { + } break; + case ITEM_FRACTION: { + if (!bPairX) nLongX=1; + if (!bPairY) nLongY=1; + ((SdrFractionItem*)pNewItem)->SetValue(Fraction(nLongX,nLongY)); + } break; + case ITEM_XCOLOR: break; + case ITEM_COLOR: break; + case ITEM_FONT: { + ((SvxFontItem*)pNewItem)->GetFamily()=FAMILY_DONTKNOW; + ((SvxFontItem*)pNewItem)->GetFamilyName()=aNewText; + ((SvxFontItem*)pNewItem)->GetStyleName().Erase(); + } break; + case ITEM_FONTHEIGHT: { + ULONG nHgt=0; + USHORT nProp=100; + if (aNewText.Search(sal_Unicode('%'))!=STRING_NOTFOUND) { + nProp=(USHORT)nLongVal; + } else { + nHgt=nLongVal; + } + ((SvxFontHeightItem*)pNewItem)->SetHeight(nHgt,nProp); + } break; + case ITEM_FONTWIDTH: { + USHORT nProp=100; + if (aNewText.Search(sal_Unicode('%'))!=STRING_NOTFOUND) { + nProp=(USHORT)nLongVal; + } + ((SvxCharScaleWidthItem*)pNewItem)->SetValue(nProp); + } break; + case ITEM_FIELD: break; + default: break; + } // switch + aNewSet.Put(*pNewItem); + delete pNewItem; + } + pView->SetAttributes(aNewSet,bDel); + } + return 0; +} + +IMPL_LINK(SdrItemBrowser,SetDirtyHdl,_SdrItemBrowserControl*,EMPTYARG) +{ + SetDirty(); + return 0; +} + + diff --git a/svx/source/svdraw/svditer.cxx b/svx/source/svdraw/svditer.cxx new file mode 100644 index 000000000000..30c423c7178c --- /dev/null +++ b/svx/source/svdraw/svditer.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include "svditer.hxx" +#include <svx/svdpage.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdmark.hxx> + +// #99190# +#include <svx/scene3d.hxx> + +SdrObjListIter::SdrObjListIter(const SdrObjList& rObjList, SdrIterMode eMode, BOOL bReverse) +: maObjList(1024, 64, 64), + mnIndex(0L), + mbReverse(bReverse) +{ + ImpProcessObjectList(rObjList, eMode, TRUE); + Reset(); +} + +SdrObjListIter::SdrObjListIter(const SdrObjList& rObjList, BOOL bUseZOrder, SdrIterMode eMode, BOOL bReverse) +: maObjList(1024, 64, 64), + mnIndex(0L), + mbReverse(bReverse) +{ + ImpProcessObjectList(rObjList, eMode, bUseZOrder); + Reset(); +} + +SdrObjListIter::SdrObjListIter( const SdrObject& rObj, SdrIterMode eMode, BOOL bReverse ) +: maObjList(1024, 64, 64), + mnIndex(0L), + mbReverse(bReverse) +{ + if ( rObj.ISA( SdrObjGroup ) ) + ImpProcessObjectList(*rObj.GetSubList(), eMode, TRUE); + else + maObjList.Insert( (void*)&rObj, LIST_APPEND ); + Reset(); +} + +SdrObjListIter::SdrObjListIter( const SdrMarkList& rMarkList, SdrIterMode eMode, BOOL bReverse ) +: maObjList(1024, 64, 64), + mnIndex(0L), + mbReverse(bReverse) +{ + ImpProcessMarkList(rMarkList, eMode); + Reset(); +} + +void SdrObjListIter::ImpProcessObjectList(const SdrObjList& rObjList, SdrIterMode eMode, BOOL bUseZOrder) +{ + for( ULONG nIdx = 0, nCount = rObjList.GetObjCount(); nIdx < nCount; ++nIdx ) + { + SdrObject* pObj = bUseZOrder ? + rObjList.GetObj( nIdx ) : rObjList.GetObjectForNavigationPosition( nIdx ); + OSL_ASSERT( pObj != 0 ); + if( pObj ) + ImpProcessObj( pObj, eMode, bUseZOrder ); + } +} + +void SdrObjListIter::ImpProcessMarkList( const SdrMarkList& rMarkList, SdrIterMode eMode ) +{ + for( ULONG nIdx = 0, nCount = rMarkList.GetMarkCount(); nIdx < nCount; ++nIdx ) + if( SdrObject* pObj = rMarkList.GetMark( nIdx )->GetMarkedSdrObj() ) + ImpProcessObj( pObj, eMode, FALSE ); +} + +void SdrObjListIter::ImpProcessObj(SdrObject* pObj, SdrIterMode eMode, BOOL bUseZOrder) +{ + bool bIsGroup = pObj->IsGroupObject(); + // #99190# 3D objects are no group objects, IsGroupObject() + // only tests if pSub is not null ptr :-( + if( bIsGroup && pObj->ISA( E3dObject ) && !pObj->ISA( E3dScene ) ) + bIsGroup = false; + + if( !bIsGroup || (eMode != IM_DEEPNOGROUPS) ) + maObjList.Insert( pObj, LIST_APPEND ); + + if( bIsGroup && (eMode != IM_FLAT) ) + ImpProcessObjectList( *pObj->GetSubList(), eMode, bUseZOrder ); +} diff --git a/svx/source/svdraw/svditext.hxx b/svx/source/svdraw/svditext.hxx new file mode 100644 index 000000000000..b181b4046f9e --- /dev/null +++ b/svx/source/svdraw/svditext.hxx @@ -0,0 +1,37 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVDITEXT_HXX +#define _SVDITEXT_HXX + +// SvxItem-Mapping. Wird benoetigt um die SvxItem-Header erfolgreich zu includen + +#include <editeng/editdata.hxx> + + +#endif // _SVDITEXT_HXX + diff --git a/svx/source/svdraw/svdlayer.cxx b/svx/source/svdraw/svdlayer.cxx new file mode 100644 index 000000000000..098c036dcad7 --- /dev/null +++ b/svx/source/svdraw/svdlayer.cxx @@ -0,0 +1,458 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <com/sun/star/uno/Sequence.hxx> + +#include <svx/svdlayer.hxx> +#include <svx/svdmodel.hxx> // fuer Broadcasting +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Namen aus der Resource + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SetOfByte +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_Bool SetOfByte::IsEmpty() const +{ + for(sal_uInt16 i(0); i < 32; i++) + { + if(aData[i] != 0) + return sal_False; + } + + return sal_True; +} + +sal_Bool SetOfByte::IsFull() const +{ + for(sal_uInt16 i(0); i < 32; i++) + { + if(aData[i] != 0xFF) + return sal_False; + } + + return sal_True; +} + +sal_uInt16 SetOfByte::GetSetCount() const +{ + sal_uInt16 nRet(0); + + for(sal_uInt16 i(0); i < 32; i++) + { + sal_uInt8 a(aData[i]); + + if(a != 0) + { + if(a & 0x80) nRet++; + if(a & 0x40) nRet++; + if(a & 0x20) nRet++; + if(a & 0x10) nRet++; + if(a & 0x08) nRet++; + if(a & 0x04) nRet++; + if(a & 0x02) nRet++; + if(a & 0x01) nRet++; + } + } + + return nRet; +} + +sal_uInt8 SetOfByte::GetSetBit(sal_uInt16 nNum) const +{ + nNum++; + sal_uInt16 i(0), j(0); + sal_uInt16 nRet(0); + + while(j < nNum && i < 256) + { + if(IsSet(sal_uInt8(i))) + j++; + i++; + } + + if(j == nNum) + nRet = i - 1; + + return sal_uInt8(nRet); +} + +sal_uInt16 SetOfByte::GetClearCount() const +{ + return sal_uInt16(256 - GetSetCount()); +} + +sal_uInt8 SetOfByte::GetClearBit(sal_uInt16 nNum) const +{ + nNum++; + sal_uInt16 i(0), j(0); + sal_uInt16 nRet(0); + + while(j < nNum && i < 256) + { + if(!IsSet(sal_uInt8(i))) + j++; + i++; + } + + if(j == nNum) + nRet = i - 1; + + return sal_uInt8(nRet); +} + +void SetOfByte::operator&=(const SetOfByte& r2ndSet) +{ + for(sal_uInt16 i(0); i < 32; i++) + { + aData[i] &= r2ndSet.aData[i]; + } +} + +void SetOfByte::operator|=(const SetOfByte& r2ndSet) +{ + for(sal_uInt16 i(0); i < 32; i++) + { + aData[i] |= r2ndSet.aData[i]; + } +} + +/** initialize this set with a uno sequence of sal_Int8 +*/ +void SetOfByte::PutValue( const com::sun::star::uno::Any & rAny ) +{ + com::sun::star::uno::Sequence< sal_Int8 > aSeq; + if( rAny >>= aSeq ) + { + sal_Int16 nCount = (sal_Int16)aSeq.getLength(); + if( nCount > 32 ) + nCount = 32; + + sal_Int16 nIndex; + for( nIndex = 0; nIndex < nCount; nIndex++ ) + { + aData[nIndex] = static_cast<BYTE>(aSeq[nIndex]); + } + + for( ; nIndex < 32; nIndex++ ) + { + aData[nIndex] = 0; + } + } +} + +/** returns a uno sequence of sal_Int8 +*/ +void SetOfByte::QueryValue( com::sun::star::uno::Any & rAny ) const +{ + sal_Int16 nNumBytesSet = 0; + sal_Int16 nIndex; + for( nIndex = 31; nIndex >= 00; nIndex-- ) + { + if( 0 != aData[nIndex] ) + { + nNumBytesSet = nIndex + 1; + break; + } + } + + com::sun::star::uno::Sequence< sal_Int8 > aSeq( nNumBytesSet ); + + for( nIndex = 0; nIndex < nNumBytesSet; nIndex++ ) + { + aSeq[nIndex] = static_cast<sal_Int8>(aData[nIndex]); + } + + rAny <<= aSeq; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrLayer +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrLayer::SetStandardLayer(FASTBOOL bStd) +{ + nType=(UINT16)bStd; + if (bStd) { + aName=ImpGetResStr(STR_StandardLayerName); + } + if (pModel!=NULL) { + SdrHint aHint(HINT_LAYERCHG); + pModel->Broadcast(aHint); + pModel->SetChanged(); + } +} + +void SdrLayer::SetName(const XubString& rNewName) +{ + if(!rNewName.Equals(aName)) + { + aName = rNewName; + nType = 0; // Userdefined + + if(pModel) + { + SdrHint aHint(HINT_LAYERCHG); + + pModel->Broadcast(aHint); + pModel->SetChanged(); + } + } +} + +bool SdrLayer::operator==(const SdrLayer& rCmpLayer) const +{ + return (nID == rCmpLayer.nID + && nType == rCmpLayer.nType + && aName.Equals(rCmpLayer.aName)); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SdrLayerAdmin +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrLayerAdmin::SdrLayerAdmin(SdrLayerAdmin* pNewParent): + aLayer(1024,16,16), + aLSets(1024,16,16), + pModel(NULL) +{ + sal_Char aTextControls[] = "Controls"; + aControlLayerName = String(aTextControls, sizeof(aTextControls-1)); + pParent=pNewParent; +} + +SdrLayerAdmin::SdrLayerAdmin(const SdrLayerAdmin& rSrcLayerAdmin): + aLayer(1024,16,16), + aLSets(1024,16,16), + pParent(NULL), + pModel(NULL) +{ + sal_Char aTextControls[] = "Controls"; + aControlLayerName = String(aTextControls, sizeof(aTextControls-1)); + *this = rSrcLayerAdmin; +} + +SdrLayerAdmin::~SdrLayerAdmin() +{ + ClearLayer(); +} + +void SdrLayerAdmin::ClearLayer() +{ + SdrLayer* pL; + pL=(SdrLayer*)aLayer.First(); + while (pL!=NULL) { + delete pL; + pL=(SdrLayer*)aLayer.Next(); + } + aLayer.Clear(); +} + +const SdrLayerAdmin& SdrLayerAdmin::operator=(const SdrLayerAdmin& rSrcLayerAdmin) +{ + ClearLayer(); + pParent=rSrcLayerAdmin.pParent; + USHORT i; + USHORT nAnz=rSrcLayerAdmin.GetLayerCount(); + for (i=0; i<nAnz; i++) { + aLayer.Insert(new SdrLayer(*rSrcLayerAdmin.GetLayer(i)),CONTAINER_APPEND); + } + return *this; +} + +bool SdrLayerAdmin::operator==(const SdrLayerAdmin& rCmpLayerAdmin) const +{ + if (pParent!=rCmpLayerAdmin.pParent || + aLayer.Count()!=rCmpLayerAdmin.aLayer.Count() || + aLSets.Count()!=rCmpLayerAdmin.aLSets.Count()) return FALSE; + FASTBOOL bOk=TRUE; + USHORT nAnz=GetLayerCount(); + USHORT i=0; + while (bOk && i<nAnz) { + bOk=*GetLayer(i)==*rCmpLayerAdmin.GetLayer(i); + i++; + } + return bOk; +} + +void SdrLayerAdmin::SetModel(SdrModel* pNewModel) +{ + if (pNewModel!=pModel) { + pModel=pNewModel; + USHORT nAnz=GetLayerCount(); + USHORT i; + for (i=0; i<nAnz; i++) { + GetLayer(i)->SetModel(pNewModel); + } + } +} + +void SdrLayerAdmin::Broadcast() const +{ + if (pModel!=NULL) { + SdrHint aHint(HINT_LAYERORDERCHG); + pModel->Broadcast(aHint); + pModel->SetChanged(); + } +} + +SdrLayer* SdrLayerAdmin::RemoveLayer(USHORT nPos) +{ + SdrLayer* pRetLayer=(SdrLayer*)(aLayer.Remove(nPos)); + Broadcast(); + return pRetLayer; +} + +SdrLayer* SdrLayerAdmin::NewLayer(const XubString& rName, USHORT nPos) +{ + SdrLayerID nID=GetUniqueLayerID(); + SdrLayer* pLay=new SdrLayer(nID,rName); + pLay->SetModel(pModel); + aLayer.Insert(pLay,nPos); + Broadcast(); + return pLay; +} + +SdrLayer* SdrLayerAdmin::NewStandardLayer(USHORT nPos) +{ + SdrLayerID nID=GetUniqueLayerID(); + SdrLayer* pLay=new SdrLayer(nID,String()); + pLay->SetStandardLayer(); + pLay->SetModel(pModel); + aLayer.Insert(pLay,nPos); + Broadcast(); + return pLay; +} + +SdrLayer* SdrLayerAdmin::MoveLayer(USHORT nPos, USHORT nNewPos) +{ + SdrLayer* pLayer=(SdrLayer*)(aLayer.Remove(nPos)); + if (pLayer!=NULL) { + aLayer.Insert(pLayer,nNewPos); + } + + Broadcast(); + return pLayer; +} + +void SdrLayerAdmin::MoveLayer(SdrLayer* pLayer, USHORT nNewPos) +{ + ULONG nPos=aLayer.GetPos(pLayer); + if (nPos!=CONTAINER_ENTRY_NOTFOUND) { + aLayer.Remove(nPos); + aLayer.Insert(pLayer,nNewPos); + Broadcast(); + } +} + +USHORT SdrLayerAdmin::GetLayerPos(SdrLayer* pLayer) const +{ + ULONG nRet=SDRLAYER_NOTFOUND; + if (pLayer!=NULL) { + nRet=aLayer.GetPos(pLayer); + if (nRet==CONTAINER_ENTRY_NOTFOUND) { + nRet=SDRLAYER_NOTFOUND; + } + } + return USHORT(nRet); +} + +const SdrLayer* SdrLayerAdmin::GetLayer(const XubString& rName, FASTBOOL /*bInherited*/) const +{ + UINT16 i(0); + const SdrLayer* pLay = NULL; + + while(i < GetLayerCount() && !pLay) + { + if(rName.Equals(GetLayer(i)->GetName())) + pLay = GetLayer(i); + else + i++; + } + + if(!pLay && pParent) + { + pLay = pParent->GetLayer(rName, TRUE); + } + + return pLay; +} + +SdrLayerID SdrLayerAdmin::GetLayerID(const XubString& rName, FASTBOOL bInherited) const +{ + SdrLayerID nRet=SDRLAYER_NOTFOUND; + const SdrLayer* pLay=GetLayer(rName,bInherited); + if (pLay!=NULL) nRet=pLay->GetID(); + return nRet; +} + +const SdrLayer* SdrLayerAdmin::GetLayerPerID(USHORT nID) const +{ + USHORT i=0; + const SdrLayer* pLay=NULL; + while (i<GetLayerCount() && pLay==NULL) { + if (nID==GetLayer(i)->GetID()) pLay=GetLayer(i); + else i++; + } + return pLay; +} + +// Globale LayerID's beginnen mit 0 aufsteigend. +// Lokale LayerID's beginnen mit 254 absteigend. +// 255 ist reserviert fuer SDRLAYER_NOTFOUND + +SdrLayerID SdrLayerAdmin::GetUniqueLayerID() const +{ + SetOfByte aSet; + sal_Bool bDown = (pParent == NULL); + USHORT j; + for (j=0; j<GetLayerCount(); j++) + { + aSet.Set(GetLayer((sal_uInt16)j)->GetID()); + } + SdrLayerID i; + if (!bDown) + { + i=254; + while (i && aSet.IsSet(BYTE(i))) + --i; + if (i == 0) + i=254; + } + else + { + i=0; + while (i<=254 && aSet.IsSet(BYTE(i))) + i++; + if (i>254) + i=0; + } + return i; +} + diff --git a/svx/source/svdraw/svdmark.cxx b/svx/source/svdraw/svdmark.cxx new file mode 100644 index 000000000000..c871865ac87b --- /dev/null +++ b/svx/source/svdraw/svdmark.cxx @@ -0,0 +1,1040 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include <svx/svdmark.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include "svditer.hxx" +#include <svx/svdpagv.hxx> +#include <svx/svdopath.hxx> // zur Abschaltung +#include <svx/svdogrp.hxx> // des Cache bei +#include <svx/svdorect.hxx> // GetMarkDescription +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#include <svx/obj3d.hxx> +#include <svx/scene3d.hxx> +#include <svl/brdcst.hxx> +#include <svx/svdoedge.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpSdrUShortContSorter: public ContainerSorter +{ +public: + ImpSdrUShortContSorter(Container& rNewCont) + : ContainerSorter(rNewCont) + {} + + virtual int Compare(const void* pElem1, const void* pElem2) const; +}; + +int ImpSdrUShortContSorter::Compare(const void* pElem1, const void* pElem2) const +{ + sal_uInt16 n1((sal_uInt16)((sal_uIntPtr)pElem1)); + sal_uInt16 n2((sal_uInt16)((sal_uIntPtr)pElem2)); + + return ((n1 < n2) ? (-1) : (n1 > n2) ? (1) : (0)); +} + +void SdrUShortCont::Sort() const +{ + ImpSdrUShortContSorter aSort(*((Container*)(&maArray))); + aSort.DoSort(); + ((SdrUShortCont*)this)->mbSorted = sal_True; + + ULONG nNum(GetCount()); + + if(nNum > 1) + { + nNum--; + sal_uInt16 nVal0 = GetObject(nNum); + + while(nNum > 0) + { + nNum--; + sal_uInt16 nVal1 = GetObject(nNum); + + if(nVal1 == nVal0) + { + ((SdrUShortCont*)this)->Remove(nNum); + } + + nVal0 = nVal1; + } + } +} + +void SdrUShortCont::CheckSort(ULONG nPos) +{ + ULONG nAnz(maArray.Count()); + + if(nPos > nAnz) + nPos = nAnz; + + sal_uInt16 nAktVal = GetObject(nPos); + + if(nPos > 0) + { + sal_uInt16 nPrevVal = GetObject(nPos - 1); + + if(nPrevVal >= nAktVal) + mbSorted = sal_False; + } + + if(nPos < nAnz - 1) + { + sal_uInt16 nNextVal = GetObject(nPos + 1); + + if(nNextVal <= nAktVal) + mbSorted = sal_False; + } +} + +std::set< sal_uInt16 > SdrUShortCont::getContainer() +{ + std::set< sal_uInt16 > aSet; + + sal_uInt32 nAnz = maArray.Count(); + while(nAnz) + aSet.insert( GetObject(--nAnz) ); + + return aSet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrMark::SdrMark(SdrObject* pNewObj, SdrPageView* pNewPageView) +: mpSelectedSdrObject(pNewObj), + mpPageView(pNewPageView), + mpPoints(0L), + mpLines(0L), + mpGluePoints(0L), + mbCon1(sal_False), + mbCon2(sal_False), + mnUser(0) +{ + if(mpSelectedSdrObject) + { + mpSelectedSdrObject->AddObjectUser( *this ); + } +} + +SdrMark::SdrMark(const SdrMark& rMark) +: ObjectUser(), + mpSelectedSdrObject(0L), + mpPageView(0L), + mpPoints(0L), + mpLines(0L), + mpGluePoints(0L), + mbCon1(sal_False), + mbCon2(sal_False), + mnUser(0) +{ + *this = rMark; +} + +SdrMark::~SdrMark() +{ + if(mpSelectedSdrObject) + { + mpSelectedSdrObject->RemoveObjectUser( *this ); + } + + if(mpPoints) + { + delete mpPoints; + } + + if(mpLines) + { + delete mpLines; + } + + if(mpGluePoints) + { + delete mpGluePoints; + } +} + +void SdrMark::ObjectInDestruction(const SdrObject& rObject) +{ + (void) rObject; // avoid warnings + OSL_ENSURE(mpSelectedSdrObject && mpSelectedSdrObject == &rObject, "SdrMark::ObjectInDestruction: called form object different from hosted one (!)"); + OSL_ENSURE(mpSelectedSdrObject, "SdrMark::ObjectInDestruction: still seleceted SdrObject is deleted, deselect first (!)"); + mpSelectedSdrObject = 0L; +} + +void SdrMark::SetMarkedSdrObj(SdrObject* pNewObj) +{ + if(mpSelectedSdrObject) + { + mpSelectedSdrObject->RemoveObjectUser( *this ); + } + + mpSelectedSdrObject = pNewObj; + + if(mpSelectedSdrObject) + { + mpSelectedSdrObject->AddObjectUser( *this ); + } +} + +SdrObject* SdrMark::GetMarkedSdrObj() const +{ + return mpSelectedSdrObject; +} + +SdrMark& SdrMark::operator=(const SdrMark& rMark) +{ + SetMarkedSdrObj(rMark.mpSelectedSdrObject); + mpPageView = rMark.mpPageView; + mbCon1 = rMark.mbCon1; + mbCon2 = rMark.mbCon2; + mnUser = rMark.mnUser; + + if(!rMark.mpPoints) + { + if(mpPoints) + { + delete mpPoints; + mpPoints = 0L; + } + } + else + { + if(!mpPoints) + { + mpPoints = new SdrUShortCont(*rMark.mpPoints); + } + else + { + *mpPoints = *rMark.mpPoints; + } + } + + if(!rMark.mpLines) + { + if(mpLines) + { + delete mpLines; + mpLines = 0L; + } + } + else + { + if(!mpLines) + { + mpLines = new SdrUShortCont(*rMark.mpLines); + } + else + { + *mpLines = *rMark.mpLines; + } + } + + if(!rMark.mpGluePoints) + { + if(mpGluePoints) + { + delete mpGluePoints; + mpGluePoints = 0L; + } + } + else + { + if(!mpGluePoints) + { + mpGluePoints = new SdrUShortCont(*rMark.mpGluePoints); + } + else + { + *mpGluePoints = *rMark.mpGluePoints; + } + } + + return *this; +} + +sal_Bool SdrMark::operator==(const SdrMark& rMark) const +{ + sal_Bool bRet(mpSelectedSdrObject == rMark.mpSelectedSdrObject && mpPageView == rMark.mpPageView && mbCon1 == rMark.mbCon1 && mbCon2 == rMark.mbCon2 && mnUser == rMark.mnUser); + + if((mpPoints != 0L) != (rMark.mpPoints != 0L)) + bRet = sal_False; + + if((mpLines != 0L) != (rMark.mpLines != 0L)) + bRet = sal_False; + + if((mpGluePoints != 0L) != (rMark.mpGluePoints != 0L)) + bRet = sal_False; + + if(bRet && mpPoints && *mpPoints != *rMark.mpPoints) + bRet = sal_False; + + if(bRet && mpLines && *mpLines != *rMark.mpLines) + bRet = sal_False; + + if(bRet && mpGluePoints && *mpGluePoints != *rMark.mpGluePoints) + bRet = sal_False; + + return bRet; +} + +SdrPage* SdrMark::GetPage() const +{ + return (mpSelectedSdrObject ? mpSelectedSdrObject->GetPage() : 0); +} + +SdrObjList* SdrMark::GetObjList() const +{ + return (mpSelectedSdrObject ? mpSelectedSdrObject->GetObjList() : 0); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpSdrMarkListSorter: public ContainerSorter +{ +public: + ImpSdrMarkListSorter(Container& rNewCont) + : ContainerSorter(rNewCont) + {} + + virtual int Compare(const void* pElem1, const void* pElem2) const; +}; + +int ImpSdrMarkListSorter::Compare(const void* pElem1, const void* pElem2) const +{ + SdrObject* pObj1 = ((SdrMark*)pElem1)->GetMarkedSdrObj(); + SdrObject* pObj2 = ((SdrMark*)pElem2)->GetMarkedSdrObj(); + SdrObjList* pOL1 = (pObj1) ? pObj1->GetObjList() : 0L; + SdrObjList* pOL2 = (pObj2) ? pObj2->GetObjList() : 0L; + + if (pOL1 == pOL2) + { + // AF: Note that I reverted a change from sal_uInt32 to ULONG (made + // for 64bit compliance, #i78198#) because internally in SdrObject + // both nOrdNum and mnNavigationPosition are stored as sal_uInt32. + sal_uInt32 nObjOrd1((pObj1) ? pObj1->GetNavigationPosition() : 0); + sal_uInt32 nObjOrd2((pObj2) ? pObj2->GetNavigationPosition() : 0); + + return (nObjOrd1 < nObjOrd2 ? -1 : 1); + } + else + { + return ((long)pOL1 < (long)pOL2) ? -1 : 1; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkList::ForceSort() const +{ + if(!mbSorted) + { + ((SdrMarkList*)this)->ImpForceSort(); + } +} + +void SdrMarkList::ImpForceSort() +{ + if(!mbSorted) + { + mbSorted = sal_True; + ULONG nAnz = maList.Count(); + + // remove invalid + if(nAnz > 0 ) + { + SdrMark* pAkt = (SdrMark*)maList.First(); + while( pAkt ) + { + if(pAkt->GetMarkedSdrObj() == 0) + { + maList.Remove(); + delete pAkt; + } + pAkt= (SdrMark*)maList.Next(); + } + nAnz = maList.Count(); + } + + if(nAnz > 1) + { + ImpSdrMarkListSorter aSort(maList); + aSort.DoSort(); + + // remove duplicates + if(maList.Count() > 1) + { + SdrMark* pAkt = (SdrMark*)maList.Last(); + SdrMark* pCmp = (SdrMark*)maList.Prev(); + + while(pCmp) + { + if(pAkt->GetMarkedSdrObj() == pCmp->GetMarkedSdrObj() && pAkt->GetMarkedSdrObj()) + { + // Con1/Con2 Merging + if(pCmp->IsCon1()) + pAkt->SetCon1(sal_True); + + if(pCmp->IsCon2()) + pAkt->SetCon2(sal_True); + + // pCmp loeschen. + maList.Remove(); + + delete pCmp; + } + else + { + pAkt = pCmp; + } + + pCmp = (SdrMark*)maList.Prev(); + } + } + } + } +} + +void SdrMarkList::Clear() +{ + for(ULONG i(0L); i < GetMarkCount(); i++) + { + SdrMark* pMark = GetMark(i); + delete pMark; + } + + maList.Clear(); + SetNameDirty(); +} + +void SdrMarkList::operator=(const SdrMarkList& rLst) +{ + Clear(); + + for(ULONG i(0L); i < rLst.GetMarkCount(); i++) + { + SdrMark* pMark = rLst.GetMark(i); + SdrMark* pNeuMark = new SdrMark(*pMark); + maList.Insert(pNeuMark, CONTAINER_APPEND); + } + + maMarkName = rLst.maMarkName; + mbNameOk = rLst.mbNameOk; + maPointName = rLst.maPointName; + mbPointNameOk = rLst.mbPointNameOk; + maGluePointName = rLst.maGluePointName; + mbGluePointNameOk = rLst.mbGluePointNameOk; + mbSorted = rLst.mbSorted; +} + +ULONG SdrMarkList::FindObject(const SdrObject* pObj) const +{ + // #109658# + // + // Since relying on OrdNums is not allowed for the selection because objects in the + // selection may not be inserted in a list if they are e.g. modified ATM, i changed + // this loop to just look if the object pointer is in the selection. + // + // Problem is that GetOrdNum() which is const, internally casts to non-const and + // hardly sets the OrdNum member of the object (nOrdNum) to 0 (ZERO) if the object + // is not inserted in a object list. + // Since this may be by purpose and necessary somewhere else i decided that it is + // less dangerous to change this method then changing SdrObject::GetOrdNum(). + if(pObj && maList.Count()) + { + for(ULONG a(0L); a < maList.Count(); a++) + { + if(((SdrMark*)(maList.GetObject(a)))->GetMarkedSdrObj() == pObj) + { + return a; + } + } + } + + return CONTAINER_ENTRY_NOTFOUND; +} + +void SdrMarkList::InsertEntry(const SdrMark& rMark, sal_Bool bChkSort) +{ + SetNameDirty(); + ULONG nAnz(maList.Count()); + + if(!bChkSort || !mbSorted || nAnz == 0) + { + if(!bChkSort) + mbSorted = sal_False; + + maList.Insert(new SdrMark(rMark), CONTAINER_APPEND); + } + else + { + SdrMark* pLast = GetMark(ULONG(nAnz - 1)); + const SdrObject* pLastObj = pLast->GetMarkedSdrObj(); + const SdrObject* pNeuObj = rMark.GetMarkedSdrObj(); + + if(pLastObj == pNeuObj) + { + // Aha, den gibt's schon + // Con1/Con2 Merging + if(rMark.IsCon1()) + pLast->SetCon1(sal_True); + + if(rMark.IsCon2()) + pLast->SetCon2(sal_True); + } + else + { + SdrMark* pKopie = new SdrMark(rMark); + maList.Insert(pKopie, CONTAINER_APPEND); + + // und nun checken, ob die Sortierung noch ok ist + const SdrObjList* pLastOL = pLastObj!=0L ? pLastObj->GetObjList() : 0L; + const SdrObjList* pNeuOL = pNeuObj !=0L ? pNeuObj ->GetObjList() : 0L; + + if(pLastOL == pNeuOL) + { + const ULONG nLastNum(pLastObj!=0L ? pLastObj->GetOrdNum() : 0); + const ULONG nNeuNum(pNeuObj !=0L ? pNeuObj ->GetOrdNum() : 0); + + if(nNeuNum < nLastNum) + { + // irgendwann muss mal sortiert werden + mbSorted = sal_False; + } + } + else + { + // irgendwann muss mal sortiert werden + mbSorted = sal_False; + } + } + } + + return; +} + +void SdrMarkList::DeleteMark(ULONG nNum) +{ + SdrMark* pMark = GetMark(nNum); + DBG_ASSERT(pMark!=0L,"DeleteMark: MarkEntry nicht gefunden"); + + if(pMark) + { + maList.Remove(nNum); + delete pMark; + SetNameDirty(); + } +} + +void SdrMarkList::ReplaceMark(const SdrMark& rNewMark, ULONG nNum) +{ + SdrMark* pMark = GetMark(nNum); + DBG_ASSERT(pMark!=0L,"ReplaceMark: MarkEntry nicht gefunden"); + + if(pMark) + { + delete pMark; + SetNameDirty(); + SdrMark* pKopie = new SdrMark(rNewMark); + maList.Replace(pKopie, nNum); + mbSorted = sal_False; + } +} + +void SdrMarkList::Merge(const SdrMarkList& rSrcList, sal_Bool bReverse) +{ + ULONG nAnz(rSrcList.maList.Count()); + + if(rSrcList.mbSorted) + { + // Merging ohne ein Sort bei rSrcList zu erzwingen + bReverse = sal_False; + } + + if(!bReverse) + { + for(ULONG i(0L); i < nAnz; i++) + { + SdrMark* pM = (SdrMark*)(rSrcList.maList.GetObject(i)); + InsertEntry(*pM); + } + } + else + { + for(ULONG i(nAnz); i > 0;) + { + i--; + SdrMark* pM = (SdrMark*)(rSrcList.maList.GetObject(i)); + InsertEntry(*pM); + } + } +} + +sal_Bool SdrMarkList::DeletePageView(const SdrPageView& rPV) +{ + sal_Bool bChgd(sal_False); + + for(ULONG i(GetMarkCount()); i > 0; ) + { + i--; + SdrMark* pMark = GetMark(i); + + if(pMark->GetPageView()==&rPV) + { + maList.Remove(i); + delete pMark; + SetNameDirty(); + bChgd = sal_True; + } + } + + return bChgd; +} + +sal_Bool SdrMarkList::InsertPageView(const SdrPageView& rPV) +{ + sal_Bool bChgd(sal_False); + DeletePageView(rPV); // erstmal alle raus, dann die ganze Seite hinten dran + SdrObject* pObj; + const SdrObjList* pOL = rPV.GetObjList(); + ULONG nObjAnz(pOL->GetObjCount()); + + for(ULONG nO(0L); nO < nObjAnz; nO++) + { + pObj = pOL->GetObj(nO); + sal_Bool bDoIt(rPV.IsObjMarkable(pObj)); + + if(bDoIt) + { + SdrMark* pM = new SdrMark(pObj, (SdrPageView*)&rPV); + maList.Insert(pM, CONTAINER_APPEND); + SetNameDirty(); + bChgd = sal_True; + } + } + + return bChgd; +} + +const XubString& SdrMarkList::GetMarkDescription() const +{ + ULONG nAnz(GetMarkCount()); + + if(mbNameOk && 1L == nAnz) + { + // Bei Einfachselektion nur Textrahmen cachen + const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj(); + const SdrTextObj* pTextObj = PTR_CAST(SdrTextObj, pObj); + + if(!pTextObj || !pTextObj->IsTextFrame()) + { + ((SdrMarkList*)(this))->mbNameOk = sal_False; + } + } + + if(!mbNameOk) + { + SdrMark* pMark = GetMark(0); + XubString aNam; + + if(!nAnz) + { + ((SdrMarkList*)(this))->maMarkName = ImpGetResStr(STR_ObjNameNoObj); + } + else if(1L == nAnz) + { + if(pMark->GetMarkedSdrObj()) + { + pMark->GetMarkedSdrObj()->TakeObjNameSingul(aNam); + } + } + else + { + if(pMark->GetMarkedSdrObj()) + { + pMark->GetMarkedSdrObj()->TakeObjNamePlural(aNam); + XubString aStr1; + sal_Bool bEq(sal_True); + + for(ULONG i = 1; i < GetMarkCount() && bEq; i++) + { + SdrMark* pMark2 = GetMark(i); + pMark2->GetMarkedSdrObj()->TakeObjNamePlural(aStr1); + bEq = aNam.Equals(aStr1); + } + + if(!bEq) + { + aNam = ImpGetResStr(STR_ObjNamePlural); + } + } + + aNam.Insert(sal_Unicode(' '), 0); + aNam.Insert(UniString::CreateFromInt32(nAnz), 0); + } + + ((SdrMarkList*)(this))->maMarkName = aNam; + ((SdrMarkList*)(this))->mbNameOk = sal_True; + } + + return maMarkName; +} + +const XubString& SdrMarkList::GetPointMarkDescription(sal_Bool bGlue) const +{ + sal_Bool& rNameOk = (sal_Bool&)(bGlue ? mbGluePointNameOk : mbPointNameOk); + XubString& rName = (XubString&)(bGlue ? maGluePointName : maPointName); + ULONG nMarkAnz(GetMarkCount()); + ULONG nMarkPtAnz(0L); + ULONG nMarkPtObjAnz(0L); + ULONG n1stMarkNum(ULONG_MAX); + + for(ULONG nMarkNum(0L); nMarkNum < nMarkAnz; nMarkNum++) + { + const SdrMark* pMark = GetMark(nMarkNum); + const SdrUShortCont* pPts = bGlue ? pMark->GetMarkedGluePoints() : pMark->GetMarkedPoints(); + ULONG nAnz(pPts ? pPts->GetCount() : 0); + + if(nAnz) + { + if(n1stMarkNum == ULONG_MAX) + { + n1stMarkNum = nMarkNum; + } + + nMarkPtAnz += nAnz; + nMarkPtObjAnz++; + } + + if(nMarkPtObjAnz > 1 && rNameOk) + { + // vorzeitige Entscheidung + return rName; + } + } + + if(rNameOk && 1L == nMarkPtObjAnz) + { + // Bei Einfachselektion nur Textrahmen cachen + const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj(); + const SdrTextObj* pTextObj = PTR_CAST(SdrTextObj,pObj); + + if(!pTextObj || !pTextObj->IsTextFrame()) + { + rNameOk = sal_False; + } + } + + if(!nMarkPtObjAnz) + { + rName.Erase(); + rNameOk = sal_True; + } + else if(!rNameOk) + { + const SdrMark* pMark = GetMark(n1stMarkNum); + XubString aNam; + + if(1L == nMarkPtObjAnz) + { + if(pMark->GetMarkedSdrObj()) + { + pMark->GetMarkedSdrObj()->TakeObjNameSingul(aNam); + } + } + else + { + if(pMark->GetMarkedSdrObj()) + { + pMark->GetMarkedSdrObj()->TakeObjNamePlural(aNam); + } + + XubString aStr1; + sal_Bool bEq(sal_True); + + for(ULONG i(n1stMarkNum + 1L); i < GetMarkCount() && bEq; i++) + { + const SdrMark* pMark2 = GetMark(i); + const SdrUShortCont* pPts = bGlue ? pMark2->GetMarkedGluePoints() : pMark2->GetMarkedPoints(); + + if(pPts && pPts->GetCount() && pMark2->GetMarkedSdrObj()) + { + pMark2->GetMarkedSdrObj()->TakeObjNamePlural(aStr1); + bEq = aNam.Equals(aStr1); + } + } + + if(!bEq) + { + aNam = ImpGetResStr(STR_ObjNamePlural); + } + + aNam.Insert(sal_Unicode(' '), 0); + aNam.Insert(UniString::CreateFromInt32(nMarkPtObjAnz), 0); + } + + XubString aStr1; + + if(1L == nMarkPtAnz) + { + aStr1 = (ImpGetResStr(bGlue ? STR_ViewMarkedGluePoint : STR_ViewMarkedPoint)); + } + else + { + aStr1 = (ImpGetResStr(bGlue ? STR_ViewMarkedGluePoints : STR_ViewMarkedPoints)); + aStr1.SearchAndReplaceAscii("%2", UniString::CreateFromInt32(nMarkPtAnz)); + } + + aStr1.SearchAndReplaceAscii("%1", aNam); + rName = aStr1; + rNameOk = sal_True; + } + + return rName; +} + +sal_Bool SdrMarkList::TakeBoundRect(SdrPageView* pPV, Rectangle& rRect) const +{ + sal_Bool bFnd(sal_False); + Rectangle aR; + + for(ULONG i(0L); i < GetMarkCount(); i++) + { + SdrMark* pMark = GetMark(i); + + if(!pPV || pMark->GetPageView() == pPV) + { + if(pMark->GetMarkedSdrObj()) + { + aR = pMark->GetMarkedSdrObj()->GetCurrentBoundRect(); + + if(bFnd) + { + rRect.Union(aR); + } + else + { + rRect = aR; + bFnd = sal_True; + } + } + } + } + + return bFnd; +} + +sal_Bool SdrMarkList::TakeSnapRect(SdrPageView* pPV, Rectangle& rRect) const +{ + sal_Bool bFnd(sal_False); + + for(ULONG i(0L); i < GetMarkCount(); i++) + { + SdrMark* pMark = GetMark(i); + + if(!pPV || pMark->GetPageView() == pPV) + { + if(pMark->GetMarkedSdrObj()) + { + Rectangle aR(pMark->GetMarkedSdrObj()->GetSnapRect()); + + if(bFnd) + { + rRect.Union(aR); + } + else + { + rRect = aR; + bFnd = sal_True; + } + } + } + } + + return bFnd; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace sdr +{ + ViewSelection::ViewSelection() + : mbEdgesOfMarkedNodesDirty(sal_False) + { + } + + void ViewSelection::SetEdgesOfMarkedNodesDirty() + { + if(!mbEdgesOfMarkedNodesDirty) + { + mbEdgesOfMarkedNodesDirty = sal_True; + maEdgesOfMarkedNodes.Clear(); + maMarkedEdgesOfMarkedNodes.Clear(); + maAllMarkedObjects.Clear(); + } + } + + const SdrMarkList& ViewSelection::GetEdgesOfMarkedNodes() const + { + if(mbEdgesOfMarkedNodesDirty) + { + ((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes(); + } + + return maEdgesOfMarkedNodes; + } + + const SdrMarkList& ViewSelection::GetMarkedEdgesOfMarkedNodes() const + { + if(mbEdgesOfMarkedNodesDirty) + { + ((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes(); + } + + return maMarkedEdgesOfMarkedNodes; + } + + const List& ViewSelection::GetAllMarkedObjects() const + { + if(mbEdgesOfMarkedNodesDirty) + { + ((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes(); + } + + return maAllMarkedObjects; + } + + void ViewSelection::ImplCollectCompleteSelection(SdrObject* pObj) + { + if(pObj) + { + sal_Bool bIsGroup(pObj->IsGroupObject()); + + if(bIsGroup && pObj->ISA(E3dObject) && !pObj->ISA(E3dScene)) + { + bIsGroup = sal_False; + } + + if(bIsGroup) + { + SdrObjList* pList = pObj->GetSubList(); + + for(ULONG a(0L); a < pList->GetObjCount(); a++) + { + SdrObject* pObj2 = pList->GetObj(a); + ImplCollectCompleteSelection(pObj2); + } + } + + maAllMarkedObjects.Insert(pObj, LIST_APPEND); + } + } + + void ViewSelection::ImpForceEdgesOfMarkedNodes() + { + if(mbEdgesOfMarkedNodesDirty) + { + mbEdgesOfMarkedNodesDirty = sal_False; + maMarkedObjectList.ForceSort(); + maEdgesOfMarkedNodes.Clear(); + maMarkedEdgesOfMarkedNodes.Clear(); + maAllMarkedObjects.Clear(); + + // #126320# GetMarkCount after ForceSort + const ULONG nMarkAnz(maMarkedObjectList.GetMarkCount()); + + for(ULONG a(0L); a < nMarkAnz; a++) + { + SdrObject* pCandidate = maMarkedObjectList.GetMark(a)->GetMarkedSdrObj(); + + if(pCandidate) + { + // build transitive hull + ImplCollectCompleteSelection(pCandidate); + + if(pCandidate->IsNode()) + { + // travel over broadcaster/listener to access edges connected to the selected object + const SfxBroadcaster* pBC = pCandidate->GetBroadcaster(); + + if(pBC) + { + sal_uInt16 nLstAnz(pBC->GetListenerCount()); + + for(sal_uInt16 nl(0); nl < nLstAnz; nl++) + { + SfxListener* pLst = pBC->GetListener(nl); + SdrEdgeObj* pEdge = PTR_CAST(SdrEdgeObj, pLst); + + if(pEdge && pEdge->IsInserted() && pEdge->GetPage() == pCandidate->GetPage()) + { + SdrMark aM(pEdge, maMarkedObjectList.GetMark(a)->GetPageView()); + + if(pEdge->GetConnectedNode(sal_True) == pCandidate) + { + aM.SetCon1(sal_True); + } + + if(pEdge->GetConnectedNode(sal_False) == pCandidate) + { + aM.SetCon2(sal_True); + } + + if(CONTAINER_ENTRY_NOTFOUND == maMarkedObjectList.FindObject(pEdge)) + { + // nachsehen, ob er selbst markiert ist + maEdgesOfMarkedNodes.InsertEntry(aM); + } + else + { + maMarkedEdgesOfMarkedNodes.InsertEntry(aM); + } + } + } + } + } + } + } + + maEdgesOfMarkedNodes.ForceSort(); + maMarkedEdgesOfMarkedNodes.ForceSort(); + } + } +} // end of namespace sdr + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx new file mode 100644 index 000000000000..2fcdfdffbb8a --- /dev/null +++ b/svx/source/svdraw/svdmodel.cxx @@ -0,0 +1,2250 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdmodel.hxx> + +#include <rtl/uuid.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <osl/endian.h> +#include <rtl/logfile.hxx> +#include <math.h> +#include <tools/urlobj.hxx> +#include <unotools/ucbstreamhelper.hxx> + +#include <tools/string.hxx> +#include <svl/whiter.hxx> +#include <svx/xit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xlnstit.hxx> + +#include "svditext.hxx" +#include <editeng/editeng.hxx> // Fuer EditEngine::CreatePool() + +#include <svx/xtable.hxx> + +#include "svditer.hxx" +#include <svx/svdtrans.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdlayer.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdotext.hxx> // fuer ReformatAllTextObjects und CalcFieldValue +#include <svx/svdetc.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdoole2.hxx> +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname +#include "svdoutlinercache.hxx" + + +#include <svl/asiancfg.hxx> +#include "editeng/fontitem.hxx" +#include <editeng/colritem.hxx> +#include <editeng/fhgtitem.hxx> +#include <svl/style.hxx> +#include <tools/bigint.hxx> +#include <editeng/numitem.hxx> +#include <editeng/bulitem.hxx> +#include <editeng/outlobj.hxx> +#include "editeng/forbiddencharacterstable.hxx" +#include <svl/zforlist.hxx> +#include <comphelper/processfactory.hxx> + +// #90477# +#include <tools/tenccvt.hxx> +#include <unotools/syslocale.hxx> + +// #95114# +#include <vcl/svapp.hxx> +#include <svx/sdr/properties/properties.hxx> +#include <editeng/eeitem.hxx> +#include <svl/itemset.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct SdrModelImpl +{ + SfxUndoManager* mpUndoManager; + SdrUndoFactory* mpUndoFactory; + bool mbAllowShapePropertyChangeListener; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +DBG_NAME(SdrModel) +TYPEINIT1(SdrModel,SfxBroadcaster); +void SdrModel::ImpCtor(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* _pEmbeddedHelper, + bool bUseExtColorTable, bool bLoadRefCounts) +{ + mpImpl = new SdrModelImpl; + mpImpl->mpUndoManager=0; + mpImpl->mpUndoFactory=0; + mpImpl->mbAllowShapePropertyChangeListener=false; + mbInDestruction=false; + aObjUnit=SdrEngineDefaults::GetMapFraction(); + eObjUnit=SdrEngineDefaults::GetMapUnit(); + eUIUnit=FUNIT_MM; + aUIScale=Fraction(1,1); + nUIUnitKomma=0; + bUIOnlyKomma=FALSE; + pLayerAdmin=NULL; + pItemPool=pPool; + bMyPool=FALSE; + m_pEmbeddedHelper=_pEmbeddedHelper; + pDrawOutliner=NULL; + pHitTestOutliner=NULL; + pRefOutDev=NULL; + nProgressAkt=0; + nProgressMax=0; + nProgressOfs=0; + pDefaultStyleSheet=NULL; + pLinkManager=NULL; + pUndoStack=NULL; + pRedoStack=NULL; + nMaxUndoCount=16; + pAktUndoGroup=NULL; + nUndoLevel=0; + mbUndoEnabled=true; + nProgressPercent=0; + nLoadVersion=0; + bExtColorTable=FALSE; + mbChanged = sal_False; + bInfoChanged=FALSE; + bPagNumsDirty=FALSE; + bMPgNumsDirty=FALSE; + bPageNotValid=FALSE; + bSavePortable=FALSE; + bSaveCompressed=FALSE; + bSaveNative=FALSE; + bSwapGraphics=FALSE; + nSwapGraphicsMode=SDR_SWAPGRAPHICSMODE_DEFAULT; + bSaveOLEPreview=FALSE; + bPasteResize=FALSE; + bNoBitmapCaching=FALSE; + bReadOnly=FALSE; + nStreamCompressMode=COMPRESSMODE_NONE; + nStreamNumberFormat=NUMBERFORMAT_INT_BIGENDIAN; + nDefaultTabulator=0; + pColorTable=NULL; + pDashList=NULL; + pLineEndList=NULL; + pHatchList=NULL; + pGradientList=NULL; + pBitmapList=NULL; + mpNumberFormatter = NULL; + bTransparentTextFrames=FALSE; + bStarDrawPreviewMode = FALSE; + nStarDrawPreviewMasterPageNum = SDRPAGE_NOTFOUND; + pModelStorage = NULL; + mpForbiddenCharactersTable = NULL; + mbModelLocked = FALSE; + mpOutlinerCache = NULL; + mbKernAsianPunctuation = sal_False; + mbAddExtLeading = sal_False; + + SvxAsianConfig aAsian; + mnCharCompressType = aAsian.GetCharDistanceCompression(); + +#ifdef OSL_LITENDIAN + nStreamNumberFormat=NUMBERFORMAT_INT_LITTLEENDIAN; +#endif + bExtColorTable=bUseExtColorTable; + + if ( pPool == NULL ) + { + pItemPool=new SdrItemPool(0L, bLoadRefCounts); + // Der Outliner hat keinen eigenen Pool, deshalb den der EditEngine + SfxItemPool* pOutlPool=EditEngine::CreatePool( bLoadRefCounts ); + // OutlinerPool als SecondaryPool des SdrPool + pItemPool->SetSecondaryPool(pOutlPool); + // Merken, dass ich mir die beiden Pools selbst gemacht habe + bMyPool=TRUE; + } + pItemPool->SetDefaultMetric((SfxMapUnit)eObjUnit); + +// SJ: #95129# using static SdrEngineDefaults only if default SvxFontHeight item is not available + const SfxPoolItem* pPoolItem = pItemPool->GetPoolDefaultItem( EE_CHAR_FONTHEIGHT ); + if ( pPoolItem ) + nDefTextHgt = ((SvxFontHeightItem*)pPoolItem)->GetHeight(); + else + nDefTextHgt = SdrEngineDefaults::GetFontHeight(); + + SetTextDefaults(); + pLayerAdmin=new SdrLayerAdmin; + pLayerAdmin->SetModel(this); + ImpSetUIUnit(); + + // den DrawOutliner OnDemand erzeugen geht noch nicht, weil ich den Pool + // sonst nicht kriege (erst ab 302!) + pDrawOutliner = SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, this ); + ImpSetOutlinerDefaults(pDrawOutliner, TRUE); + + pHitTestOutliner = SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, this ); + ImpSetOutlinerDefaults(pHitTestOutliner, TRUE); + + ImpCreateTables(); +} + +SdrModel::SdrModel(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, sal_Bool bLoadRefCounts): + maMaPag(1024,32,32), + maPages(1024,32,32) +{ +#ifdef TIMELOG + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" ); +#endif + + DBG_CTOR(SdrModel,NULL); + ImpCtor(pPool,pPers,FALSE, (FASTBOOL)bLoadRefCounts); +} + +SdrModel::SdrModel(const String& rPath, SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, sal_Bool bLoadRefCounts): + maMaPag(1024,32,32), + maPages(1024,32,32), + aTablePath(rPath) +{ +#ifdef TIMELOG + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" ); +#endif + + DBG_CTOR(SdrModel,NULL); + ImpCtor(pPool,pPers,FALSE, (FASTBOOL)bLoadRefCounts); +} + +SdrModel::SdrModel(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, FASTBOOL bUseExtColorTable, sal_Bool bLoadRefCounts): + maMaPag(1024,32,32), + maPages(1024,32,32) +{ +#ifdef TIMELOG + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" ); +#endif + + DBG_CTOR(SdrModel,NULL); + ImpCtor(pPool,pPers,bUseExtColorTable, (FASTBOOL)bLoadRefCounts); +} + +SdrModel::SdrModel(const String& rPath, SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, FASTBOOL bUseExtColorTable, sal_Bool bLoadRefCounts): + maMaPag(1024,32,32), + maPages(1024,32,32), + aTablePath(rPath) +{ +#ifdef TIMELOG + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" ); +#endif + + DBG_CTOR(SdrModel,NULL); + ImpCtor(pPool,pPers,bUseExtColorTable, (FASTBOOL)bLoadRefCounts); +} + +SdrModel::SdrModel(const SdrModel& /*rSrcModel*/): + SfxBroadcaster(), + tools::WeakBase< SdrModel >(), + maMaPag(1024,32,32), + maPages(1024,32,32) +{ +#ifdef TIMELOG + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" ); +#endif + + // noch nicht implementiert + DBG_ERROR("SdrModel::CopyCtor() ist noch nicht implementiert"); +} + +SdrModel::~SdrModel() +{ +#ifdef TIMELOG + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::~SdrModel(...)" ); +#endif + + DBG_DTOR(SdrModel,NULL); + + mbInDestruction = true; + + Broadcast(SdrHint(HINT_MODELCLEARED)); + + delete mpOutlinerCache; + + ClearUndoBuffer(); +#ifdef DBG_UTIL + if(pAktUndoGroup) + { + ByteString aStr("Im Dtor des SdrModel steht noch ein offenes Undo rum: \""); + + aStr += ByteString(pAktUndoGroup->GetComment(), gsl_getSystemTextEncoding()); + aStr += '\"'; + + DBG_ERROR(aStr.GetBuffer()); + } +#endif + if (pAktUndoGroup!=NULL) + delete pAktUndoGroup; + + // #116168# + ClearModel(sal_True); + + delete pLayerAdmin; + + // Den DrawOutliner erst nach dem ItemPool loeschen, da + // der ItemPool Items des DrawOutliners referenziert !!! (<- das war mal) + // Wg. Problem bei Malte Reihenfolge wieder umgestellt. + // Loeschen des Outliners vor dem loeschen des ItemPools + delete pHitTestOutliner; + delete pDrawOutliner; + + // delete StyleSheetPool, derived classes should not do this since + // the DrawingEngine may need it in its destrctor (SB) + if( mxStyleSheetPool.is() ) + { + Reference< XComponent > xComponent( dynamic_cast< cppu::OWeakObject* >( mxStyleSheetPool.get() ), UNO_QUERY ); + if( xComponent.is() ) try + { + xComponent->dispose(); + } + catch( RuntimeException& ) + { + } + mxStyleSheetPool.clear(); + } + + if (bMyPool) + { + // Pools loeschen, falls es meine sind + SfxItemPool* pOutlPool=pItemPool->GetSecondaryPool(); + SfxItemPool::Free(pItemPool); + // Der OutlinerPool muss nach dem ItemPool plattgemacht werden, da der + // ItemPool SetItems enthaelt die ihrerseits Items des OutlinerPools + // referenzieren (Joe) + SfxItemPool::Free(pOutlPool); + } + + if( mpForbiddenCharactersTable ) + mpForbiddenCharactersTable->release(); + + // Tabellen, Listen und Paletten loeschen + if (!bExtColorTable) + delete pColorTable; + delete pDashList; + delete pLineEndList; + delete pHatchList; + delete pGradientList; + delete pBitmapList; + + if(mpNumberFormatter) + delete mpNumberFormatter; + + delete mpImpl->mpUndoFactory; + delete mpImpl; +} + +bool SdrModel::IsInDestruction() const +{ + return mbInDestruction; +} + +const SvNumberFormatter& SdrModel::GetNumberFormatter() const +{ + if(!mpNumberFormatter) + { + // use cast here since from outside view this IS a const method + ((SdrModel*)this)->mpNumberFormatter = new SvNumberFormatter( + ::comphelper::getProcessServiceFactory(), LANGUAGE_SYSTEM); + } + + return *mpNumberFormatter; +} + +// noch nicht implementiert: +void SdrModel::operator=(const SdrModel& /*rSrcModel*/) +{ + DBG_ERROR("SdrModel::operator=() ist noch nicht implementiert"); +} + +FASTBOOL SdrModel::operator==(const SdrModel& /*rCmpModel*/) const +{ + DBG_ERROR("SdrModel::operator==() ist noch nicht implementiert"); + return FALSE; +} + +void SdrModel::SetSwapGraphics( FASTBOOL bSwap ) +{ + bSwapGraphics = bSwap; +} + +FASTBOOL SdrModel::IsReadOnly() const +{ + return bReadOnly; +} + +void SdrModel::SetReadOnly(FASTBOOL bYes) +{ + bReadOnly=bYes; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrModel::SetMaxUndoActionCount(ULONG nAnz) +{ + if (nAnz<1) nAnz=1; + nMaxUndoCount=nAnz; + if (pUndoStack!=NULL) { + while (pUndoStack->Count()>nMaxUndoCount) { + delete (SfxUndoAction*) pUndoStack->Remove(pUndoStack->Count()); + } + } +} + +void SdrModel::ClearUndoBuffer() +{ + if (pUndoStack!=NULL) { + while (pUndoStack->Count()!=0) { + delete (SfxUndoAction*) pUndoStack->Remove(pUndoStack->Count()-1); + } + delete pUndoStack; + pUndoStack=NULL; + } + if (pRedoStack!=NULL) { + while (pRedoStack->Count()!=0) { + delete (SfxUndoAction*) pRedoStack->Remove(pRedoStack->Count()-1); + } + delete pRedoStack; + pRedoStack=NULL; + } +} + +FASTBOOL SdrModel::Undo() +{ + FASTBOOL bRet=FALSE; + if( mpImpl->mpUndoManager ) + { + DBG_ERROR("svx::SdrModel::Undo(), method not supported with application undo manager!"); + } + else + { + SfxUndoAction* pDo=(SfxUndoAction*)GetUndoAction(0); + if(pDo!=NULL) + { + const bool bWasUndoEnabled = mbUndoEnabled; + mbUndoEnabled = false; + pDo->Undo(); + if(pRedoStack==NULL) + pRedoStack=new Container(1024,16,16); + pRedoStack->Insert(pUndoStack->Remove((ULONG)0),(ULONG)0); + mbUndoEnabled = bWasUndoEnabled; + } + } + return bRet; +} + +FASTBOOL SdrModel::Redo() +{ + FASTBOOL bRet=FALSE; + if( mpImpl->mpUndoManager ) + { + DBG_ERROR("svx::SdrModel::Redo(), method not supported with application undo manager!"); + } + else + { + SfxUndoAction* pDo=(SfxUndoAction*)GetRedoAction(0); + if(pDo!=NULL) + { + const bool bWasUndoEnabled = mbUndoEnabled; + mbUndoEnabled = false; + pDo->Redo(); + if(pUndoStack==NULL) + pUndoStack=new Container(1024,16,16); + pUndoStack->Insert(pRedoStack->Remove((ULONG)0),(ULONG)0); + mbUndoEnabled = bWasUndoEnabled; + } + } + return bRet; +} + +FASTBOOL SdrModel::Repeat(SfxRepeatTarget& rView) +{ + FASTBOOL bRet=FALSE; + if( mpImpl->mpUndoManager ) + { + DBG_ERROR("svx::SdrModel::Redo(), method not supported with application undo manager!"); + } + else + { + SfxUndoAction* pDo=(SfxUndoAction*)GetUndoAction(0); + if(pDo!=NULL) + { + if(pDo->CanRepeat(rView)) + { + pDo->Repeat(rView); + bRet=TRUE; + } + } + } + return bRet; +} + +void SdrModel::ImpPostUndoAction(SdrUndoAction* pUndo) +{ + DBG_ASSERT( mpImpl->mpUndoManager == 0, "svx::SdrModel::ImpPostUndoAction(), method not supported with application undo manager!" ); + if( IsUndoEnabled() ) + { + if (aUndoLink.IsSet()) + { + aUndoLink.Call(pUndo); + } + else + { + if (pUndoStack==NULL) + pUndoStack=new Container(1024,16,16); + pUndoStack->Insert(pUndo,(ULONG)0); + while (pUndoStack->Count()>nMaxUndoCount) + { + delete (SfxUndoAction*)pUndoStack->Remove(pUndoStack->Count()-1); + } + if (pRedoStack!=NULL) + pRedoStack->Clear(); + } + } + else + { + delete pUndo; + } +} + +void SdrModel::BegUndo() +{ + if( mpImpl->mpUndoManager ) + { + const String aEmpty; + mpImpl->mpUndoManager->EnterListAction(aEmpty,aEmpty); + nUndoLevel++; + } + else if( IsUndoEnabled() ) + { + if(pAktUndoGroup==NULL) + { + pAktUndoGroup = new SdrUndoGroup(*this); + nUndoLevel=1; + } + else + { + nUndoLevel++; + } + } +} + +void SdrModel::BegUndo(const XubString& rComment) +{ + if( mpImpl->mpUndoManager ) + { + const String aEmpty; + mpImpl->mpUndoManager->EnterListAction( rComment, aEmpty ); + nUndoLevel++; + } + else if( IsUndoEnabled() ) + { + BegUndo(); + if (nUndoLevel==1) + { + pAktUndoGroup->SetComment(rComment); + } + } +} + +void SdrModel::BegUndo(const XubString& rComment, const XubString& rObjDescr, SdrRepeatFunc eFunc) +{ + if( mpImpl->mpUndoManager ) + { + String aComment(rComment); + if( aComment.Len() && rObjDescr.Len() ) + { + String aSearchString(RTL_CONSTASCII_USTRINGPARAM("%1")); + aComment.SearchAndReplace(aSearchString, rObjDescr); + } + const String aEmpty; + mpImpl->mpUndoManager->EnterListAction( aComment,aEmpty ); + nUndoLevel++; + } + else if( IsUndoEnabled() ) + { + BegUndo(); + if (nUndoLevel==1) + { + pAktUndoGroup->SetComment(rComment); + pAktUndoGroup->SetObjDescription(rObjDescr); + pAktUndoGroup->SetRepeatFunction(eFunc); + } + } +} + +void SdrModel::BegUndo(SdrUndoGroup* pUndoGrp) +{ + if( mpImpl->mpUndoManager ) + { + DBG_ERROR("svx::SdrModel::BegUndo(), method not supported with application undo manager!" ); + nUndoLevel++; + } + else if( IsUndoEnabled() ) + { + if (pAktUndoGroup==NULL) + { + pAktUndoGroup=pUndoGrp; + nUndoLevel=1; + } + else + { + delete pUndoGrp; + nUndoLevel++; + } + } + else + { + delete pUndoGrp; + } +} + +void SdrModel::EndUndo() +{ + DBG_ASSERT(nUndoLevel!=0,"SdrModel::EndUndo(): UndoLevel is already 0!"); + if( mpImpl->mpUndoManager ) + { + if( nUndoLevel ) + { + nUndoLevel--; + mpImpl->mpUndoManager->LeaveListAction(); + } + } + else + { + if(pAktUndoGroup!=NULL && IsUndoEnabled()) + { + nUndoLevel--; + if(nUndoLevel==0) + { + if(pAktUndoGroup->GetActionCount()!=0) + { + SdrUndoAction* pUndo=pAktUndoGroup; + pAktUndoGroup=NULL; + ImpPostUndoAction(pUndo); + } + else + { + // was empty + delete pAktUndoGroup; + pAktUndoGroup=NULL; + } + } + } + } +} + +void SdrModel::SetUndoComment(const XubString& rComment) +{ + DBG_ASSERT(nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is on level 0!"); + + if( mpImpl->mpUndoManager ) + { + DBG_ERROR("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" ); + } + else if( IsUndoEnabled() ) + { + if(nUndoLevel==1) + { + pAktUndoGroup->SetComment(rComment); + } + } +} + +void SdrModel::SetUndoComment(const XubString& rComment, const XubString& rObjDescr) +{ + DBG_ASSERT(nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is 0!"); + if( mpImpl->mpUndoManager ) + { + DBG_ERROR("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" ); + } + else + { + if (nUndoLevel==1) + { + pAktUndoGroup->SetComment(rComment); + pAktUndoGroup->SetObjDescription(rObjDescr); + } + } +} + +void SdrModel::AddUndo(SdrUndoAction* pUndo) +{ + if( mpImpl->mpUndoManager ) + { + mpImpl->mpUndoManager->AddUndoAction( pUndo ); + } + else if( !IsUndoEnabled() ) + { + delete pUndo; + } + else + { + if (pAktUndoGroup!=NULL) + { + pAktUndoGroup->AddAction(pUndo); + } + else + { + ImpPostUndoAction(pUndo); + } + } +} + +void SdrModel::EnableUndo( bool bEnable ) +{ + if( mpImpl->mpUndoManager ) + { + mpImpl->mpUndoManager->EnableUndo( bEnable ); + } + else + { + mbUndoEnabled = bEnable; + } +} + +bool SdrModel::IsUndoEnabled() const +{ + if( mpImpl->mpUndoManager ) + { + return mpImpl->mpUndoManager->IsUndoEnabled(); + } + else + { + return mbUndoEnabled; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrModel::ImpCreateTables() +{ + // der Writer hat seinen eigenen ColorTable + if (!bExtColorTable) pColorTable=new XColorTable(aTablePath,(XOutdevItemPool*)pItemPool); + pDashList =new XDashList (aTablePath,(XOutdevItemPool*)pItemPool); + pLineEndList =new XLineEndList (aTablePath,(XOutdevItemPool*)pItemPool); + pHatchList =new XHatchList (aTablePath,(XOutdevItemPool*)pItemPool); + pGradientList=new XGradientList(aTablePath,(XOutdevItemPool*)pItemPool); + pBitmapList =new XBitmapList (aTablePath,(XOutdevItemPool*)pItemPool); +} + +// #116168# +void SdrModel::ClearModel(sal_Bool bCalledFromDestructor) +{ + if(bCalledFromDestructor) + { + mbInDestruction = true; + } + + sal_Int32 i; + // delete all drawing pages + sal_Int32 nAnz=GetPageCount(); + for (i=nAnz-1; i>=0; i--) + { + DeletePage( (USHORT)i ); + } + maPages.Clear(); + // #109538# + PageListChanged(); + + // delete all Masterpages + nAnz=GetMasterPageCount(); + for(i=nAnz-1; i>=0; i--) + { + DeleteMasterPage( (USHORT)i ); + } + maMaPag.Clear(); + // #109538# + MasterPageListChanged(); + + pLayerAdmin->ClearLayer(); +} + +SdrModel* SdrModel::AllocModel() const +{ + SdrModel* pModel=new SdrModel; + pModel->SetScaleUnit(eObjUnit,aObjUnit); + return pModel; +} + +SdrPage* SdrModel::AllocPage(FASTBOOL bMasterPage) +{ + return new SdrPage(*this,bMasterPage); +} + +void SdrModel::SetTextDefaults() const +{ + SetTextDefaults( pItemPool, nDefTextHgt ); +} + +void ImpGetDefaultFontsLanguage( SvxFontItem& rLatin, SvxFontItem& rAsian, SvxFontItem& rComplex) +{ + const USHORT nItemCnt = 3; + static struct { + USHORT nFntType, nLanguage; + } aOutTypeArr[ nItemCnt ] = { + { DEFAULTFONT_LATIN_TEXT, LANGUAGE_ENGLISH_US }, + { DEFAULTFONT_CJK_TEXT, LANGUAGE_ENGLISH_US }, + { DEFAULTFONT_CTL_TEXT, LANGUAGE_ARABIC_SAUDI_ARABIA } + }; + SvxFontItem* aItemArr[ nItemCnt ] = { &rLatin, &rAsian, &rComplex }; + + for( USHORT n = 0; n < nItemCnt; ++n ) + { + Font aFnt( OutputDevice::GetDefaultFont( + aOutTypeArr[ n ].nFntType, aOutTypeArr[ n ].nLanguage, + DEFAULTFONT_FLAGS_ONLYONE, 0 )); + SvxFontItem* pI = aItemArr[ n ]; + pI->GetFamily() = aFnt.GetFamily(); + pI->GetFamilyName() = aFnt.GetName(); + pI->GetStyleName().Erase(); + pI->GetPitch() = aFnt.GetPitch(); + pI->GetCharSet() = aFnt.GetCharSet(); + } +} + +void SdrModel::SetTextDefaults( SfxItemPool* pItemPool, ULONG nDefTextHgt ) +{ + // #95114# set application-language specific dynamic pool language defaults + SvxFontItem aSvxFontItem( EE_CHAR_FONTINFO) ; + SvxFontItem aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK); + SvxFontItem aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL); + sal_uInt16 nLanguage(Application::GetSettings().GetLanguage()); + + // get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default + Font aFont(OutputDevice::GetDefaultFont(DEFAULTFONT_LATIN_TEXT, nLanguage, DEFAULTFONT_FLAGS_ONLYONE, 0)); + aSvxFontItem.GetFamily() = aFont.GetFamily(); + aSvxFontItem.GetFamilyName() = aFont.GetName(); + aSvxFontItem.GetStyleName().Erase(); + aSvxFontItem.GetPitch() = aFont.GetPitch(); + aSvxFontItem.GetCharSet() = aFont.GetCharSet(); + pItemPool->SetPoolDefaultItem(aSvxFontItem); + + // get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default + Font aFontCJK(OutputDevice::GetDefaultFont(DEFAULTFONT_CJK_TEXT, nLanguage, DEFAULTFONT_FLAGS_ONLYONE, 0)); + aSvxFontItemCJK.GetFamily() = aFontCJK.GetFamily(); + aSvxFontItemCJK.GetFamilyName() = aFontCJK.GetName(); + aSvxFontItemCJK.GetStyleName().Erase(); + aSvxFontItemCJK.GetPitch() = aFontCJK.GetPitch(); + aSvxFontItemCJK.GetCharSet() = aFontCJK.GetCharSet(); + pItemPool->SetPoolDefaultItem(aSvxFontItemCJK); + + // get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default + Font aFontCTL(OutputDevice::GetDefaultFont(DEFAULTFONT_CTL_TEXT, nLanguage, DEFAULTFONT_FLAGS_ONLYONE, 0)); + aSvxFontItemCTL.GetFamily() = aFontCTL.GetFamily(); + aSvxFontItemCTL.GetFamilyName() = aFontCTL.GetName(); + aSvxFontItemCTL.GetStyleName().Erase(); + aSvxFontItemCTL.GetPitch() = aFontCTL.GetPitch(); + aSvxFontItemCTL.GetCharSet() = aFontCTL.GetCharSet(); + pItemPool->SetPoolDefaultItem(aSvxFontItemCTL); + + // set dynamic FontHeight defaults + pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT ) ); + pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + + // set FontColor defaults + pItemPool->SetPoolDefaultItem( SvxColorItem(SdrEngineDefaults::GetFontColor(), EE_CHAR_COLOR) ); +} + +SdrOutliner& SdrModel::GetDrawOutliner(const SdrTextObj* pObj) const +{ + pDrawOutliner->SetTextObj(pObj); + return *pDrawOutliner; +} + +boost::shared_ptr< SdrOutliner > SdrModel::CreateDrawOutliner(const SdrTextObj* pObj) +{ + boost::shared_ptr< SdrOutliner > xDrawOutliner( SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, this ) ); + ImpSetOutlinerDefaults(xDrawOutliner.get(), TRUE); + xDrawOutliner->SetTextObj(pObj); + return xDrawOutliner; +} + +const SdrTextObj* SdrModel::GetFormattingTextObj() const +{ + if (pDrawOutliner!=NULL) { + return pDrawOutliner->GetTextObj(); + } + return NULL; +} + +void SdrModel::ImpSetOutlinerDefaults( SdrOutliner* pOutliner, BOOL bInit ) +{ + /************************************************************************** + * Initialisierung der Outliner fuer Textausgabe und HitTest + **************************************************************************/ + if( bInit ) + { + pOutliner->EraseVirtualDevice(); + pOutliner->SetUpdateMode(FALSE); + pOutliner->SetEditTextObjectPool(pItemPool); + pOutliner->SetDefTab(nDefaultTabulator); + } + + pOutliner->SetRefDevice(GetRefDevice()); + pOutliner->SetForbiddenCharsTable(GetForbiddenCharsTable()); + pOutliner->SetAsianCompressionMode( mnCharCompressType ); + pOutliner->SetKernAsianPunctuation( IsKernAsianPunctuation() ); + pOutliner->SetAddExtLeading( IsAddExtLeading() ); + + if ( !GetRefDevice() ) + { + MapMode aMapMode(eObjUnit, Point(0,0), aObjUnit, aObjUnit); + pOutliner->SetRefMapMode(aMapMode); + } +} + +void SdrModel::SetRefDevice(OutputDevice* pDev) +{ + pRefOutDev=pDev; + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); + RefDeviceChanged(); +} + +void SdrModel::ImpReformatAllTextObjects() +{ + if( isLocked() ) + return; + + USHORT nAnz=GetMasterPageCount(); + USHORT nNum; + for (nNum=0; nNum<nAnz; nNum++) { + GetMasterPage(nNum)->ReformatAllTextObjects(); + } + nAnz=GetPageCount(); + for (nNum=0; nNum<nAnz; nNum++) { + GetPage(nNum)->ReformatAllTextObjects(); + } +} + +/** #103122# + steps over all available pages and sends notify messages to + all edge objects that are connected to other objects so that + they may reposition itselfs +*/ +void SdrModel::ImpReformatAllEdgeObjects() +{ + if( isLocked() ) + return; + + sal_uInt16 nAnz=GetMasterPageCount(); + sal_uInt16 nNum; + for (nNum=0; nNum<nAnz; nNum++) + { + GetMasterPage(nNum)->ReformatAllEdgeObjects(); + } + nAnz=GetPageCount(); + for (nNum=0; nNum<nAnz; nNum++) + { + GetPage(nNum)->ReformatAllEdgeObjects(); + } +} + +SvStream* SdrModel::GetDocumentStream(SdrDocumentStreamInfo& /*rStreamInfo*/) const +{ + return NULL; +} + +// Die Vorlagenattribute der Zeichenobjekte in harte Attribute verwandeln. +void SdrModel::BurnInStyleSheetAttributes() +{ + USHORT nAnz=GetMasterPageCount(); + USHORT nNum; + for (nNum=0; nNum<nAnz; nNum++) { + GetMasterPage(nNum)->BurnInStyleSheetAttributes(); + } + nAnz=GetPageCount(); + for (nNum=0; nNum<nAnz; nNum++) { + GetPage(nNum)->BurnInStyleSheetAttributes(); + } +} + +void SdrModel::RefDeviceChanged() +{ + Broadcast(SdrHint(HINT_REFDEVICECHG)); + ImpReformatAllTextObjects(); +} + +void SdrModel::SetDefaultFontHeight(ULONG nVal) +{ + if (nVal!=nDefTextHgt) { + nDefTextHgt=nVal; + Broadcast(SdrHint(HINT_DEFFONTHGTCHG)); + ImpReformatAllTextObjects(); + } +} + +void SdrModel::SetDefaultTabulator(USHORT nVal) +{ + if (nDefaultTabulator!=nVal) { + nDefaultTabulator=nVal; + Outliner& rOutliner=GetDrawOutliner(); + rOutliner.SetDefTab(nVal); + Broadcast(SdrHint(HINT_DEFAULTTABCHG)); + ImpReformatAllTextObjects(); + } +} + +void SdrModel::ImpSetUIUnit() +{ + if(0 == aUIScale.GetNumerator() || 0 == aUIScale.GetDenominator()) + { + aUIScale = Fraction(1,1); + } + + // set start values + nUIUnitKomma = 0; + sal_Int64 nMul(1); + sal_Int64 nDiv(1); + + // normalize on meters resp. inch + switch (eObjUnit) + { + case MAP_100TH_MM : nUIUnitKomma+=5; break; + case MAP_10TH_MM : nUIUnitKomma+=4; break; + case MAP_MM : nUIUnitKomma+=3; break; + case MAP_CM : nUIUnitKomma+=2; break; + case MAP_1000TH_INCH: nUIUnitKomma+=3; break; + case MAP_100TH_INCH : nUIUnitKomma+=2; break; + case MAP_10TH_INCH : nUIUnitKomma+=1; break; + case MAP_INCH : nUIUnitKomma+=0; break; + case MAP_POINT : nDiv=72; break; // 1Pt = 1/72" + case MAP_TWIP : nDiv=144; nUIUnitKomma++; break; // 1Twip = 1/1440" + case MAP_PIXEL : break; + case MAP_SYSFONT : break; + case MAP_APPFONT : break; + case MAP_RELATIVE : break; + default: break; + } // switch + + // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm + // 1 furlong = 10 chains = 7.920" = 201.168,0mm + // 1 chain = 4 poles = 792" = 20.116,8mm + // 1 pole = 5 1/2 yd = 198" = 5.029,2mm + // 1 yd = 3 ft = 36" = 914,4mm + // 1 ft = 12 " = 1" = 304,8mm + switch (eUIUnit) + { + case FUNIT_NONE : break; + // Metrisch + case FUNIT_100TH_MM: nUIUnitKomma-=5; break; + case FUNIT_MM : nUIUnitKomma-=3; break; + case FUNIT_CM : nUIUnitKomma-=2; break; + case FUNIT_M : nUIUnitKomma+=0; break; + case FUNIT_KM : nUIUnitKomma+=3; break; + // Inch + case FUNIT_TWIP : nMul=144; nUIUnitKomma--; break; // 1Twip = 1/1440" + case FUNIT_POINT : nMul=72; break; // 1Pt = 1/72" + case FUNIT_PICA : nMul=6; break; // 1Pica = 1/6" ? + case FUNIT_INCH : break; // 1" = 1" + case FUNIT_FOOT : nDiv*=12; break; // 1Ft = 12" + case FUNIT_MILE : nDiv*=6336; nUIUnitKomma++; break; // 1mile = 63360" + // sonstiges + case FUNIT_CUSTOM : break; + case FUNIT_PERCENT: nUIUnitKomma+=2; break; + } // switch + + // check if mapping is from metric to inch and adapt + const bool bMapInch(IsInch(eObjUnit)); + const bool bUIMetr(IsMetric(eUIUnit)); + + if (bMapInch && bUIMetr) + { + nUIUnitKomma += 4; + nMul *= 254; + } + + // check if mapping is from inch to metric and adapt + const bool bMapMetr(IsMetric(eObjUnit)); + const bool bUIInch(IsInch(eUIUnit)); + + if (bMapMetr && bUIInch) + { + nUIUnitKomma -= 4; + nDiv *= 254; + } + + // use temporary fraction for reduction (fallback to 32bit here), + // may need to be changed in the future, too + if(1 != nMul || 1 != nDiv) + { + const Fraction aTemp(static_cast< long >(nMul), static_cast< long >(nDiv)); + nMul = aTemp.GetNumerator(); + nDiv = aTemp.GetDenominator(); + } + + // #i89872# take Unit of Measurement into account + if(1 != aUIScale.GetDenominator() || 1 != aUIScale.GetNumerator()) + { + // divide by UIScale + nMul *= aUIScale.GetDenominator(); + nDiv *= aUIScale.GetNumerator(); + } + + // shorten trailing zeroes for dividend + while(0 == (nMul % 10)) + { + nUIUnitKomma--; + nMul /= 10; + } + + // shorten trailing zeroes for divisor + while(0 == (nDiv % 10)) + { + nUIUnitKomma++; + nDiv /= 10; + } + + // end preparations, set member values + aUIUnitFact = Fraction(sal_Int32(nMul), sal_Int32(nDiv)); + bUIOnlyKomma = (nMul == nDiv); + TakeUnitStr(eUIUnit, aUIUnitStr); +} + +void SdrModel::SetScaleUnit(MapUnit eMap, const Fraction& rFrac) +{ + if (eObjUnit!=eMap || aObjUnit!=rFrac) { + eObjUnit=eMap; + aObjUnit=rFrac; + pItemPool->SetDefaultMetric((SfxMapUnit)eObjUnit); + ImpSetUIUnit(); + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); + ImpReformatAllTextObjects(); // #40424# + } +} + +void SdrModel::SetScaleUnit(MapUnit eMap) +{ + if (eObjUnit!=eMap) { + eObjUnit=eMap; + pItemPool->SetDefaultMetric((SfxMapUnit)eObjUnit); + ImpSetUIUnit(); + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); + ImpReformatAllTextObjects(); // #40424# + } +} + +void SdrModel::SetScaleFraction(const Fraction& rFrac) +{ + if (aObjUnit!=rFrac) { + aObjUnit=rFrac; + ImpSetUIUnit(); + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); + ImpReformatAllTextObjects(); // #40424# + } +} + +void SdrModel::SetUIUnit(FieldUnit eUnit) +{ + if (eUIUnit!=eUnit) { + eUIUnit=eUnit; + ImpSetUIUnit(); + ImpReformatAllTextObjects(); // #40424# + } +} + +void SdrModel::SetUIScale(const Fraction& rScale) +{ + if (aUIScale!=rScale) { + aUIScale=rScale; + ImpSetUIUnit(); + ImpReformatAllTextObjects(); // #40424# + } +} + +void SdrModel::SetUIUnit(FieldUnit eUnit, const Fraction& rScale) +{ + if (eUIUnit!=eUnit || aUIScale!=rScale) { + eUIUnit=eUnit; + aUIScale=rScale; + ImpSetUIUnit(); + ImpReformatAllTextObjects(); // #40424# + } +} + +void SdrModel::TakeUnitStr(FieldUnit eUnit, XubString& rStr) +{ + switch(eUnit) + { + default: + case FUNIT_NONE : + case FUNIT_CUSTOM : + { + rStr = String(); + break; + } + case FUNIT_100TH_MM: + { + sal_Char aText[] = "/100mm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_MM : + { + sal_Char aText[] = "mm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_CM : + { + sal_Char aText[] = "cm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_M : + { + rStr = String(); + rStr += sal_Unicode('m'); + break; + } + case FUNIT_KM : + { + sal_Char aText[] = "km"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_TWIP : + { + sal_Char aText[] = "twip"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_POINT : + { + sal_Char aText[] = "pt"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_PICA : + { + sal_Char aText[] = "pica"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_INCH : + { + rStr = String(); + rStr += sal_Unicode('"'); + break; + } + case FUNIT_FOOT : + { + sal_Char aText[] = "ft"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_MILE : + { + sal_Char aText[] = "mile(s)"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_PERCENT: + { + rStr = String(); + rStr += sal_Unicode('%'); + break; + } + } +} + +void SdrModel::TakeMetricStr(long nVal, XubString& rStr, FASTBOOL bNoUnitChars, sal_Int32 nNumDigits) const +{ + // #i22167# + // change to double precision usage to not loose decimal places after comma + const bool bNegative(nVal < 0L); + SvtSysLocale aSysLoc; + const LocaleDataWrapper& rLoc(aSysLoc.GetLocaleData()); + double fLocalValue(double(nVal) * double(aUIUnitFact)); + + if(bNegative) + { + fLocalValue = -fLocalValue; + } + + if( -1 == nNumDigits ) + { + nNumDigits = rLoc.getNumDigits(); + } + + sal_Int32 nKomma(nUIUnitKomma); + + if(nKomma > nNumDigits) + { + const sal_Int32 nDiff(nKomma - nNumDigits); + const double fFactor(pow(10.0, static_cast<const int>(nDiff))); + + fLocalValue /= fFactor; + nKomma = nNumDigits; + } + else if(nKomma < nNumDigits) + { + const sal_Int32 nDiff(nNumDigits - nKomma); + const double fFactor(pow(10.0, static_cast<const int>(nDiff))); + + fLocalValue *= fFactor; + nKomma = nNumDigits; + } + + rStr = UniString::CreateFromInt32(static_cast<sal_Int32>(fLocalValue + 0.5)); + + if(nKomma < 0) + { + // Negatives Komma bedeutet: Nullen dran + sal_Int32 nAnz(-nKomma); + + for(sal_Int32 i=0; i<nAnz; i++) + rStr += sal_Unicode('0'); + + nKomma = 0; + } + + // #83257# the second condition needs to be <= since inside this loop + // also the leading zero is inserted. + if(nKomma > 0 && rStr.Len() <= nKomma) + { + // Fuer Komma evtl. vorne Nullen dran + sal_Int32 nAnz(nKomma - rStr.Len()); + + if(nAnz >= 0 && rLoc.isNumLeadingZero()) + nAnz++; + + for(sal_Int32 i=0; i<nAnz; i++) + rStr.Insert(sal_Unicode('0'), 0); + } + + sal_Unicode cDec( rLoc.getNumDecimalSep().GetChar(0) ); + + // KommaChar einfuegen + sal_Int32 nVorKomma(rStr.Len() - nKomma); + + if(nKomma > 0) + rStr.Insert(cDec, (xub_StrLen) nVorKomma); + + if(!rLoc.isNumTrailingZeros()) + { + while(rStr.Len() && rStr.GetChar(rStr.Len() - 1) == sal_Unicode('0')) + rStr.Erase(rStr.Len() - 1); + + if(rStr.Len() && rStr.GetChar(rStr.Len() - 1) == cDec) + rStr.Erase(rStr.Len() - 1); + } + + // ggf. Trennpunkte bei jedem Tausender einfuegen + if( nVorKomma > 3 ) + { + String aThoSep( rLoc.getNumThousandSep() ); + if ( aThoSep.Len() > 0 ) + { + sal_Unicode cTho( aThoSep.GetChar(0) ); + sal_Int32 i(nVorKomma - 3); + + while(i > 0) // #78311# + { + rStr.Insert(cTho, (xub_StrLen)i); + i -= 3; + } + } + } + + if(!rStr.Len()) + { + rStr = String(); + rStr += sal_Unicode('0'); + } + + if(bNegative) + { + rStr.Insert(sal_Unicode('-'), 0); + } + + if(!bNoUnitChars) + rStr += aUIUnitStr; +} + +void SdrModel::TakeWinkStr(long nWink, XubString& rStr, FASTBOOL bNoDegChar) const +{ + BOOL bNeg(nWink < 0); + + if(bNeg) + nWink = -nWink; + + rStr = UniString::CreateFromInt32(nWink); + + SvtSysLocale aSysLoc; + const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData(); + xub_StrLen nAnz(2); + + if(rLoc.isNumLeadingZero()) + nAnz++; + + while(rStr.Len() < nAnz) + rStr.Insert(sal_Unicode('0'), 0); + + rStr.Insert(rLoc.getNumDecimalSep().GetChar(0), rStr.Len() - 2); + + if(bNeg) + rStr.Insert(sal_Unicode('-'), 0); + + if(!bNoDegChar) + rStr += DEGREE_CHAR; +} + +void SdrModel::TakePercentStr(const Fraction& rVal, XubString& rStr, FASTBOOL bNoPercentChar) const +{ + INT32 nMul(rVal.GetNumerator()); + INT32 nDiv(rVal.GetDenominator()); + BOOL bNeg(nMul < 0); + + if(nDiv < 0) + bNeg = !bNeg; + + if(nMul < 0) + nMul = -nMul; + + if(nDiv < 0) + nDiv = -nDiv; + + nMul *= 100; + nMul += nDiv/2; + nMul /= nDiv; + + rStr = UniString::CreateFromInt32(nMul); + + if(bNeg) + rStr.Insert(sal_Unicode('-'), 0); + + if(!bNoPercentChar) + rStr += sal_Unicode('%'); +} + +void SdrModel::SetChanged(sal_Bool bFlg) +{ + mbChanged = bFlg; +} + +void SdrModel::RecalcPageNums(FASTBOOL bMaster) +{ + Container& rPL=*(bMaster ? &maMaPag : &maPages); + USHORT nAnz=USHORT(rPL.Count()); + USHORT i; + for (i=0; i<nAnz; i++) { + SdrPage* pPg=(SdrPage*)(rPL.GetObject(i)); + pPg->SetPageNum(i); + } + if (bMaster) bMPgNumsDirty=FALSE; + else bPagNumsDirty=FALSE; +} + +void SdrModel::InsertPage(SdrPage* pPage, USHORT nPos) +{ + USHORT nAnz=GetPageCount(); + if (nPos>nAnz) nPos=nAnz; + maPages.Insert(pPage,nPos); + // #109538# + PageListChanged(); + pPage->SetInserted(TRUE); + pPage->SetPageNum(nPos); + pPage->SetModel(this); + if (nPos<nAnz) bPagNumsDirty=TRUE; + SetChanged(); + SdrHint aHint(HINT_PAGEORDERCHG); + aHint.SetPage(pPage); + Broadcast(aHint); +} + +void SdrModel::DeletePage(USHORT nPgNum) +{ + SdrPage* pPg=RemovePage(nPgNum); + delete pPg; +} + +SdrPage* SdrModel::RemovePage(USHORT nPgNum) +{ + SdrPage* pPg=(SdrPage*)maPages.Remove(nPgNum); + // #109538# + PageListChanged(); + if (pPg!=NULL) { + pPg->SetInserted(FALSE); + } + bPagNumsDirty=TRUE; + SetChanged(); + SdrHint aHint(HINT_PAGEORDERCHG); + aHint.SetPage(pPg); + Broadcast(aHint); + return pPg; +} + +void SdrModel::MovePage(USHORT nPgNum, USHORT nNewPos) +{ + SdrPage* pPg=(SdrPage*)maPages.Remove(nPgNum); + // #109538# + PageListChanged(); + if (pPg!=NULL) { + pPg->SetInserted(FALSE); + InsertPage(pPg,nNewPos); + } +} + +void SdrModel::InsertMasterPage(SdrPage* pPage, USHORT nPos) +{ + USHORT nAnz=GetMasterPageCount(); + if (nPos>nAnz) nPos=nAnz; + maMaPag.Insert(pPage,nPos); + // #109538# + MasterPageListChanged(); + pPage->SetInserted(TRUE); + pPage->SetPageNum(nPos); + pPage->SetModel(this); + if (nPos<nAnz) { + bMPgNumsDirty=TRUE; + } + SetChanged(); + SdrHint aHint(HINT_PAGEORDERCHG); + aHint.SetPage(pPage); + Broadcast(aHint); +} + +void SdrModel::DeleteMasterPage(USHORT nPgNum) +{ + SdrPage* pPg=RemoveMasterPage(nPgNum); + if (pPg!=NULL) delete pPg; +} + +SdrPage* SdrModel::RemoveMasterPage(USHORT nPgNum) +{ + SdrPage* pRetPg=(SdrPage*)maMaPag.Remove(nPgNum); + // #109538# + MasterPageListChanged(); + + if(pRetPg) + { + // Nun die Verweise der normalen Zeichenseiten auf die entfernte MasterPage loeschen + sal_uInt16 nPageAnz(GetPageCount()); + + for(sal_uInt16 np(0); np < nPageAnz; np++) + { + GetPage(np)->TRG_ImpMasterPageRemoved(*pRetPg); + } + + pRetPg->SetInserted(FALSE); + } + + bMPgNumsDirty=TRUE; + SetChanged(); + SdrHint aHint(HINT_PAGEORDERCHG); + aHint.SetPage(pRetPg); + Broadcast(aHint); + return pRetPg; +} + +void SdrModel::MoveMasterPage(USHORT nPgNum, USHORT nNewPos) +{ + SdrPage* pPg=(SdrPage*)maMaPag.Remove(nPgNum); + // #109538# + MasterPageListChanged(); + if (pPg!=NULL) { + pPg->SetInserted(FALSE); + maMaPag.Insert(pPg,nNewPos); + // #109538# + MasterPageListChanged(); + } + bMPgNumsDirty=TRUE; + SetChanged(); + SdrHint aHint(HINT_PAGEORDERCHG); + aHint.SetPage(pPg); + Broadcast(aHint); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrModel::CheckConsistence() const +{ + FASTBOOL bRet=TRUE; +#ifdef DBG_UTIL + DBG_CHKTHIS(SdrModel,NULL); +#endif + return bRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// #48289# +void SdrModel::CopyPages(USHORT nFirstPageNum, USHORT nLastPageNum, + USHORT nDestPos, + FASTBOOL bUndo, FASTBOOL bMoveNoCopy) +{ + if( bUndo && !IsUndoEnabled() ) + bUndo = false; + + if( bUndo ) + BegUndo(ImpGetResStr(STR_UndoMergeModel)); + + USHORT nPageAnz=GetPageCount(); + USHORT nMaxPage=nPageAnz; + + if (nMaxPage!=0) + nMaxPage--; + if (nFirstPageNum>nMaxPage) + nFirstPageNum=nMaxPage; + if (nLastPageNum>nMaxPage) + nLastPageNum =nMaxPage; + FASTBOOL bReverse=nLastPageNum<nFirstPageNum; + if (nDestPos>nPageAnz) + nDestPos=nPageAnz; + + // Zunaechst die Zeiger der betroffenen Seiten in einem Array sichern + USHORT nPageNum=nFirstPageNum; + USHORT nCopyAnz=((!bReverse)?(nLastPageNum-nFirstPageNum):(nFirstPageNum-nLastPageNum))+1; + SdrPage** pPagePtrs=new SdrPage*[nCopyAnz]; + USHORT nCopyNum; + for(nCopyNum=0; nCopyNum<nCopyAnz; nCopyNum++) + { + pPagePtrs[nCopyNum]=GetPage(nPageNum); + if (bReverse) + nPageNum--; + else + nPageNum++; + } + + // Jetzt die Seiten kopieren + USHORT nDestNum=nDestPos; + for (nCopyNum=0; nCopyNum<nCopyAnz; nCopyNum++) + { + SdrPage* pPg=pPagePtrs[nCopyNum]; + USHORT nPageNum2=pPg->GetPageNum(); + if (!bMoveNoCopy) + { + const SdrPage* pPg1=GetPage(nPageNum2); + pPg=pPg1->Clone(); + InsertPage(pPg,nDestNum); + if (bUndo) + AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg)); + nDestNum++; + } + else + { + // Move ist nicht getestet! + if (nDestNum>nPageNum2) + nDestNum--; + + if(bUndo) + AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*GetPage(nPageNum2),nPageNum2,nDestNum)); + + pPg=RemovePage(nPageNum2); + InsertPage(pPg,nDestNum); + nDestNum++; + } + + if(bReverse) + nPageNum2--; + else + nPageNum2++; + } + + delete[] pPagePtrs; + if(bUndo) + EndUndo(); +} + +void SdrModel::Merge(SdrModel& rSourceModel, + USHORT nFirstPageNum, USHORT nLastPageNum, + USHORT nDestPos, + FASTBOOL bMergeMasterPages, FASTBOOL bAllMasterPages, + FASTBOOL bUndo, FASTBOOL bTreadSourceAsConst) +{ + if (&rSourceModel==this) + { // #48289# + CopyPages(nFirstPageNum,nLastPageNum,nDestPos,bUndo,!bTreadSourceAsConst); + return; + } + + if( bUndo && !IsUndoEnabled() ) + bUndo = false; + + if (bUndo) + BegUndo(ImpGetResStr(STR_UndoMergeModel)); + + USHORT nSrcPageAnz=rSourceModel.GetPageCount(); + USHORT nSrcMasterPageAnz=rSourceModel.GetMasterPageCount(); + USHORT nDstMasterPageAnz=GetMasterPageCount(); + FASTBOOL bInsPages=(nFirstPageNum<nSrcPageAnz || nLastPageNum<nSrcPageAnz); + USHORT nMaxSrcPage=nSrcPageAnz; if (nMaxSrcPage!=0) nMaxSrcPage--; + if (nFirstPageNum>nMaxSrcPage) nFirstPageNum=nMaxSrcPage; + if (nLastPageNum>nMaxSrcPage) nLastPageNum =nMaxSrcPage; + FASTBOOL bReverse=nLastPageNum<nFirstPageNum; + + USHORT* pMasterMap=NULL; + FASTBOOL* pMasterNeed=NULL; + USHORT nMasterNeed=0; + if (bMergeMasterPages && nSrcMasterPageAnz!=0) { + // Feststellen, welche MasterPages aus rSrcModel benoetigt werden + pMasterMap=new USHORT[nSrcMasterPageAnz]; + pMasterNeed=new FASTBOOL[nSrcMasterPageAnz]; + memset(pMasterMap,0xFF,nSrcMasterPageAnz*sizeof(USHORT)); + if (bAllMasterPages) { + memset(pMasterNeed,TRUE,nSrcMasterPageAnz*sizeof(FASTBOOL)); + } else { + memset(pMasterNeed,FALSE,nSrcMasterPageAnz*sizeof(FASTBOOL)); + USHORT nAnf= bReverse ? nLastPageNum : nFirstPageNum; + USHORT nEnd= bReverse ? nFirstPageNum : nLastPageNum; + for (USHORT i=nAnf; i<=nEnd; i++) { + const SdrPage* pPg=rSourceModel.GetPage(i); + if(pPg->TRG_HasMasterPage()) + { + SdrPage& rMasterPage = pPg->TRG_GetMasterPage(); + sal_uInt16 nMPgNum(rMasterPage.GetPageNum()); + + if(nMPgNum < nSrcMasterPageAnz) + { + pMasterNeed[nMPgNum] = TRUE; + } + } + } + } + // Nun das Mapping der MasterPages bestimmen + USHORT nAktMaPagNum=nDstMasterPageAnz; + for (USHORT i=0; i<nSrcMasterPageAnz; i++) { + if (pMasterNeed[i]) { + pMasterMap[i]=nAktMaPagNum; + nAktMaPagNum++; + nMasterNeed++; + } + } + } + + // rueberholen der Masterpages + if (pMasterMap!=NULL && pMasterNeed!=NULL && nMasterNeed!=0) { + for (USHORT i=nSrcMasterPageAnz; i>0;) { + i--; + if (pMasterNeed[i]) { + SdrPage* pPg=NULL; + if (bTreadSourceAsConst) { + const SdrPage* pPg1=rSourceModel.GetMasterPage(i); + pPg=pPg1->Clone(); + } else { + pPg=rSourceModel.RemoveMasterPage(i); + } + if (pPg!=NULL) { + // und alle ans einstige Ende des DstModel reinschieben. + // nicht InsertMasterPage() verwenden da die Sache + // inkonsistent ist bis alle drin sind + maMaPag.Insert(pPg,nDstMasterPageAnz); + // #109538# + MasterPageListChanged(); + pPg->SetInserted(TRUE); + pPg->SetModel(this); + bMPgNumsDirty=TRUE; + if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg)); + } else { + DBG_ERROR("SdrModel::Merge(): MasterPage im SourceModel nicht gefunden"); + } + } + } + } + + // rueberholen der Zeichenseiten + if (bInsPages) { + USHORT nSourcePos=nFirstPageNum; + USHORT nMergeCount=USHORT(Abs((long)((long)nFirstPageNum-nLastPageNum))+1); + if (nDestPos>GetPageCount()) nDestPos=GetPageCount(); + while (nMergeCount>0) { + SdrPage* pPg=NULL; + if (bTreadSourceAsConst) { + const SdrPage* pPg1=rSourceModel.GetPage(nSourcePos); + pPg=pPg1->Clone(); + } else { + pPg=rSourceModel.RemovePage(nSourcePos); + } + if (pPg!=NULL) { + InsertPage(pPg,nDestPos); + if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg)); + // und nun zu den MasterPageDescriptoren + + if(pPg->TRG_HasMasterPage()) + { + SdrPage& rMasterPage = pPg->TRG_GetMasterPage(); + sal_uInt16 nMaPgNum(rMasterPage.GetPageNum()); + + if (bMergeMasterPages) + { + sal_uInt16 nNeuNum(0xFFFF); + + if(pMasterMap) + { + nNeuNum = pMasterMap[nMaPgNum]; + } + + if(nNeuNum != 0xFFFF) + { + if(bUndo) + { + AddUndo(GetSdrUndoFactory().CreateUndoPageChangeMasterPage(*pPg)); + } + + pPg->TRG_SetMasterPage(*GetMasterPage(nNeuNum)); + } + DBG_ASSERT(nNeuNum!=0xFFFF,"SdrModel::Merge(): Irgendwas ist krumm beim Mappen der MasterPages"); + } else { + if (nMaPgNum>=nDstMasterPageAnz) { + // Aha, die ist ausserbalb des urspruenglichen Bereichs der Masterpages des DstModel + pPg->TRG_ClearMasterPage(); + } + } + } + + } else { + DBG_ERROR("SdrModel::Merge(): Zeichenseite im SourceModel nicht gefunden"); + } + nDestPos++; + if (bReverse) nSourcePos--; + else if (bTreadSourceAsConst) nSourcePos++; + nMergeCount--; + } + } + + delete [] pMasterMap; + delete [] pMasterNeed; + + bMPgNumsDirty=TRUE; + bPagNumsDirty=TRUE; + + SetChanged(); + // Fehlt: Mergen und Mapping der Layer + // an den Objekten sowie an den MasterPageDescriptoren + if (bUndo) EndUndo(); +} + +void SdrModel::SetStarDrawPreviewMode(BOOL bPreview) +{ + if (!bPreview && bStarDrawPreviewMode && GetPageCount()) + { + // Das Zuruecksetzen ist nicht erlaubt, da das Model ev. nicht vollstaendig geladen wurde + DBG_ASSERT(FALSE,"SdrModel::SetStarDrawPreviewMode(): Zuruecksetzen nicht erlaubt, da Model ev. nicht vollstaendig"); + } + else + { + bStarDrawPreviewMode = bPreview; + } +} + +uno::Reference< uno::XInterface > SdrModel::getUnoModel() +{ + if( !mxUnoModel.is() ) + mxUnoModel = createUnoModel(); + + return mxUnoModel; +} + +void SdrModel::setUnoModel( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xModel ) +{ + mxUnoModel = xModel; +} + +uno::Reference< uno::XInterface > SdrModel::createUnoModel() +{ + DBG_ERROR( "SdrModel::createUnoModel() - base implementation should not be called!" ); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xInt; + return xInt; +} + +void SdrModel::setLock( BOOL bLock ) +{ + if( mbModelLocked != bLock ) + { + if( sal_False == bLock ) + { + // ReformatAllTextObjects(); #103122# due to a typo in the above if, this code was never + // executed, so I remove it until we discover that we need it here + ImpReformatAllEdgeObjects(); // #103122# + } + mbModelLocked = bLock; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrModel::MigrateItemSet( const SfxItemSet* pSourceSet, SfxItemSet* pDestSet, SdrModel* pNewModel ) +{ + if( pSourceSet && pDestSet && (pSourceSet != pDestSet ) ) + { + if( pNewModel == NULL ) + pNewModel = this; + + SfxWhichIter aWhichIter(*pSourceSet); + sal_uInt16 nWhich(aWhichIter.FirstWhich()); + const SfxPoolItem *pPoolItem; + + while(nWhich) + { + if(SFX_ITEM_SET == pSourceSet->GetItemState(nWhich, FALSE, &pPoolItem)) + { + const SfxPoolItem* pItem = pPoolItem; + + switch( nWhich ) + { + case XATTR_FILLBITMAP: + pItem = ((XFillBitmapItem*)pItem)->checkForUniqueItem( pNewModel ); + break; + case XATTR_LINEDASH: + pItem = ((XLineDashItem*)pItem)->checkForUniqueItem( pNewModel ); + break; + case XATTR_LINESTART: + pItem = ((XLineStartItem*)pItem)->checkForUniqueItem( pNewModel ); + break; + case XATTR_LINEEND: + pItem = ((XLineEndItem*)pItem)->checkForUniqueItem( pNewModel ); + break; + case XATTR_FILLGRADIENT: + pItem = ((XFillGradientItem*)pItem)->checkForUniqueItem( pNewModel ); + break; + case XATTR_FILLFLOATTRANSPARENCE: + // #85953# allow all kinds of XFillFloatTransparenceItem to be set + pItem = ((XFillFloatTransparenceItem*)pItem)->checkForUniqueItem( pNewModel ); + break; + case XATTR_FILLHATCH: + pItem = ((XFillHatchItem*)pItem)->checkForUniqueItem( pNewModel ); + break; + } + + // set item + if( pItem ) + { + pDestSet->Put(*pItem); + + // delete item if it was a generated one + if( pItem != pPoolItem) + delete (SfxPoolItem*)pItem; + } + } + nWhich = aWhichIter.NextWhich(); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrModel::SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars ) +{ + if( mpForbiddenCharactersTable ) + mpForbiddenCharactersTable->release(); + + mpForbiddenCharactersTable = xForbiddenChars.getBodyPtr(); + + if( mpForbiddenCharactersTable ) + mpForbiddenCharactersTable->acquire(); + + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); +} + +vos::ORef<SvxForbiddenCharactersTable> SdrModel::GetForbiddenCharsTable() const +{ + return mpForbiddenCharactersTable; +} + +void SdrModel::SetCharCompressType( UINT16 nType ) +{ + if( nType != mnCharCompressType ) + { + mnCharCompressType = nType; + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); + } +} + +void SdrModel::SetKernAsianPunctuation( sal_Bool bEnabled ) +{ + if( mbKernAsianPunctuation != bEnabled ) + { + mbKernAsianPunctuation = bEnabled; + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); + } +} + +void SdrModel::SetAddExtLeading( sal_Bool bEnabled ) +{ + if( mbAddExtLeading != bEnabled ) + { + mbAddExtLeading = bEnabled; + ImpSetOutlinerDefaults( pDrawOutliner ); + ImpSetOutlinerDefaults( pHitTestOutliner ); + } +} + +void SdrModel::ReformatAllTextObjects() +{ + ImpReformatAllTextObjects(); +} + +FASTBOOL SdrModel::HasTransparentObjects( BOOL bCheckForAlphaChannel ) const +{ + FASTBOOL bRet = FALSE; + USHORT n, nCount; + + for( n = 0, nCount = GetMasterPageCount(); ( n < nCount ) && !bRet; n++ ) + if( GetMasterPage( n )->HasTransparentObjects( bCheckForAlphaChannel ) ) + bRet = TRUE; + + if( !bRet ) + { + for( n = 0, nCount = GetPageCount(); ( n < nCount ) && !bRet; n++ ) + if( GetPage( n )->HasTransparentObjects( bCheckForAlphaChannel ) ) + bRet = TRUE; + } + + return bRet; +} + +SdrOutliner* SdrModel::createOutliner( USHORT nOutlinerMode ) +{ + if( NULL == mpOutlinerCache ) + mpOutlinerCache = new SdrOutlinerCache(this); + + return mpOutlinerCache->createOutliner( nOutlinerMode ); +} + +void SdrModel::disposeOutliner( SdrOutliner* pOutliner ) +{ + if( mpOutlinerCache ) + { + mpOutlinerCache->disposeOutliner( pOutliner ); + } + else + { + delete pOutliner; + } +} + +SvxNumType SdrModel::GetPageNumType() const +{ + return SVX_ARABIC; +} + +const SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum) const +{ + DBG_ASSERT(nPgNum < maPages.Count(), "SdrModel::GetPage: Access out of range (!)"); + return (SdrPage*)(maPages.GetObject(nPgNum)); +} + +SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum) +{ + DBG_ASSERT(nPgNum < maPages.Count(), "SdrModel::GetPage: Access out of range (!)"); + return (SdrPage*)(maPages.GetObject(nPgNum)); +} + +sal_uInt16 SdrModel::GetPageCount() const +{ + return sal_uInt16(maPages.Count()); +} + +void SdrModel::PageListChanged() +{ +} + +const SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum) const +{ + DBG_ASSERT(nPgNum < maMaPag.Count(), "SdrModel::GetMasterPage: Access out of range (!)"); + return (SdrPage*)(maMaPag.GetObject(nPgNum)); +} + +SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum) +{ + DBG_ASSERT(nPgNum < maMaPag.Count(), "SdrModel::GetMasterPage: Access out of range (!)"); + return (SdrPage*)(maMaPag.GetObject(nPgNum)); +} + +sal_uInt16 SdrModel::GetMasterPageCount() const +{ + return sal_uInt16(maMaPag.Count()); +} + +void SdrModel::MasterPageListChanged() +{ +} + +void SdrModel::SetSdrUndoManager( SfxUndoManager* pUndoManager ) +{ + mpImpl->mpUndoManager = pUndoManager; +} + +SdrUndoFactory& SdrModel::GetSdrUndoFactory() const +{ + if( !mpImpl->mpUndoFactory ) + mpImpl->mpUndoFactory = new SdrUndoFactory; + return *mpImpl->mpUndoFactory; +} + +void SdrModel::SetSdrUndoFactory( SdrUndoFactory* pUndoFactory ) +{ + if( pUndoFactory && (pUndoFactory != mpImpl->mpUndoFactory) ) + { + delete mpImpl->mpUndoFactory; + mpImpl->mpUndoFactory = pUndoFactory; + } +} + +/** cl: added this for OJ to complete his reporting engine, does not work + correctly so only enable it for his model */ +bool SdrModel::IsAllowShapePropertyChangeListener() const +{ + return mpImpl && mpImpl->mbAllowShapePropertyChangeListener; +} + +void SdrModel::SetAllowShapePropertyChangeListener( bool bAllow ) +{ + if( mpImpl ) + { + mpImpl->mbAllowShapePropertyChangeListener = bAllow; + } +} + +const ::com::sun::star::uno::Sequence< sal_Int8 >& SdrModel::getUnoTunnelImplementationId() +{ + static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = 0; + if( !pSeq ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrHint,SfxHint); + +SdrHint::SdrHint() +: mpPage(0L), + mpObj(0L), + mpObjList(0L), + meHint(HINT_UNKNOWN) +{ +} + +SdrHint::SdrHint(SdrHintKind eNewHint) +: mpPage(0L), + mpObj(0L), + mpObjList(0L), + meHint(eNewHint) +{ +} + +SdrHint::SdrHint(const SdrObject& rNewObj) +: mpPage(rNewObj.GetPage()), + mpObj(&rNewObj), + mpObjList(rNewObj.GetObjList()), + meHint(HINT_OBJCHG) +{ + maRectangle = rNewObj.GetLastBoundRect(); +} + +SdrHint::SdrHint(const SdrObject& rNewObj, const Rectangle& rRect) +: mpPage(rNewObj.GetPage()), + mpObj(&rNewObj), + mpObjList(rNewObj.GetObjList()), + meHint(HINT_OBJCHG) +{ + maRectangle = rRect; +} + +void SdrHint::SetPage(const SdrPage* pNewPage) +{ + mpPage = pNewPage; +} + +void SdrHint::SetObjList(const SdrObjList* pNewOL) +{ + mpObjList = pNewOL; +} + +void SdrHint::SetObject(const SdrObject* pNewObj) +{ + mpObj = pNewObj; +} + +void SdrHint::SetKind(SdrHintKind eNewKind) +{ + meHint = eNewKind; +} + +void SdrHint::SetRect(const Rectangle& rNewRect) +{ + maRectangle = rNewRect; +} + +const SdrPage* SdrHint::GetPage() const +{ + return mpPage; +} + +const SdrObjList* SdrHint::GetObjList() const +{ + return mpObjList; +} + +const SdrObject* SdrHint::GetObject() const +{ + return mpObj; +} + +SdrHintKind SdrHint::GetKind() const +{ + return meHint; +} + +const Rectangle& SdrHint::GetRect() const +{ + return maRectangle; +} + +// eof diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx new file mode 100644 index 000000000000..fffcac00e46c --- /dev/null +++ b/svx/source/svdraw/svdmrkv.cxx @@ -0,0 +1,2176 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdmrkv.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdoedge.hxx> +#include "svdglob.hxx" +#include "svditext.hxx" +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdpage.hxx> +#include "svddrgm1.hxx" + +#ifdef DBG_UTIL +#include <svdibrow.hxx> +#endif + +#include <svx/svdoole2.hxx> +#include <svx/xgrad.hxx> +#include <svx/xflgrit.hxx> +#include "gradtrns.hxx" +#include <svx/xflftrit.hxx> +#include <svx/dialmgr.hxx> +#include "svdstr.hrc" +#include <svx/svdundo.hxx> +#include <svx/svdopath.hxx> +#include <svx/scene3d.hxx> +#include <svx/svdovirt.hxx> +#include <svx/sdr/overlay/overlayrollingrectangle.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <sdrpaintwindow.hxx> +#include <svx/sdrpagewindow.hxx> +#include <svx/sdrhittesthelper.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// predefines + +class SdrUnoControlList; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #114409#-3 Migrate Marking of Objects, Points and GluePoints + +class ImplMarkingOverlay +{ + // The OverlayObjects + ::sdr::overlay::OverlayObjectList maObjects; + + // The remembered second position in logical coodinates + basegfx::B2DPoint maSecondPosition; + + // bitfield + // A flag to remember if the action is for unmarking. + unsigned mbUnmarking : 1; + +public: + ImplMarkingOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos, sal_Bool bUnmarking = sal_False); + ~ImplMarkingOverlay(); + + void SetSecondPosition(const basegfx::B2DPoint& rNewPosition); + sal_Bool IsUnmarking() const { return mbUnmarking; } +}; + +ImplMarkingOverlay::ImplMarkingOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos, sal_Bool bUnmarking) +: maSecondPosition(rStartPos), + mbUnmarking(bUnmarking) +{ + for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); + + if(pTargetOverlay) + { + ::sdr::overlay::OverlayRollingRectangleStriped* pNew = new ::sdr::overlay::OverlayRollingRectangleStriped( + rStartPos, rStartPos, false); + pTargetOverlay->add(*pNew); + maObjects.append(*pNew); + } + } +} + +ImplMarkingOverlay::~ImplMarkingOverlay() +{ + // The OverlayObjects are cleared using the destructor of OverlayObjectList. + // That destructor calls clear() at the list which removes all objects from the + // OverlayManager and deletes them. +} + +void ImplMarkingOverlay::SetSecondPosition(const basegfx::B2DPoint& rNewPosition) +{ + if(rNewPosition != maSecondPosition) + { + // apply to OverlayObjects + for(sal_uInt32 a(0L); a < maObjects.count(); a++) + { + ::sdr::overlay::OverlayRollingRectangleStriped& rCandidate = (::sdr::overlay::OverlayRollingRectangleStriped&)maObjects.getOverlayObject(a); + rCandidate.setSecondPosition(rNewPosition); + } + + // remember new position + maSecondPosition = rNewPosition; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@ @@ @@@@ @@@@@ @@ @@ @@ @@ @@ @@@@@ @@ @@ +// @@@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ +// @@@@@@@ @@@@@@ @@@@@ @@@@ @@@@@ @@ @@@@ @@@@@@@ +// @@ @ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkView::ImpClearVars() +{ + eDragMode=SDRDRAG_MOVE; + //HMHbHdlShown=FALSE; + bRefHdlShownOnly=FALSE; + eEditMode=SDREDITMODE_EDIT; + eEditMode0=SDREDITMODE_EDIT; + bDesignMode=FALSE; + pMarkedObj=NULL; + pMarkedPV=NULL; + bForceFrameHandles=FALSE; + bPlusHdlAlways=FALSE; + nFrameHandlesLimit=50; + bInsPolyPoint=FALSE; + mnInsPointNum = 0L; + bMarkedObjRectDirty=FALSE; + bMarkedPointsRectsDirty=FALSE; + mbMarkHandlesHidden = false; + bMrkPntDirty=FALSE; + bMarkHdlWhenTextEdit=FALSE; + bMarkableObjCountDirty=FALSE; // noch nicht implementiert + nMarkableObjCount=0; // noch nicht implementiert + + // #114409#-3 Migrate selections + BrkMarkObj(); + BrkMarkPoints(); + BrkMarkGluePoints(); +} + +SdrMarkView::SdrMarkView(SdrModel* pModel1, OutputDevice* pOut) +: SdrSnapView(pModel1,pOut), + mpMarkObjOverlay(0L), + mpMarkPointsOverlay(0L), + mpMarkGluePointsOverlay(0L), + aHdl(this), + mpSdrViewSelection(new sdr::ViewSelection()) +{ + ImpClearVars(); + StartListening(*pModel1); +} + +SdrMarkView::~SdrMarkView() +{ + // #114409#-3 Migrate selections + BrkMarkObj(); + BrkMarkPoints(); + BrkMarkGluePoints(); + delete mpSdrViewSelection; +} + +void __EXPORT SdrMarkView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + SdrHint* pSdrHint=PTR_CAST(SdrHint,&rHint); + if (pSdrHint!=NULL) + { + SdrHintKind eKind=pSdrHint->GetKind(); + + if (eKind==HINT_OBJCHG || eKind==HINT_OBJINSERTED || eKind==HINT_OBJREMOVED) + { + bMarkedObjRectDirty=TRUE; + bMarkedPointsRectsDirty=TRUE; + } +/* removed for now since this breaks existing code who iterates over the mark list and sequentially replaces objects + if( eKind==HINT_OBJREMOVED && IsObjMarked( const_cast<SdrObject*>(pSdrHint->GetObject()) ) ) + { + MarkObj( const_cast<SdrObject*>(pSdrHint->GetObject()), GetSdrPageView(), TRUE ); + } +*/ + } + SdrSnapView::Notify(rBC,rHint); +} + +void SdrMarkView::ModelHasChanged() +{ + SdrPaintView::ModelHasChanged(); + GetMarkedObjectListWriteAccess().SetNameDirty(); + bMarkedObjRectDirty=TRUE; + bMarkedPointsRectsDirty=TRUE; + // Es sind beispielsweise Obj markiert und maMarkedObjectListist Sorted. + // In einer anderen View 2 wird die ObjOrder veraendert + // (z.B. MovToTop()). Dann ist Neusortieren der MarkList erforderlich. + GetMarkedObjectListWriteAccess().SetUnsorted(); + SortMarkedObjects(); + bMrkPntDirty=TRUE; + UndirtyMrkPnt(); + SdrView* pV=(SdrView*)this; + if (pV!=NULL && !pV->IsDragObj() && !pV->IsInsObjPoint()) { // an dieser Stelle habe ich ein ziemliches Problem !!! + AdjustMarkHdl(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrMarkView::IsAction() const +{ + return SdrSnapView::IsAction() || IsMarkObj() || IsMarkPoints() || IsMarkGluePoints(); +} + +void SdrMarkView::MovAction(const Point& rPnt) +{ + SdrSnapView::MovAction(rPnt); + + if(IsMarkObj()) + { + MovMarkObj(rPnt); + } + else if(IsMarkPoints()) + { + MovMarkPoints(rPnt); + } + else if(IsMarkGluePoints()) + { + MovMarkGluePoints(rPnt); + } +} + +void SdrMarkView::EndAction() +{ + if(IsMarkObj()) + { + EndMarkObj(); + } + else if(IsMarkPoints()) + { + EndMarkPoints(); + } + else if(IsMarkGluePoints()) + { + EndMarkGluePoints(); + } + + SdrSnapView::EndAction(); +} + +void SdrMarkView::BckAction() +{ + SdrSnapView::BckAction(); + BrkMarkObj(); + BrkMarkPoints(); + BrkMarkGluePoints(); +} + +void SdrMarkView::BrkAction() +{ + SdrSnapView::BrkAction(); + BrkMarkObj(); + BrkMarkPoints(); + BrkMarkGluePoints(); +} + +void SdrMarkView::TakeActionRect(Rectangle& rRect) const +{ + if(IsMarkObj() || IsMarkPoints() || IsMarkGluePoints()) + { + rRect = Rectangle(aDragStat.GetStart(), aDragStat.GetNow()); + } + else + { + SdrSnapView::TakeActionRect(rRect); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkView::ClearPageView() +{ + UnmarkAllObj(); + SdrSnapView::ClearPageView(); +} + +void SdrMarkView::HideSdrPage() +{ + bool bMrkChg(false); + //HMHbool bVis(false); + + if(mpPageView) + { + // break all creation actions when hiding page (#75081#) + BrkAction(); + //HMHbVis = IsMarkHdlShown(); + + //HMHif(bVis) + //HMH{ + //HMH HideMarkHdl(); + //HMH} + + // Alle Markierungen dieser Seite verwerfen + bMrkChg = GetMarkedObjectListWriteAccess().DeletePageView(*mpPageView); + } + + SdrSnapView::HideSdrPage(); + + if(bMrkChg) + { + MarkListHasChanged(); + AdjustMarkHdl(); + } + + //HMHif(bVis) + //HMH{ + //HMH ShowMarkHdl(); + //HMH} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_Bool SdrMarkView::BegMarkObj(const Point& rPnt, sal_Bool bUnmark) +{ + BrkAction(); + + DBG_ASSERT(0L == mpMarkObjOverlay, "SdrMarkView::BegMarkObj: There exists a mpMarkObjOverlay (!)"); + basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); + mpMarkObjOverlay = new ImplMarkingOverlay(*this, aStartPos, bUnmark); + + aDragStat.Reset(rPnt); + aDragStat.NextPoint(); + aDragStat.SetMinMove(nMinMovLog); + + return sal_True; +} + +void SdrMarkView::MovMarkObj(const Point& rPnt) +{ + if(IsMarkObj() && aDragStat.CheckMinMoved(rPnt)) + { + aDragStat.NextMove(rPnt); + DBG_ASSERT(mpMarkObjOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + basegfx::B2DPoint aNewPos(rPnt.X(), rPnt.Y()); + mpMarkObjOverlay->SetSecondPosition(aNewPos); + } +} + +sal_Bool SdrMarkView::EndMarkObj() +{ + sal_Bool bRetval(sal_False); + + if(IsMarkObj()) + { + if(aDragStat.IsMinMoved()) + { + Rectangle aRect(aDragStat.GetStart(), aDragStat.GetNow()); + aRect.Justify(); + MarkObj(aRect, mpMarkObjOverlay->IsUnmarking()); + bRetval = sal_True; + } + + // cleanup + BrkMarkObj(); + } + + return bRetval; +} + +void SdrMarkView::BrkMarkObj() +{ + if(IsMarkObj()) + { + DBG_ASSERT(mpMarkObjOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + delete mpMarkObjOverlay; + mpMarkObjOverlay = 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_Bool SdrMarkView::BegMarkPoints(const Point& rPnt, sal_Bool bUnmark) +{ + if(HasMarkablePoints()) + { + BrkAction(); + + DBG_ASSERT(0L == mpMarkPointsOverlay, "SdrMarkView::BegMarkObj: There exists a mpMarkPointsOverlay (!)"); + basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); + mpMarkPointsOverlay = new ImplMarkingOverlay(*this, aStartPos, bUnmark); + + aDragStat.Reset(rPnt); + aDragStat.NextPoint(); + aDragStat.SetMinMove(nMinMovLog); + + return sal_True; + } + + return sal_False; +} + +void SdrMarkView::MovMarkPoints(const Point& rPnt) +{ + if(IsMarkPoints() && aDragStat.CheckMinMoved(rPnt)) + { + aDragStat.NextMove(rPnt); + + DBG_ASSERT(mpMarkPointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + basegfx::B2DPoint aNewPos(rPnt.X(), rPnt.Y()); + mpMarkPointsOverlay->SetSecondPosition(aNewPos); + } +} + +sal_Bool SdrMarkView::EndMarkPoints() +{ + sal_Bool bRetval(sal_False); + + if(IsMarkPoints()) + { + if(aDragStat.IsMinMoved()) + { + Rectangle aRect(aDragStat.GetStart(), aDragStat.GetNow()); + aRect.Justify(); + MarkPoints(aRect, mpMarkPointsOverlay->IsUnmarking()); + + bRetval = sal_True; + } + + // cleanup + BrkMarkPoints(); + } + + return bRetval; +} + +void SdrMarkView::BrkMarkPoints() +{ + if(IsMarkPoints()) + { + DBG_ASSERT(mpMarkPointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + delete mpMarkPointsOverlay; + mpMarkPointsOverlay = 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_Bool SdrMarkView::BegMarkGluePoints(const Point& rPnt, sal_Bool bUnmark) +{ + if(HasMarkableGluePoints()) + { + BrkAction(); + + DBG_ASSERT(0L == mpMarkGluePointsOverlay, "SdrMarkView::BegMarkObj: There exists a mpMarkGluePointsOverlay (!)"); + basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); + mpMarkGluePointsOverlay = new ImplMarkingOverlay(*this, aStartPos, bUnmark); + + aDragStat.Reset(rPnt); + aDragStat.NextPoint(); + aDragStat.SetMinMove(nMinMovLog); + + return sal_True; + } + + return sal_False; +} + +void SdrMarkView::MovMarkGluePoints(const Point& rPnt) +{ + if(IsMarkGluePoints() && aDragStat.CheckMinMoved(rPnt)) + { + aDragStat.NextMove(rPnt); + + DBG_ASSERT(mpMarkGluePointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + basegfx::B2DPoint aNewPos(rPnt.X(), rPnt.Y()); + mpMarkGluePointsOverlay->SetSecondPosition(aNewPos); + } +} + +sal_Bool SdrMarkView::EndMarkGluePoints() +{ + sal_Bool bRetval(sal_False); + + if(IsMarkGluePoints()) + { + if(aDragStat.IsMinMoved()) + { + Rectangle aRect(aDragStat.GetStart(),aDragStat.GetNow()); + aRect.Justify(); + MarkGluePoints(&aRect, mpMarkGluePointsOverlay->IsUnmarking()); + + bRetval = sal_True; + } + + // cleanup + BrkMarkGluePoints(); + } + + return bRetval; +} + +void SdrMarkView::BrkMarkGluePoints() +{ + if(IsMarkGluePoints()) + { + DBG_ASSERT(mpMarkGluePointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + delete mpMarkGluePointsOverlay; + mpMarkGluePointsOverlay = 0L; + } +} + +BOOL SdrMarkView::HasMarkableObj() const +{ + ULONG nCount=0; + + SdrPageView* pPV = GetSdrPageView(); + if(pPV) + { + SdrObjList* pOL=pPV->GetObjList(); + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG nObjNum=0; nObjNum<nObjAnz && nCount==0; nObjNum++) { + SdrObject* pObj=pOL->GetObj(nObjNum); + if (IsObjMarkable(pObj,pPV)) { + nCount++; + } + } + } + return nCount!=0; +} + +ULONG SdrMarkView::GetMarkableObjCount() const +{ + ULONG nCount=0; + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + SdrObjList* pOL=pPV->GetObjList(); + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG nObjNum=0; nObjNum<nObjAnz; nObjNum++) { + SdrObject* pObj=pOL->GetObj(nObjNum); + if (IsObjMarkable(pObj,pPV)) { + nCount++; + } + } + } + return nCount; +} + +//HMHvoid SdrMarkView::ImpShowMarkHdl(bool /*bNoRefHdl*/) +//HMH{ +//HMH bNoRefHdl=FALSE; // geht leider erstmal nicht anders +//HMH if (!bHdlShown) { +//HMH bRefHdlShownOnly=FALSE; +//HMH bHdlShown=TRUE; +//HMH } +//HMH} + +//HMHvoid SdrMarkView::ShowMarkHdl(bool /*bNoRefHdl*/) +//HMH{ +//HMH bNoRefHdl=FALSE; // geht leider erstmal nicht anders +//HMH ImpShowMarkHdl(bNoRefHdl); +//HMH} + + +//HMHvoid SdrMarkView::HideMarkHdl(bool /*bNoRefHdl*/) +//HMH{ +//HMH bNoRefHdl=FALSE; // geht leider erstmal nicht anders +//HMH if (bHdlShown) { +//HMH bRefHdlShownOnly=bNoRefHdl; +//HMH bHdlShown=FALSE; +//HMH } +//HMH} + +void SdrMarkView::hideMarkHandles() +{ + if(!mbMarkHandlesHidden) + { + mbMarkHandlesHidden = true; + AdjustMarkHdl(); + } +} + +void SdrMarkView::showMarkHandles() +{ + if(mbMarkHandlesHidden) + { + mbMarkHandlesHidden = false; + AdjustMarkHdl(); + } +} + +BOOL SdrMarkView::ImpIsFrameHandles() const +{ + ULONG nMarkAnz=GetMarkedObjectCount(); + BOOL bFrmHdl=nMarkAnz>nFrameHandlesLimit || bForceFrameHandles; + BOOL bStdDrag=eDragMode==SDRDRAG_MOVE; + if (nMarkAnz==1 && bStdDrag && bFrmHdl) + { + const SdrObject* pObj=GetMarkedObjectByIndex(0); + if (pObj->GetObjInventor()==SdrInventor) + { + UINT16 nIdent=pObj->GetObjIdentifier(); + if (nIdent==OBJ_LINE || nIdent==OBJ_EDGE || nIdent==OBJ_CAPTION || nIdent==OBJ_MEASURE || nIdent==OBJ_CUSTOMSHAPE || nIdent==OBJ_TABLE ) + { + bFrmHdl=FALSE; + } + } + } + if (!bStdDrag && !bFrmHdl) { + // Grundsaetzlich erstmal alle anderen Dragmodi nur mit FrameHandles + bFrmHdl=TRUE; + if (eDragMode==SDRDRAG_ROTATE) { + // bei Rotate ObjOwn-Drag, wenn mind. 1 PolyObj + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz && bFrmHdl; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + bFrmHdl=!pObj->IsPolyObj(); + } + } + } + if (!bFrmHdl) { + // FrameHandles, wenn wenigstens 1 Obj kein SpecialDrag kann + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz && !bFrmHdl; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + bFrmHdl=!pObj->hasSpecialDrag(); + } + } + return bFrmHdl; +} + +void SdrMarkView::SetMarkHandles() +{ + // #105722# remember old focus handle values to search for it again + const SdrHdl* pSaveOldFocusHdl = aHdl.GetFocusHdl(); + sal_Bool bSaveOldFocus(sal_False); + sal_uInt32 nSavePolyNum(0L), nSavePointNum(0L); + SdrHdlKind eSaveKind(HDL_MOVE); + SdrObject* pSaveObj = NULL; + + if(pSaveOldFocusHdl + && pSaveOldFocusHdl->GetObj() + && pSaveOldFocusHdl->GetObj()->ISA(SdrPathObj) + && (pSaveOldFocusHdl->GetKind() == HDL_POLY || pSaveOldFocusHdl->GetKind() == HDL_BWGT)) + { + bSaveOldFocus = sal_True; + nSavePolyNum = pSaveOldFocusHdl->GetPolyNum(); + nSavePointNum = pSaveOldFocusHdl->GetPointNum(); + pSaveObj = pSaveOldFocusHdl->GetObj(); + eSaveKind = pSaveOldFocusHdl->GetKind(); + } + + // delete/clear all handles. This will always be done, even with areMarkHandlesHidden() + aHdl.Clear(); + aHdl.SetRotateShear(eDragMode==SDRDRAG_ROTATE); + aHdl.SetDistortShear(eDragMode==SDRDRAG_SHEAR); + pMarkedObj=NULL; + pMarkedPV=NULL; + + // are handles enabled at all? Create only then + if(!areMarkHandlesHidden()) + { + ULONG nMarkAnz=GetMarkedObjectCount(); + BOOL bStdDrag=eDragMode==SDRDRAG_MOVE; + BOOL bSingleTextObjMark=FALSE; + + if (nMarkAnz==1) + { + pMarkedObj=GetMarkedObjectByIndex(0); + bSingleTextObjMark = + pMarkedObj && + pMarkedObj->ISA(SdrTextObj) && + static_cast<SdrTextObj*>(pMarkedObj)->IsTextFrame(); + } + + BOOL bFrmHdl=ImpIsFrameHandles(); + + if (nMarkAnz>0) + { + pMarkedPV=GetSdrPageViewOfMarkedByIndex(0); + + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz && (pMarkedPV!=NULL || !bFrmHdl); nMarkNum++) + { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + + if (pMarkedPV!=pM->GetPageView()) + { + pMarkedPV=NULL; + } + } + } + + if (bFrmHdl) + { + Rectangle aRect(GetMarkedObjRect()); + + // #i33755# + const sal_Bool bHideHandlesWhenInTextEdit( + ((SdrView*)this)->IsTextEdit() + && pMarkedObj + && pMarkedObj->ISA(SdrTextObj) + && ((SdrTextObj*)pMarkedObj)->IsInEditMode()); + + if(!aRect.IsEmpty() && !bHideHandlesWhenInTextEdit) + { // sonst nix gefunden + if( bSingleTextObjMark ) + { + const ULONG nSiz0=aHdl.GetHdlCount(); + pMarkedObj->AddToHdlList(aHdl); + const ULONG nSiz1=aHdl.GetHdlCount(); + for (ULONG i=nSiz0; i<nSiz1; i++) + { + SdrHdl* pHdl=aHdl.GetHdl(i); + pHdl->SetObj(pMarkedObj); + pHdl->SetPageView(pMarkedPV); + pHdl->SetObjHdlNum(USHORT(i-nSiz0)); + } + } + else if( eDragMode==SDRDRAG_CROP ) + { + aHdl.AddHdl(new SdrCropHdl(aRect.TopLeft() ,HDL_UPLFT)); + aHdl.AddHdl(new SdrCropHdl(aRect.TopCenter() ,HDL_UPPER)); + aHdl.AddHdl(new SdrCropHdl(aRect.TopRight() ,HDL_UPRGT)); + aHdl.AddHdl(new SdrCropHdl(aRect.LeftCenter() ,HDL_LEFT )); + aHdl.AddHdl(new SdrCropHdl(aRect.RightCenter() ,HDL_RIGHT)); + aHdl.AddHdl(new SdrCropHdl(aRect.BottomLeft() ,HDL_LWLFT)); + aHdl.AddHdl(new SdrCropHdl(aRect.BottomCenter(),HDL_LOWER)); + aHdl.AddHdl(new SdrCropHdl(aRect.BottomRight() ,HDL_LWRGT)); + } + else + { + BOOL bWdt0=aRect.Left()==aRect.Right(); + BOOL bHgt0=aRect.Top()==aRect.Bottom(); + if (bWdt0 && bHgt0) + { + aHdl.AddHdl(new SdrHdl(aRect.TopLeft(),HDL_UPLFT)); + } + else if (!bStdDrag && (bWdt0 || bHgt0)) + { + aHdl.AddHdl(new SdrHdl(aRect.TopLeft() ,HDL_UPLFT)); + aHdl.AddHdl(new SdrHdl(aRect.BottomRight(),HDL_LWRGT)); + } + else + { + if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.TopLeft() ,HDL_UPLFT)); + if ( !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.TopCenter() ,HDL_UPPER)); + if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.TopRight() ,HDL_UPRGT)); + if (!bWdt0 ) aHdl.AddHdl(new SdrHdl(aRect.LeftCenter() ,HDL_LEFT )); + if (!bWdt0 ) aHdl.AddHdl(new SdrHdl(aRect.RightCenter() ,HDL_RIGHT)); + if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.BottomLeft() ,HDL_LWLFT)); + if ( !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.BottomCenter(),HDL_LOWER)); + if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.BottomRight() ,HDL_LWRGT)); + } + } + } + } + else + { + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) + { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrPageView* pPV=pM->GetPageView(); + const ULONG nSiz0=aHdl.GetHdlCount(); + pObj->AddToHdlList(aHdl); + const ULONG nSiz1=aHdl.GetHdlCount(); + bool bPoly=pObj->IsPolyObj(); + const SdrUShortCont* pMrkPnts=pM->GetMarkedPoints(); + for (ULONG i=nSiz0; i<nSiz1; i++) + { + SdrHdl* pHdl=aHdl.GetHdl(i); + pHdl->SetObj(pObj); + pHdl->SetPageView(pPV); + pHdl->SetObjHdlNum(USHORT(i-nSiz0)); + if (bPoly) + { + BOOL bSelected=pMrkPnts!=NULL && pMrkPnts->Exist(USHORT(i-nSiz0)); + pHdl->SetSelected(bSelected); + //BOOL bPlus=bPlusHdlAlways; + if (bPlusHdlAlways || bSelected) + { + sal_uInt32 nPlusAnz=pObj->GetPlusHdlCount(*pHdl); + for (sal_uInt32 nPlusNum=0; nPlusNum<nPlusAnz; nPlusNum++) + { + SdrHdl* pPlusHdl=pObj->GetPlusHdl(*pHdl,nPlusNum); + if (pPlusHdl!=NULL) + { + pPlusHdl->SetObj(pObj); + pPlusHdl->SetPageView(pPV); + pPlusHdl->SetPlusHdl(TRUE); + aHdl.AddHdl(pPlusHdl); + } + } + } + } + } + } // for nMarkNum + } // if bFrmHdl else + + // GluePoint-Handles + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) + { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrPageView* pPV=pM->GetPageView(); + const SdrUShortCont* pMrkGlue=pM->GetMarkedGluePoints(); + if (pMrkGlue!=NULL) + { + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + if (pGPL!=NULL) + { + //USHORT nGlueAnz=pGPL->GetCount(); + USHORT nAnz=(USHORT)pMrkGlue->GetCount(); + for (USHORT nNum=0; nNum<nAnz; nNum++) + { + USHORT nId=pMrkGlue->GetObject(nNum); + //nNum changed to nNumGP because already used in for loop + USHORT nNumGP=pGPL->FindGluePoint(nId); + if (nNumGP!=SDRGLUEPOINT_NOTFOUND) + { + const SdrGluePoint& rGP=(*pGPL)[nNumGP]; + Point aPos(rGP.GetAbsolutePos(*pObj)); + SdrHdl* pGlueHdl=new SdrHdl(aPos,HDL_GLUE); + pGlueHdl->SetObj(pObj); + pGlueHdl->SetPageView(pPV); + pGlueHdl->SetObjHdlNum(nId); + aHdl.AddHdl(pGlueHdl); + } + } + } + } + } + + // Drehpunkt/Spiegelachse + AddDragModeHdl(eDragMode); + + // add custom handles (used by other apps, e.g. AnchorPos) + AddCustomHdl(); + + // sort handles + aHdl.Sort(); + + // #105722# try to restore focus handle index from remembered values + if(bSaveOldFocus) + { + for(sal_uInt32 a(0); a < aHdl.GetHdlCount(); a++) + { + SdrHdl* pCandidate = aHdl.GetHdl(a); + + if(pCandidate->GetObj() + && pCandidate->GetObj() == pSaveObj + && pCandidate->GetKind() == eSaveKind + && pCandidate->GetPolyNum() == nSavePolyNum + && pCandidate->GetPointNum() == nSavePointNum) + { + aHdl.SetFocusHdl(pCandidate); + break; + } + } + } + } +} + +void SdrMarkView::AddCustomHdl() +{ + // add custom handles (used by other apps, e.g. AnchorPos) +} + +void SdrMarkView::SetDragMode(SdrDragMode eMode) +{ + SdrDragMode eMode0=eDragMode; + eDragMode=eMode; + if (eDragMode==SDRDRAG_RESIZE) eDragMode=SDRDRAG_MOVE; + if (eDragMode!=eMode0) { + //HMHBOOL bVis=IsMarkHdlShown(); + //HMHif (bVis) HideMarkHdl(); + ForceRefToMarked(); + SetMarkHandles(); + //HMHif (bVis) ShowMarkHdl(); + { + if (AreObjectsMarked()) MarkListHasChanged(); + } + } +} + +void SdrMarkView::AddDragModeHdl(SdrDragMode eMode) +{ + switch(eMode) + { + case SDRDRAG_ROTATE: + { + // add rotation center + SdrHdl* pHdl = new SdrHdl(aRef1, HDL_REF1); + + aHdl.AddHdl(pHdl); + + break; + } + case SDRDRAG_MIRROR: + { + // add mirror axis + SdrHdl* pHdl3 = new SdrHdl(aRef2, HDL_REF2); + SdrHdl* pHdl2 = new SdrHdl(aRef1, HDL_REF1); + SdrHdl* pHdl1 = new SdrHdlLine(*pHdl2, *pHdl3, HDL_MIRX); + + pHdl1->SetObjHdlNum(1); // fuer Sortierung + pHdl2->SetObjHdlNum(2); // fuer Sortierung + pHdl3->SetObjHdlNum(3); // fuer Sortierung + + aHdl.AddHdl(pHdl1); // Linie als erstes, damit als letztes im HitTest + aHdl.AddHdl(pHdl2); + aHdl.AddHdl(pHdl3); + + break; + } + case SDRDRAG_TRANSPARENCE: + { + // add interactive transparence handle + ULONG nMarkAnz = GetMarkedObjectCount(); + if(nMarkAnz == 1) + { + SdrObject* pObj = GetMarkedObjectByIndex(0); + SdrModel* pModel = GetModel(); + const SfxItemSet& rSet = pObj->GetMergedItemSet(); + + if(SFX_ITEM_SET != rSet.GetItemState(XATTR_FILLFLOATTRANSPARENCE, FALSE)) + { + // add this item, it's not yet there + XFillFloatTransparenceItem aNewItem( + (const XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE)); + XGradient aGrad = aNewItem.GetGradientValue(); + + aNewItem.SetEnabled(TRUE); + aGrad.SetStartIntens(100); + aGrad.SetEndIntens(100); + aNewItem.SetGradientValue(aGrad); + + // add undo to allow user to take back this step + if( pModel->IsUndoEnabled() ) + { + pModel->BegUndo(SVX_RESSTR(SIP_XA_FILLTRANSPARENCE)); + pModel->AddUndo(pModel->GetSdrUndoFactory().CreateUndoAttrObject(*pObj)); + pModel->EndUndo(); + } + + //pObj->SetItemAndBroadcast(aNewItem); + SfxItemSet aNewSet(pModel->GetItemPool()); + aNewSet.Put(aNewItem); + pObj->SetMergedItemSetAndBroadcast(aNewSet); + } + + // set values and transform to vector set + GradTransformer aGradTransformer; + GradTransVector aGradTransVector; + GradTransGradient aGradTransGradient; + + aGradTransGradient.aGradient = ((XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE)).GetGradientValue(); + aGradTransformer.GradToVec(aGradTransGradient, aGradTransVector, pObj); + + // build handles + const Point aTmpPos1(basegfx::fround(aGradTransVector.maPositionA.getX()), basegfx::fround(aGradTransVector.maPositionA.getY())); + const Point aTmpPos2(basegfx::fround(aGradTransVector.maPositionB.getX()), basegfx::fround(aGradTransVector.maPositionB.getY())); + SdrHdlColor* pColHdl1 = new SdrHdlColor(aTmpPos1, aGradTransVector.aCol1, SDR_HANDLE_COLOR_SIZE_NORMAL, TRUE); + SdrHdlColor* pColHdl2 = new SdrHdlColor(aTmpPos2, aGradTransVector.aCol2, SDR_HANDLE_COLOR_SIZE_NORMAL, TRUE); + SdrHdlGradient* pGradHdl = new SdrHdlGradient(aTmpPos1, aTmpPos2, FALSE); + DBG_ASSERT(pColHdl1 && pColHdl2 && pGradHdl, "Got not all necessary handles!!"); + + // link them + pGradHdl->SetColorHandles(pColHdl1, pColHdl2); + pGradHdl->SetObj(pObj); + pColHdl1->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); + pColHdl2->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); + + // insert them + aHdl.AddHdl(pColHdl1); + aHdl.AddHdl(pColHdl2); + aHdl.AddHdl(pGradHdl); + } + break; + } + case SDRDRAG_GRADIENT: + { + // add interactive gradient handle + ULONG nMarkAnz = GetMarkedObjectCount(); + if(nMarkAnz == 1) + { + SdrObject* pObj = GetMarkedObjectByIndex(0); + const SfxItemSet& rSet = pObj->GetMergedItemSet(); + XFillStyle eFillStyle = ((XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue(); + + if(eFillStyle == XFILL_GRADIENT) + { + // set values and transform to vector set + GradTransformer aGradTransformer; + GradTransVector aGradTransVector; + GradTransGradient aGradTransGradient; + Size aHdlSize(15, 15); + + aGradTransGradient.aGradient = ((XFillGradientItem&)rSet.Get(XATTR_FILLGRADIENT)).GetGradientValue(); + aGradTransformer.GradToVec(aGradTransGradient, aGradTransVector, pObj); + + // build handles + const Point aTmpPos1(basegfx::fround(aGradTransVector.maPositionA.getX()), basegfx::fround(aGradTransVector.maPositionA.getY())); + const Point aTmpPos2(basegfx::fround(aGradTransVector.maPositionB.getX()), basegfx::fround(aGradTransVector.maPositionB.getY())); + SdrHdlColor* pColHdl1 = new SdrHdlColor(aTmpPos1, aGradTransVector.aCol1, aHdlSize, FALSE); + SdrHdlColor* pColHdl2 = new SdrHdlColor(aTmpPos2, aGradTransVector.aCol2, aHdlSize, FALSE); + SdrHdlGradient* pGradHdl = new SdrHdlGradient(aTmpPos1, aTmpPos2, TRUE); + DBG_ASSERT(pColHdl1 && pColHdl2 && pGradHdl, "Got not all necessary handles!!"); + + // link them + pGradHdl->SetColorHandles(pColHdl1, pColHdl2); + pGradHdl->SetObj(pObj); + pColHdl1->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); + pColHdl2->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); + + // insert them + aHdl.AddHdl(pColHdl1); + aHdl.AddHdl(pColHdl2); + aHdl.AddHdl(pGradHdl); + } + } + break; + } + case SDRDRAG_CROP: + { + // todo + break; + } + default: break; + } +} + +/** handle mouse over effects for handles */ +BOOL SdrMarkView::MouseMove(const MouseEvent& rMEvt, Window* pWin) +{ + const ULONG nHdlCount = aHdl.GetHdlCount(); + if( nHdlCount ) + { + SdrHdl* pMouseOverHdl = 0; + if( !rMEvt.IsLeaveWindow() && pWin ) + { + Point aMDPos( pWin->PixelToLogic( rMEvt.GetPosPixel() ) ); + pMouseOverHdl = PickHandle(aMDPos); + } + + // notify last mouse over handle that he lost the mouse + for(ULONG nHdl = 0; nHdl < nHdlCount; nHdl++ ) + { + SdrHdl* pCurrentHdl = GetHdl(nHdl); + if( pCurrentHdl->mbMouseOver ) + { + if( pCurrentHdl != pMouseOverHdl ) + { + pCurrentHdl->mbMouseOver = false; + pCurrentHdl->onMouseLeave(); + } + break; + } + } + + // notify current mouse over handle + if( pMouseOverHdl /* && !pMouseOverHdl->mbMouseOver */ ) + { + pMouseOverHdl->mbMouseOver = true; + pMouseOverHdl->onMouseEnter(rMEvt); + } + } + return SdrSnapView::MouseMove(rMEvt, pWin); +} + +void SdrMarkView::ForceRefToMarked() +{ + switch(eDragMode) + { + case SDRDRAG_ROTATE: + { + Rectangle aR(GetMarkedObjRect()); + aRef1 = aR.Center(); + + break; + } + + case SDRDRAG_MIRROR: + { + // Erstmal die laenge der Spiegelachsenlinie berechnen + long nOutMin=0; + long nOutMax=0; + long nMinLen=0; + long nObjDst=0; + long nOutHgt=0; + OutputDevice* pOut=GetFirstOutputDevice(); + //OutputDevice* pOut=GetWin(0); + if (pOut!=NULL) { + // Mindestlaenge 50 Pixel + nMinLen=pOut->PixelToLogic(Size(0,50)).Height(); + // 20 Pixel fuer RefPt-Abstand vom Obj + nObjDst=pOut->PixelToLogic(Size(0,20)).Height(); + // MinY/MaxY + // Abstand zum Rand = Mindestlaenge = 10 Pixel + long nDst=pOut->PixelToLogic(Size(0,10)).Height(); + nOutMin=-pOut->GetMapMode().GetOrigin().Y(); + nOutMax=pOut->GetOutputSize().Height()-1+nOutMin; + nOutMin+=nDst; + nOutMax-=nDst; + // Absolute Mindestlaenge jedoch 10 Pixel + if (nOutMax-nOutMin<nDst) { + nOutMin+=nOutMax+1; + nOutMin/=2; + nOutMin-=(nDst+1)/2; + nOutMax=nOutMin+nDst; + } + nOutHgt=nOutMax-nOutMin; + // Sonst Mindestlaenge = 1/4 OutHgt + long nTemp=nOutHgt/4; + if (nTemp>nMinLen) nMinLen=nTemp; + } + + Rectangle aR(GetMarkedObjBoundRect()); + Point aCenter(aR.Center()); + long nMarkHgt=aR.GetHeight()-1; + long nHgt=nMarkHgt+nObjDst*2; // 20 Pixel obej und unten ueberstehend + if (nHgt<nMinLen) nHgt=nMinLen; // Mindestlaenge 50 Pixel bzw. 1/4 OutHgt + + long nY1=aCenter.Y()-(nHgt+1)/2; + long nY2=nY1+nHgt; + + if (pOut!=NULL && nMinLen>nOutHgt) nMinLen=nOutHgt; // evtl. noch etwas verkuerzen + + if (pOut!=NULL) { // nun vollstaendig in den sichtbaren Bereich schieben + if (nY1<nOutMin) { + nY1=nOutMin; + if (nY2<nY1+nMinLen) nY2=nY1+nMinLen; + } + if (nY2>nOutMax) { + nY2=nOutMax; + if (nY1>nY2-nMinLen) nY1=nY2-nMinLen; + } + } + + aRef1.X()=aCenter.X(); + aRef1.Y()=nY1; + aRef2.X()=aCenter.X(); + aRef2.Y()=nY2; + + break; + } + + case SDRDRAG_TRANSPARENCE: + case SDRDRAG_GRADIENT: + case SDRDRAG_CROP: + { + Rectangle aRect(GetMarkedObjBoundRect()); + aRef1 = aRect.TopLeft(); + aRef2 = aRect.BottomRight(); + break; + } + default: break; + } +} + +void SdrMarkView::SetRef1(const Point& rPt) +{ + if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR) + { + aRef1 = rPt; + SdrHdl* pH = aHdl.GetHdl(HDL_REF1); + if(pH) + pH->SetPos(rPt); + //HMHShowMarkHdl(); + } +} + +void SdrMarkView::SetRef2(const Point& rPt) +{ + if(eDragMode == SDRDRAG_MIRROR) + { + aRef2 = rPt; + SdrHdl* pH = aHdl.GetHdl(HDL_REF2); + if(pH) + pH->SetPos(rPt); + //HMHShowMarkHdl(); + } +} + +void SdrMarkView::CheckMarked() +{ + for (ULONG nm=GetMarkedObjectCount(); nm>0;) { + nm--; + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrPageView* pPV=pM->GetPageView(); + SdrLayerID nLay=pObj->GetLayer(); + BOOL bRaus=!pObj->IsInserted(); // Obj geloescht? + if (!pObj->Is3DObj()) { + bRaus=bRaus || pObj->GetPage()!=pPV->GetPage(); // Obj ploetzlich in anderer Page oder Group + } + bRaus=bRaus || pPV->GetLockedLayers().IsSet(nLay) || // Layer gesperrt? + !pPV->GetVisibleLayers().IsSet(nLay); // Layer nicht sichtbar? + + if( !bRaus ) + bRaus = !pObj->IsVisible(); // not visible objects can not be marked + + if (!bRaus) { + // Joe am 9.3.1997: Gruppierte Objekten koennen nun auch + // markiert werden. Nach EnterGroup muessen aber die Objekte + // der hoeheren Ebene deselektiert werden. + const SdrObjList* pOOL=pObj->GetObjList(); + const SdrObjList* pVOL=pPV->GetObjList(); + while (pOOL!=NULL && pOOL!=pVOL) { + pOOL=pOOL->GetUpList(); + } + bRaus=pOOL!=pVOL; + } + + if (bRaus) + { + GetMarkedObjectListWriteAccess().DeleteMark(nm); + } + else + { + if (!IsGluePointEditMode()) { // Markierte GluePoints nur im GlueEditMode + SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + if (pPts!=NULL && pPts->GetCount()!=0) { + pPts->Clear(); + } + } + } + } + + // #97995# at least reset the remembered BoundRect to prevent handle + // generation if bForceFrameHandles is TRUE. + bMarkedObjRectDirty = TRUE; +} + +void SdrMarkView::SetMarkRects() +{ + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + pPV->SetHasMarkedObj(GetSnapRectFromMarkedObjects(pPV, pPV->MarkSnap())); + GetBoundRectFromMarkedObjects(pPV, pPV->MarkBound()); + } +} + +void SdrMarkView::SetFrameHandles(BOOL bOn) +{ + if (bOn!=bForceFrameHandles) { + BOOL bOld=ImpIsFrameHandles(); + bForceFrameHandles=bOn; + BOOL bNew=ImpIsFrameHandles(); + if (bNew!=bOld) { + AdjustMarkHdl(); //HMHTRUE); + MarkListHasChanged(); + } + } +} + +void SdrMarkView::SetEditMode(SdrViewEditMode eMode) +{ + if (eMode!=eEditMode) { + BOOL bGlue0=eEditMode==SDREDITMODE_GLUEPOINTEDIT; + BOOL bEdge0=((SdrCreateView*)this)->IsEdgeTool(); + eEditMode0=eEditMode; + eEditMode=eMode; + BOOL bGlue1=eEditMode==SDREDITMODE_GLUEPOINTEDIT; + BOOL bEdge1=((SdrCreateView*)this)->IsEdgeTool(); + // etwas Aufwand um Flackern zu verhindern beim Umschalten + // zwischen GlueEdit und EdgeTool + if (bGlue1 && !bGlue0) ImpSetGlueVisible2(bGlue1); + if (bEdge1!=bEdge0) ImpSetGlueVisible3(bEdge1); + if (!bGlue1 && bGlue0) ImpSetGlueVisible2(bGlue1); + if (bGlue0 && !bGlue1) UnmarkAllGluePoints(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrMarkView::IsObjMarkable(SdrObject* pObj, SdrPageView* pPV) const +{ + if (pObj) + { + if (pObj->IsMarkProtect() || + (!bDesignMode && pObj->IsUnoObj())) + { + // Objekt nicht selektierbar oder + // SdrUnoObj nicht im DesignMode + return FALSE; + } + } + return pPV!=NULL ? pPV->IsObjMarkable(pObj) : TRUE; +} + +BOOL SdrMarkView::IsMarkedObjHit(const Point& rPnt, short nTol) const +{ + BOOL bRet=FALSE; + nTol=ImpGetHitTolLogic(nTol,NULL); + Point aPt(rPnt); + for (ULONG nm=0; nm<GetMarkedObjectCount() && !bRet; nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + bRet = 0 != CheckSingleSdrObjectHit(aPt,USHORT(nTol),pM->GetMarkedSdrObj(),pM->GetPageView(),0,0); + } + return bRet; +} + +SdrHdl* SdrMarkView::PickHandle(const Point& rPnt, ULONG nOptions, SdrHdl* pHdl0) const +{ + if (bSomeObjChgdFlag) { // ggf. Handles neu berechnen lassen! + FlushComeBackTimer(); + } + BOOL bBack=(nOptions & SDRSEARCH_BACKWARD) !=0; + BOOL bNext=(nOptions & SDRSEARCH_NEXT) !=0; + Point aPt(rPnt); + return aHdl.IsHdlListHit(aPt,bBack,bNext,pHdl0); +} + +BOOL SdrMarkView::MarkObj(const Point& rPnt, short nTol, BOOL bToggle, BOOL bDeep) +{ + SdrObject* pObj; + SdrPageView* pPV; + nTol=ImpGetHitTolLogic(nTol,NULL); + ULONG nOptions=SDRSEARCH_PICKMARKABLE; + if (bDeep) nOptions=nOptions|SDRSEARCH_DEEP; + BOOL bRet=PickObj(rPnt,(USHORT)nTol,pObj,pPV,nOptions); + if (bRet) { + BOOL bUnmark=bToggle && IsObjMarked(pObj); + MarkObj(pObj,pPV,bUnmark); + } + return bRet; +} + +BOOL SdrMarkView::MarkNextObj(BOOL bPrev) +{ + SdrPageView* pPageView = GetSdrPageView(); + + if(!pPageView) + { + return FALSE; + } + + SortMarkedObjects(); + ULONG nMarkAnz=GetMarkedObjectCount(); + ULONG nChgMarkNum = ULONG_MAX; // Nummer des zu ersetzenden MarkEntries + ULONG nSearchObjNum = bPrev ? 0 : ULONG_MAX; + if (nMarkAnz!=0) { + nChgMarkNum=bPrev ? 0 : ULONG(nMarkAnz-1); + SdrMark* pM=GetSdrMarkByIndex(nChgMarkNum); + OSL_ASSERT(pM!=NULL); + if (pM->GetMarkedSdrObj() != NULL) + nSearchObjNum = pM->GetMarkedSdrObj()->GetNavigationPosition(); + } + + SdrObject* pMarkObj=NULL; + SdrObjList* pSearchObjList=pPageView->GetObjList(); + ULONG nObjAnz=pSearchObjList->GetObjCount(); + if (nObjAnz!=0) { + if (nSearchObjNum>nObjAnz) nSearchObjNum=nObjAnz; + while (pMarkObj==NULL && ((!bPrev && nSearchObjNum>0) || (bPrev && nSearchObjNum<nObjAnz))) + { + if (!bPrev) + nSearchObjNum--; + SdrObject* pSearchObj = pSearchObjList->GetObjectForNavigationPosition(nSearchObjNum); + if (IsObjMarkable(pSearchObj,pPageView)) + { + if (TryToFindMarkedObject(pSearchObj)==CONTAINER_ENTRY_NOTFOUND) + { + pMarkObj=pSearchObj; + } + } + if (bPrev) nSearchObjNum++; + } + } + + if(!pMarkObj) + { + return FALSE; + } + + if (nChgMarkNum!=ULONG_MAX) + { + GetMarkedObjectListWriteAccess().DeleteMark(nChgMarkNum); + } + MarkObj(pMarkObj,pPageView); // ruft auch MarkListHasChanged(), AdjustMarkHdl() + return TRUE; +} + +BOOL SdrMarkView::MarkNextObj(const Point& rPnt, short nTol, BOOL bPrev) +{ + SortMarkedObjects(); + nTol=ImpGetHitTolLogic(nTol,NULL); + Point aPt(rPnt); + SdrMark* pTopMarkHit=NULL; + SdrMark* pBtmMarkHit=NULL; + ULONG nTopMarkHit=0; + ULONG nBtmMarkHit=0; + // oberstes der markierten Objekte suchen, das von rPnt getroffen wird + ULONG nMarkAnz=GetMarkedObjectCount(); + ULONG nm=0; + for (nm=nMarkAnz; nm>0 && pTopMarkHit==NULL;) { + nm--; + SdrMark* pM=GetSdrMarkByIndex(nm); + if(CheckSingleSdrObjectHit(aPt,USHORT(nTol),pM->GetMarkedSdrObj(),pM->GetPageView(),0,0)) + { + pTopMarkHit=pM; + nTopMarkHit=nm; + } + } + // Nichts gefunden, dann ganz normal ein Obj markieren. + if (pTopMarkHit==NULL) return MarkObj(rPnt,USHORT(nTol),FALSE); + + SdrObject* pTopObjHit=pTopMarkHit->GetMarkedSdrObj(); + SdrObjList* pObjList=pTopObjHit->GetObjList(); + SdrPageView* pPV=pTopMarkHit->GetPageView(); + // unterstes der markierten Objekte suchen, das von rPnt getroffen wird + // und auf der gleichen PageView liegt wie pTopMarkHit + for (nm=0; nm<nMarkAnz && pBtmMarkHit==NULL; nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrPageView* pPV2=pM->GetPageView(); + if (pPV2==pPV && CheckSingleSdrObjectHit(aPt,USHORT(nTol),pM->GetMarkedSdrObj(),pPV2,0,0)) + { + pBtmMarkHit=pM; + nBtmMarkHit=nm; + } + } + if (pBtmMarkHit==NULL) { pBtmMarkHit=pTopMarkHit; nBtmMarkHit=nTopMarkHit; } + SdrObject* pBtmObjHit=pBtmMarkHit->GetMarkedSdrObj(); + ULONG nObjAnz=pObjList->GetObjCount(); + + // #110988# + //ULONG nSearchBeg=bPrev ? pBtmObjHit->GetOrdNum()+1 : pTopObjHit->GetOrdNum(); + sal_uInt32 nSearchBeg; + E3dScene* pScene = NULL; + SdrObject* pObjHit = (bPrev) ? pBtmObjHit : pTopObjHit; + sal_Bool bRemap = pObjHit->ISA(E3dCompoundObject) + ? ((E3dCompoundObject*)pObjHit)->IsAOrdNumRemapCandidate(pScene) + : sal_False; + + if(bPrev) + { + sal_uInt32 nOrdNumBtm(pBtmObjHit->GetOrdNum()); + + if(bRemap) + { + nOrdNumBtm = pScene->RemapOrdNum(nOrdNumBtm); + } + + nSearchBeg = nOrdNumBtm + 1; + } + else + { + sal_uInt32 nOrdNumTop(pTopObjHit->GetOrdNum()); + + if(bRemap) + { + nOrdNumTop = pScene->RemapOrdNum(nOrdNumTop); + } + + nSearchBeg = nOrdNumTop; + } + + ULONG no=nSearchBeg; + SdrObject* pFndObj=NULL; + //SdrObject* pAktObj=NULL; + while (pFndObj==NULL && ((!bPrev && no>0) || (bPrev && no<nObjAnz))) { + if (!bPrev) no--; + SdrObject* pObj; + + if(bRemap) + { + pObj = pObjList->GetObj(pScene->RemapOrdNum(no)); + } + else + { + pObj = pObjList->GetObj(no); + } + + if (CheckSingleSdrObjectHit(aPt,USHORT(nTol),pObj,pPV,SDRSEARCH_TESTMARKABLE,0)) + { + if (TryToFindMarkedObject(pObj)==CONTAINER_ENTRY_NOTFOUND) { + pFndObj=pObj; + } else { + // hier wg. Performance ggf. noch no auf Top bzw. auf Btm stellen + } + } + if (bPrev) no++; + } + if (pFndObj!=NULL) + { + GetMarkedObjectListWriteAccess().DeleteMark(bPrev?nBtmMarkHit:nTopMarkHit); + GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pFndObj,pPV)); + MarkListHasChanged(); + AdjustMarkHdl(); //HMHTRUE); + } + return pFndObj!=NULL; +} + +BOOL SdrMarkView::MarkObj(const Rectangle& rRect, BOOL bUnmark) +{ + BOOL bFnd=FALSE; + Rectangle aR(rRect); + SdrObject* pObj; + SdrObjList* pObjList; + BrkAction(); + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + pObjList=pPV->GetObjList(); + Rectangle aFrm1(aR); + ULONG nObjAnz=pObjList->GetObjCount(); + for (ULONG nO=0; nO<nObjAnz; nO++) { + pObj=pObjList->GetObj(nO); + Rectangle aRect(pObj->GetCurrentBoundRect()); + if (aFrm1.IsInside(aRect)) { + if (!bUnmark) { + if (IsObjMarkable(pObj,pPV)) + { + GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj,pPV)); + bFnd=TRUE; + } + } else { + ULONG nPos=TryToFindMarkedObject(pObj); + if (nPos!=CONTAINER_ENTRY_NOTFOUND) + { + GetMarkedObjectListWriteAccess().DeleteMark(nPos); + bFnd=TRUE; + } + } + } + } + } + if (bFnd) { + SortMarkedObjects(); + MarkListHasChanged(); + AdjustMarkHdl(); //HMHTRUE); + //HMHShowMarkHdl(); + } + return bFnd; +} + +void SdrMarkView::MarkObj(SdrObject* pObj, SdrPageView* pPV, BOOL bUnmark, BOOL bImpNoSetMarkHdl) +{ + if (pObj!=NULL && pPV!=NULL && IsObjMarkable(pObj, pPV)) { + BrkAction(); + if (!bUnmark) + { + GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj,pPV)); + } + else + { + ULONG nPos=TryToFindMarkedObject(pObj); + if (nPos!=CONTAINER_ENTRY_NOTFOUND) + { + GetMarkedObjectListWriteAccess().DeleteMark(nPos); + } + } + if (!bImpNoSetMarkHdl) { + MarkListHasChanged(); + AdjustMarkHdl(); //HMHTRUE); + //HMHif (!bSomeObjChgdFlag) { + // ShowMarkHdl kommt sonst mit dem AfterPaintTimer + //HMHShowMarkHdl(); + //HMH} + } + } +} + +BOOL SdrMarkView::IsObjMarked(SdrObject* pObj) const +{ + // nicht so ganz die feine Art: Da FindObject() nicht const ist + // muss ich mich hier auf non-const casten. + ULONG nPos=((SdrMarkView*)this)->TryToFindMarkedObject(pObj); + return nPos!=CONTAINER_ENTRY_NOTFOUND; +} + +USHORT SdrMarkView::GetMarkHdlSizePixel() const +{ + return aHdl.GetHdlSize()*2+1; +} + +void SdrMarkView::SetSolidMarkHdl(BOOL bOn) +{ + if (bOn!=aHdl.IsFineHdl()) { + //HMHBOOL bMerk=IsMarkHdlShown(); + //HMHif (bMerk) HideMarkHdl(); + aHdl.SetFineHdl(bOn); + //HMHif (bMerk) ShowMarkHdl(); + } +} + +void SdrMarkView::SetMarkHdlSizePixel(USHORT nSiz) +{ + if (nSiz<3) nSiz=3; + nSiz/=2; + if (nSiz!=aHdl.GetHdlSize()) { + //HMHBOOL bMerk=IsMarkHdlShown(); + //HMHif (bMerk) HideMarkHdl(); + aHdl.SetHdlSize(nSiz); + //HMHif (bMerk) ShowMarkHdl(); + } +} + +#define SDRSEARCH_IMPISMASTER 0x80000000 /* MasterPage wird gerade durchsucht */ +SdrObject* SdrMarkView::CheckSingleSdrObjectHit(const Point& rPnt, USHORT nTol, SdrObject* pObj, SdrPageView* pPV, ULONG nOptions, const SetOfByte* pMVisLay) const +{ + if(((nOptions & SDRSEARCH_IMPISMASTER) && pObj->IsNotVisibleAsMaster()) || (!pObj->IsVisible())) + { + return NULL; + } + + const bool bCheckIfMarkable(nOptions & SDRSEARCH_TESTMARKABLE); + const bool bDeep(nOptions & SDRSEARCH_DEEP); + const bool bOLE(pObj->ISA(SdrOle2Obj)); + const bool bTXT(pObj->ISA(SdrTextObj) && ((SdrTextObj*)pObj)->IsTextFrame()); + SdrObject* pRet=NULL; + Rectangle aRect(pObj->GetCurrentBoundRect()); + USHORT nTol2(nTol); + + // double tolerance for OLE, text frames and objects in + // active text edit + if(bOLE || bTXT || pObj==((SdrObjEditView*)this)->GetTextEditObject()) + { + nTol2*=2; + } + + aRect.Left ()-=nTol2; // Einmal Toleranz drauf fuer alle Objekte + aRect.Top ()-=nTol2; + aRect.Right ()+=nTol2; + aRect.Bottom()+=nTol2; + + if (aRect.IsInside(rPnt)) + { + if ((!bCheckIfMarkable || IsObjMarkable(pObj,pPV))) + { + SdrObjList* pOL=pObj->GetSubList(); + + if (pOL!=NULL && pOL->GetObjCount()!=0) + { + SdrObject* pTmpObj; + // OD 30.06.2003 #108784# - adjustment hit point for virtual + // objects. + Point aPnt( rPnt ); + + if ( pObj->ISA(SdrVirtObj) ) + { + Point aOffset = static_cast<SdrVirtObj*>(pObj)->GetOffset(); + aPnt.Move( -aOffset.X(), -aOffset.Y() ); + } + + pRet=CheckSingleSdrObjectHit(aPnt,nTol,pOL,pPV,nOptions,pMVisLay,pTmpObj); + } + else + { + if(!pMVisLay || pMVisLay->IsSet(pObj->GetLayer())) + { + pRet = SdrObjectPrimitiveHit(*pObj, rPnt, nTol2, *pPV, &pPV->GetVisibleLayers(), false); + } + } + } + } + + if (!bDeep && pRet!=NULL) + { + pRet=pObj; + } + + return pRet; +} + +SdrObject* SdrMarkView::CheckSingleSdrObjectHit(const Point& rPnt, USHORT nTol, SdrObjList* pOL, SdrPageView* pPV, ULONG nOptions, const SetOfByte* pMVisLay, SdrObject*& rpRootObj) const +{ + BOOL bBack=(nOptions & SDRSEARCH_BACKWARD)!=0; + SdrObject* pRet=NULL; + rpRootObj=NULL; + if (pOL!=NULL) + { + // #110988# + sal_Bool bRemap(pOL->GetOwnerObj() && pOL->GetOwnerObj()->ISA(E3dScene)); + E3dScene* pRemapScene = (bRemap ? (E3dScene*)pOL->GetOwnerObj() : 0L); + + ULONG nObjAnz=pOL->GetObjCount(); + ULONG nObjNum=bBack ? 0 : nObjAnz; + while (pRet==NULL && (bBack ? nObjNum<nObjAnz : nObjNum>0)) { + if (!bBack) nObjNum--; + SdrObject* pObj; + + // #110988# + if(bRemap) + { + pObj = pOL->GetObj(pRemapScene->RemapOrdNum(nObjNum)); + } + else + { + pObj = pOL->GetObj(nObjNum); + } + + pRet=CheckSingleSdrObjectHit(rPnt,nTol,pObj,pPV,nOptions,pMVisLay); + if (pRet!=NULL) rpRootObj=pObj; + if (bBack) nObjNum++; + } + } + return pRet; +} + +BOOL SdrMarkView::PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions) const +{ + return PickObj(rPnt,nTol,rpObj,rpPV,nOptions,NULL,NULL,NULL); +} + +BOOL SdrMarkView::PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions, SdrObject** ppRootObj, ULONG* pnMarkNum, USHORT* pnPassNum) const +{ // Fehlt noch Pass2,Pass3 + SortMarkedObjects(); + if (ppRootObj!=NULL) *ppRootObj=NULL; + if (pnMarkNum!=NULL) *pnMarkNum=CONTAINER_ENTRY_NOTFOUND; + if (pnPassNum!=NULL) *pnPassNum=0; + rpObj=NULL; + rpPV=NULL; + BOOL bWholePage=(nOptions & SDRSEARCH_WHOLEPAGE) !=0; + BOOL bMarked=(nOptions & SDRSEARCH_MARKED) !=0; + BOOL bMasters=!bMarked && (nOptions & SDRSEARCH_ALSOONMASTER) !=0; + BOOL bBack=(nOptions & SDRSEARCH_BACKWARD) !=0; +#if OSL_DEBUG_LEVEL > 0 + BOOL bNext=(nOptions & SDRSEARCH_NEXT) !=0; (void)bNext; // n.i. + BOOL bBoundCheckOn2ndPass=(nOptions & SDRSEARCH_PASS2BOUND) !=0; (void)bBoundCheckOn2ndPass;// n.i. + BOOL bCheckNearestOn3rdPass=(nOptions & SDRSEARCH_PASS3NEAREST) !=0; (void)bCheckNearestOn3rdPass;// n.i. +#endif + if (nTol<0) nTol=ImpGetHitTolLogic(nTol,NULL); + Point aPt(rPnt); + SdrObject* pObj=NULL; + SdrObject* pHitObj=NULL; + SdrPageView* pPV=NULL; + if (!bBack && ((SdrObjEditView*)this)->IsTextEditFrameHit(rPnt)) { + pObj=((SdrObjEditView*)this)->GetTextEditObject(); + pHitObj=pObj; + pPV=((SdrObjEditView*)this)->GetTextEditPageView(); + } + if (bMarked) { + ULONG nMrkAnz=GetMarkedObjectCount(); + ULONG nMrkNum=bBack ? 0 : nMrkAnz; + while (pHitObj==NULL && (bBack ? nMrkNum<nMrkAnz : nMrkNum>0)) { + if (!bBack) nMrkNum--; + SdrMark* pM=GetSdrMarkByIndex(nMrkNum); + pObj=pM->GetMarkedSdrObj(); + pPV=pM->GetPageView(); + pHitObj=CheckSingleSdrObjectHit(aPt,nTol,pObj,pPV,nOptions,NULL); + if (bBack) nMrkNum++; + } + } + else + { + pPV = GetSdrPageView(); + + if(pPV) + { + SdrPage* pPage=pPV->GetPage(); + USHORT nPgAnz=1; + + if(bMasters && pPage->TRG_HasMasterPage()) + { + nPgAnz++; + } + + BOOL bExtraPassForWholePage=bWholePage && pPage!=pPV->GetObjList(); + if (bExtraPassForWholePage) nPgAnz++; // Suche erst in AktObjList, dann auf der gesamten Page + USHORT nPgNum=bBack ? 0 : nPgAnz; + while (pHitObj==NULL && (bBack ? nPgNum<nPgAnz : nPgNum>0)) { + ULONG nTmpOptions=nOptions; + if (!bBack) nPgNum--; + const SetOfByte* pMVisLay=NULL; + SdrObjList* pObjList=NULL; + if (pnPassNum!=NULL) *pnPassNum&=~(SDRSEARCHPASS_MASTERPAGE|SDRSEARCHPASS_INACTIVELIST); + if (nPgNum>=nPgAnz-1 || (bExtraPassForWholePage && nPgNum>=nPgAnz-2)) + { + pObjList=pPV->GetObjList(); + if (bExtraPassForWholePage && nPgNum==nPgAnz-2) { + pObjList=pPage; + if (pnPassNum!=NULL) *pnPassNum|=SDRSEARCHPASS_INACTIVELIST; + } + } + else + { + // sonst MasterPage + SdrPage& rMasterPage = pPage->TRG_GetMasterPage(); + pMVisLay = &pPage->TRG_GetMasterPageVisibleLayers(); + pObjList = &rMasterPage; + + if (pnPassNum!=NULL) *pnPassNum|=SDRSEARCHPASS_MASTERPAGE; + nTmpOptions=nTmpOptions | SDRSEARCH_IMPISMASTER; + } + pHitObj=CheckSingleSdrObjectHit(aPt,nTol,pObjList,pPV,nTmpOptions,pMVisLay,pObj); + if (bBack) nPgNum++; + } + } + } + if (pHitObj!=NULL) { + if (ppRootObj!=NULL) *ppRootObj=pObj; + if ((nOptions & SDRSEARCH_DEEP) !=0) pObj=pHitObj; + if ((nOptions & SDRSEARCH_TESTTEXTEDIT) !=0) { + if (!pObj->HasTextEdit() || pPV->GetLockedLayers().IsSet(pObj->GetLayer())) { + pObj=NULL; + } + } + if (pObj!=NULL && (nOptions & SDRSEARCH_TESTMACRO) !=0) { + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=aPt; + aHitRec.aDownPos=aPt; + aHitRec.nTol=nTol; + aHitRec.pVisiLayer=&pPV->GetVisibleLayers(); + aHitRec.pPageView=pPV; + if (!pObj->HasMacro() || !pObj->IsMacroHit(aHitRec)) pObj=NULL; + } + if (pObj!=NULL && (nOptions & SDRSEARCH_WITHTEXT) !=0 && pObj->GetOutlinerParaObject()==NULL) pObj=NULL; + if (pObj!=NULL && (nOptions & SDRSEARCH_TESTTEXTAREA) !=0) + { + if(!SdrObjectPrimitiveHit(*pObj, aPt, 0, *pPV, 0, true)) + { + pObj = 0; + } + } + if (pObj!=NULL) { + rpObj=pObj; + rpPV=pPV; + if (pnPassNum!=NULL) *pnPassNum|=SDRSEARCHPASS_DIRECT; + } + } + return rpObj!=NULL; +} + +BOOL SdrMarkView::PickMarkedObj(const Point& rPnt, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG* pnMarkNum, ULONG nOptions) const +{ + SortMarkedObjects(); + BOOL bBoundCheckOn2ndPass=(nOptions & SDRSEARCH_PASS2BOUND) !=0; + BOOL bCheckNearestOn3rdPass=(nOptions & SDRSEARCH_PASS3NEAREST) !=0; + rpObj=NULL; + rpPV=NULL; + if (pnMarkNum!=NULL) *pnMarkNum=CONTAINER_ENTRY_NOTFOUND; + Point aPt(rPnt); + USHORT nTol=(USHORT)nHitTolLog; + BOOL bFnd=FALSE; + ULONG nMarkAnz=GetMarkedObjectCount(); + ULONG nMarkNum; + for (nMarkNum=nMarkAnz; nMarkNum>0 && !bFnd;) { + nMarkNum--; + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrPageView* pPV=pM->GetPageView(); + SdrObject* pObj=pM->GetMarkedSdrObj(); + bFnd = 0 != CheckSingleSdrObjectHit(aPt,nTol,pObj,pPV,SDRSEARCH_TESTMARKABLE,0); + if (bFnd) { + rpObj=pObj; + rpPV=pPV; + if (pnMarkNum!=NULL) *pnMarkNum=nMarkNum; + } + } + if ((bBoundCheckOn2ndPass || bCheckNearestOn3rdPass) && !bFnd) { + SdrObject* pBestObj=NULL; + SdrPageView* pBestPV=NULL; + ULONG nBestMarkNum=0; + ULONG nBestDist=ULONG_MAX; + for (nMarkNum=nMarkAnz; nMarkNum>0 && !bFnd;) { + nMarkNum--; + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrPageView* pPV=pM->GetPageView(); + SdrObject* pObj=pM->GetMarkedSdrObj(); + Rectangle aRect(pObj->GetCurrentBoundRect()); + aRect.Left ()-=nTol; + aRect.Top ()-=nTol; + aRect.Right ()+=nTol; + aRect.Bottom()+=nTol; + if (aRect.IsInside(aPt)) { + bFnd=TRUE; + rpObj=pObj; + rpPV=pPV; + if (pnMarkNum!=NULL) *pnMarkNum=nMarkNum; + } else if (bCheckNearestOn3rdPass) { + ULONG nDist=0; + if (aPt.X()<aRect.Left()) nDist+=aRect.Left()-aPt.X(); + if (aPt.X()>aRect.Right()) nDist+=aPt.X()-aRect.Right(); + if (aPt.Y()<aRect.Top()) nDist+=aRect.Top()-aPt.Y(); + if (aPt.Y()>aRect.Bottom()) nDist+=aPt.Y()-aRect.Bottom(); + if (nDist<nBestDist) { + pBestObj=pObj; + pBestPV=pPV; + nBestMarkNum=nMarkNum; + } + } + } + if (bCheckNearestOn3rdPass && !bFnd) { + rpObj=pBestObj; + rpPV=pBestPV; + if (pnMarkNum!=NULL) *pnMarkNum=nBestMarkNum; + bFnd=pBestObj!=NULL; + } + } + return bFnd; +} + +SdrHitKind SdrMarkView::PickSomething(const Point& rPnt, short nTol) const +{ + nTol=ImpGetHitTolLogic(nTol,NULL); + SdrHitKind eRet=SDRHIT_NONE; + Point aPt(rPnt); + SdrObject* pObj=NULL; + SdrPageView* pPV=NULL; + if (eRet==SDRHIT_NONE && PickObj(rPnt,USHORT(nTol),pObj,pPV,SDRSEARCH_PICKMARKABLE)) { + Rectangle aRct1(aPt-Point(nTol,nTol),aPt+Point(nTol,nTol)); // HitRect fuer Toleranz + Rectangle aBR(pObj->GetCurrentBoundRect()); + if (aRct1.IsInside(aBR.TopLeft())) eRet=SDRHIT_BOUNDTL; + else if (aRct1.IsInside(aBR.TopCenter())) eRet=SDRHIT_BOUNDTC; + else if (aRct1.IsInside(aBR.TopRight())) eRet=SDRHIT_BOUNDTR; + else if (aRct1.IsInside(aBR.LeftCenter())) eRet=SDRHIT_BOUNDCL; + else if (aRct1.IsInside(aBR.RightCenter())) eRet=SDRHIT_BOUNDCR; + else if (aRct1.IsInside(aBR.BottomLeft())) eRet=SDRHIT_BOUNDBL; + else if (aRct1.IsInside(aBR.BottomCenter())) eRet=SDRHIT_BOUNDBC; + else if (aRct1.IsInside(aBR.BottomRight())) eRet=SDRHIT_BOUNDBR; + else eRet=SDRHIT_OBJECT; + } + return eRet; +} + +void SdrMarkView::UnmarkAllObj(SdrPageView* pPV) +{ + if (GetMarkedObjectCount()!=0) { + BrkAction(); + //HMHBOOL bVis=bHdlShown; + //HMHif (bVis) HideMarkHdl(); + if (pPV!=NULL) + { + GetMarkedObjectListWriteAccess().DeletePageView(*pPV); + } + else + { + GetMarkedObjectListWriteAccess().Clear(); + } + pMarkedObj=NULL; + pMarkedPV=NULL; + MarkListHasChanged(); + AdjustMarkHdl(); //HMHTRUE); + //HMHif (bVis) ShowMarkHdl(); // ggf. fuer die RefPoints + } +} + +void SdrMarkView::MarkAllObj(SdrPageView* _pPV) +{ + BrkAction(); + //HMHHideMarkHdl(); + + if(!_pPV) + { + _pPV = GetSdrPageView(); + } + + // #i69171# _pPV may still be NULL if there is no SDrPageView (!), e.g. when inserting + // other files + if(_pPV) + { + const bool bMarkChg(GetMarkedObjectListWriteAccess().InsertPageView(*_pPV)); + + if(bMarkChg) + { + MarkListHasChanged(); + } + } + + if(GetMarkedObjectCount()) + { + AdjustMarkHdl(); //HMHTRUE); + //HMHShowMarkHdl(); + } +} + +void SdrMarkView::AdjustMarkHdl() //HMHBOOL bRestraintPaint) +{ + //HMHBOOL bVis=bHdlShown; + //HMHif (bVis) HideMarkHdl(); + CheckMarked(); + SetMarkRects(); + SetMarkHandles(); + //HMHif(bRestraintPaint && bVis) + //HMH{ + //HMH ShowMarkHdl(); + //HMH} +} + +Rectangle SdrMarkView::GetMarkedObjBoundRect() const +{ + Rectangle aRect; + for (ULONG nm=0; nm<GetMarkedObjectCount(); nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + Rectangle aR1(pO->GetCurrentBoundRect()); + if (aRect.IsEmpty()) aRect=aR1; + else aRect.Union(aR1); + } + return aRect; +} + +const Rectangle& SdrMarkView::GetMarkedObjRect() const +{ + if (bMarkedObjRectDirty) { + ((SdrMarkView*)this)->bMarkedObjRectDirty=FALSE; + Rectangle aRect; + for (ULONG nm=0; nm<GetMarkedObjectCount(); nm++) { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + Rectangle aR1(pO->GetSnapRect()); + if (aRect.IsEmpty()) aRect=aR1; + else aRect.Union(aR1); + } + ((SdrMarkView*)this)->aMarkedObjRect=aRect; + } + return aMarkedObjRect; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkView::ImpTakeDescriptionStr(USHORT nStrCacheID, XubString& rStr, USHORT nVal, USHORT nOpt) const +{ + rStr = ImpGetResStr(nStrCacheID); + xub_StrLen nPos = rStr.SearchAscii("%1"); + + if(nPos != STRING_NOTFOUND) + { + rStr.Erase(nPos, 2); + + if(nOpt == IMPSDR_POINTSDESCRIPTION) + { + rStr.Insert(GetDescriptionOfMarkedPoints(), nPos); + } + else if(nOpt == IMPSDR_GLUEPOINTSDESCRIPTION) + { + rStr.Insert(GetDescriptionOfMarkedGluePoints(), nPos); + } + else + { + rStr.Insert(GetDescriptionOfMarkedObjects(), nPos); + } + } + + nPos = rStr.SearchAscii("%2"); + + if(nPos != STRING_NOTFOUND) + { + rStr.Erase(nPos, 2); + rStr.Insert(UniString::CreateFromInt32(nVal), nPos); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrMarkView::EnterMarkedGroup() +{ + BOOL bRet=FALSE; + // Es wird nur die erste gefundene Gruppe (also nur in einer PageView) geentert + // Weil PageView::EnterGroup ein AdjustMarkHdl ruft. + // Das muss ich per Flag mal unterbinden vvvvvvvv + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + BOOL bEnter=FALSE; + for (sal_uInt32 nm(GetMarkedObjectCount()); nm > 0 && !bEnter;) + { + nm--; + SdrMark* pM=GetSdrMarkByIndex(nm); + if (pM->GetPageView()==pPV) { + SdrObject* pObj=pM->GetMarkedSdrObj(); + if (pObj->IsGroupObject()) { + if (pPV->EnterGroup(pObj)) { + bRet=TRUE; + bEnter=TRUE; + } + } + } + } + } + return bRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkView::MarkListHasChanged() +{ + GetMarkedObjectListWriteAccess().SetNameDirty(); + SetEdgesOfMarkedNodesDirty(); // bEdgesOfMarkedNodesDirty=TRUE; + + bMarkedObjRectDirty=TRUE; + bMarkedPointsRectsDirty=TRUE; +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + BOOL bOneEdgeMarked=FALSE; + if (GetMarkedObjectCount()==1) { + const SdrObject* pObj=GetMarkedObjectByIndex(0); + if (pObj->GetObjInventor()==SdrInventor) { + UINT16 nIdent=pObj->GetObjIdentifier(); + bOneEdgeMarked=nIdent==OBJ_EDGE; + } + } + ImpSetGlueVisible4(bOneEdgeMarked); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkView::SetMoveOutside(BOOL bOn) +{ + aHdl.SetMoveOutside(bOn); +} + +BOOL SdrMarkView::IsMoveOutside() const +{ + return aHdl.IsMoveOutside(); +} + +void SdrMarkView::SetDesignMode( BOOL _bOn ) +{ + if ( bDesignMode != _bOn ) + { + bDesignMode = _bOn; + SdrPageView* pPageView = GetSdrPageView(); + if ( pPageView ) + pPageView->SetDesignMode( _bOn ); + } +} + +// MarkHandles Objektaenderung: +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// - Bei Notify mit HINT_OBJCHG (oder so) werden die Handles erstmal versteckt +// (wenn nicht schon wegen Dragging versteckt). +// - XorHdl: Bei ModelHasChanged() werden sie dann wieder angezeigt. +// - PaintEvents kommen nun durch. +// - Die XorHandles werden z.T. wieder uebermalt. +// - Xor: Nach dem Painten werden die Handles im (vom PaintHandler gerufenen) +// CompleteRedraw per ToggleShownXor bei gesetzter ClipRegion nochmal gemalt +// und damit ist alles in Butter. +// - ToggleShownXor macht bei SolidHdl nix weil bHdlShown=FALSE +// - Der AfterPaintTimer wird gestartet. +// - SolidHdl: Im AfterPaintHandler wird ShowMarkHdl gerufen. +// Da die Handles zu diesem Zeitpunkt nicht angezeigt sind wird: +// - SaveBackground durchgefuehrt. +// - DrawMarkHdl gerufen und bHdlShown gesetzt. +// +// MarkHandles bei sonstigem Invalidate: +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// In diesem Fall bekomme ich kein Notify und beim Aufruf des +// PaintHandlers->CompleteRedraw() sind auch die SolidHandles sichtbar. + diff --git a/svx/source/svdraw/svdmrkv1.cxx b/svx/source/svdraw/svdmrkv1.cxx new file mode 100644 index 000000000000..fe271c80534d --- /dev/null +++ b/svx/source/svdraw/svdmrkv1.cxx @@ -0,0 +1,724 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdmrkv.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdoedge.hxx> +#include "svdglob.hxx" +#include <svx/svdpagv.hxx> +#include <svx/svdpage.hxx> +#include "svddrgm1.hxx" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@ @@ @@ @@ @@ @@ @@ @@@@@@ @@ @@ @@@@ @@@@@ @@ @@ @@ @@@@@ @@@@@ @@ @@ @@ @@ @@@@ +// @@ @@ @@ @@ @@@ @@ @@ @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@ +// @@ @@ @@ @@ @@@@@@ @@ @@ @@ @@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@@ @@ +// @@@@@ @@ @@ @@@@@@ @@@@ @@ @@@@@@@ @@@@@@ @@@@@ @@@@ @@ @@@@ @@@@@ @@ @@ @@@@@@ @@ @@@ +// @@ @@ @@ @@ @@@ @@ @@ @@ @@ @ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@ @@ @@ @@@@ @@ @@ @@@@@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrMarkView::HasMarkablePoints() const +{ + ForceUndirtyMrkPnt(); + bool bRet=false; + if (!ImpIsFrameHandles()) { + ULONG nMarkAnz=GetMarkedObjectCount(); + if (nMarkAnz<=nFrameHandlesLimit) { + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz && !bRet; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + bRet=pObj->IsPolyObj(); + } + } + } + return bRet; +} + +ULONG SdrMarkView::GetMarkablePointCount() const +{ + ForceUndirtyMrkPnt(); + ULONG nAnz=0; + if (!ImpIsFrameHandles()) { + ULONG nMarkAnz=GetMarkedObjectCount(); + if (nMarkAnz<=nFrameHandlesLimit) { + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + if (pObj->IsPolyObj()) { + nAnz+=pObj->GetPointCount(); + } + } + } + } + return nAnz; +} + +BOOL SdrMarkView::HasMarkedPoints() const +{ + ForceUndirtyMrkPnt(); + BOOL bRet=FALSE; + if (!ImpIsFrameHandles()) { + ULONG nMarkAnz=GetMarkedObjectCount(); + if (nMarkAnz<=nFrameHandlesLimit) { + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz && !bRet; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrUShortCont* pPts=pM->GetMarkedPoints(); + bRet=pPts!=NULL && pPts->GetCount()!=0; + } + } + } + return bRet; +} + +ULONG SdrMarkView::GetMarkedPointCount() const +{ + ForceUndirtyMrkPnt(); + ULONG nAnz=0; + if (!ImpIsFrameHandles()) { + ULONG nMarkAnz=GetMarkedObjectCount(); + if (nMarkAnz<=nFrameHandlesLimit) { + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrUShortCont* pPts=pM->GetMarkedPoints(); + if (pPts!=NULL) nAnz+=pPts->GetCount(); + } + } + } + return nAnz; +} + +BOOL SdrMarkView::IsPointMarkable(const SdrHdl& rHdl) const +{ + return !ImpIsFrameHandles() && &rHdl!=NULL && !rHdl.IsPlusHdl() && rHdl.GetKind()!=HDL_GLUE && rHdl.GetKind()!=HDL_SMARTTAG && rHdl.GetObj()!=NULL && rHdl.GetObj()->IsPolyObj(); +} + +BOOL SdrMarkView::MarkPointHelper(SdrHdl* pHdl, SdrMark* pMark, BOOL bUnmark) +{ + return ImpMarkPoint( pHdl, pMark, bUnmark ); +} + +BOOL SdrMarkView::ImpMarkPoint(SdrHdl* pHdl, SdrMark* pMark, BOOL bUnmark) +{ + if (pHdl==NULL || pHdl->IsPlusHdl() || pHdl->GetKind()==HDL_GLUE) + return FALSE; + + if (pHdl->IsSelected() != bUnmark) + return FALSE; + + SdrObject* pObj=pHdl->GetObj(); + if (pObj==NULL || !pObj->IsPolyObj()) + return FALSE; + + if (pMark==NULL) + { + ULONG nMarkNum=TryToFindMarkedObject(pObj); + if (nMarkNum==CONTAINER_ENTRY_NOTFOUND) + return FALSE; + pMark=GetSdrMarkByIndex(nMarkNum); + } + const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); + SdrUShortCont* pPts=pMark->ForceMarkedPoints(); + if (!bUnmark) + { + pPts->Insert((sal_uInt16)nHdlNum); + } + else + { + ULONG nBla=pPts->GetPos((sal_uInt16)nHdlNum); + if (nBla!=CONTAINER_ENTRY_NOTFOUND) + { + pPts->Remove(nBla); + } + else + { + return FALSE; // Fehlerfall! + } + } + + pHdl->SetSelected(!bUnmark); + if (!bPlusHdlAlways) + { + if (!bUnmark) + { + sal_uInt32 nAnz(pObj->GetPlusHdlCount(*pHdl)); + for (sal_uInt32 i=0; i<nAnz; i++) + { + SdrHdl* pPlusHdl=pObj->GetPlusHdl(*pHdl,i); + if (pPlusHdl!=NULL) + { + pPlusHdl->SetObj(pObj); + pPlusHdl->SetPageView(pMark->GetPageView()); + pPlusHdl->SetPlusHdl(TRUE); + aHdl.AddHdl(pPlusHdl); + } + } + } + else + { + for (ULONG i = aHdl.GetHdlCount(); i>0;) + { + i--; + SdrHdl* pPlusHdl=aHdl.GetHdl(i); + if (pPlusHdl->IsPlusHdl() && pPlusHdl->GetSourceHdlNum()==nHdlNum) + { + aHdl.RemoveHdl(i); + delete pPlusHdl; + } + } + } + } + + // #97016# II: Sort handles. This was missing in ImpMarkPoint all the time. + aHdl.Sort(); + + return TRUE; +} + + +BOOL SdrMarkView::MarkPoint(SdrHdl& rHdl, BOOL bUnmark) +{ + if (&rHdl==NULL) return FALSE; + ForceUndirtyMrkPnt(); + BOOL bRet=FALSE; + const SdrObject* pObj=rHdl.GetObj(); + if (IsPointMarkable(rHdl) && rHdl.IsSelected()==bUnmark) { + ULONG nMarkNum=TryToFindMarkedObject(pObj); + if (nMarkNum!=CONTAINER_ENTRY_NOTFOUND) { + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrUShortCont* pPts=pM->ForceMarkedPoints(); + pPts->ForceSort(); + if (ImpMarkPoint(&rHdl,pM,bUnmark)) { + pPts->ForceSort(); + MarkListHasChanged(); + bRet=TRUE; + } + } + } + + return bRet; +} + +BOOL SdrMarkView::MarkPoints(const Rectangle* pRect, BOOL bUnmark) +{ + ForceUndirtyMrkPnt(); + BOOL bChgd=FALSE; + SortMarkedObjects(); + const SdrObject* pObj0=NULL; + const SdrPageView* pPV0=NULL; + SdrMark* pM=NULL; + aHdl.Sort(); + //HMHBOOL bHideHdl=IsMarkHdlShown() && IsSolidMarkHdl() && !bPlusHdlAlways; + ULONG nHdlAnz=aHdl.GetHdlCount(); + for (ULONG nHdlNum=nHdlAnz; nHdlNum>0;) { + nHdlNum--; + SdrHdl* pHdl=aHdl.GetHdl(nHdlNum); + if (IsPointMarkable(*pHdl) && pHdl->IsSelected()==bUnmark) { + const SdrObject* pObj=pHdl->GetObj(); + const SdrPageView* pPV=pHdl->GetPageView(); + if (pObj!=pObj0 || pPV!=pPV0 || pM==NULL) { // Dieser Abschnitt dient zur Optimierung, + if (pM!=NULL) { + SdrUShortCont* pPts=pM->GetMarkedPoints(); + if (pPts!=NULL) pPts->ForceSort(); + } + ULONG nMarkNum=TryToFindMarkedObject(pObj); // damit ImpMarkPoint() nicht staendig das + if (nMarkNum!=CONTAINER_ENTRY_NOTFOUND) { // Objekt in der MarkList suchen muss. + pM=GetSdrMarkByIndex(nMarkNum); + pObj0=pObj; + pPV0=pPV; + SdrUShortCont* pPts=pM->ForceMarkedPoints(); + pPts->ForceSort(); + } else { +#ifdef DBG_UTIL + if (pObj->IsInserted()) { + DBG_ERROR("SdrMarkView::MarkPoints(const Rectangle* pRect): Markiertes Objekt nicht gefunden"); + } +#endif + pM=NULL; + } + } + Point aPos(pHdl->GetPos()); + if (pM!=NULL && (pRect==NULL || pRect->IsInside(aPos))) { + //HMHif (bHideHdl && IsMarkHdlShown() && pHdl->GetObj()!=NULL) { + //HMHsal_uInt32 nAnz=pHdl->GetObj()->GetPlusHdlCount(*pHdl); + //HMHif (nAnz!=0L) HideMarkHdl(); // #36987# + //HMH} + if (ImpMarkPoint(pHdl,pM,bUnmark)) bChgd=TRUE; + } + } + } + if (pM!=NULL) { // Den zuletzt geaenderten MarkEntry ggf. noch aufraeumen + SdrUShortCont* pPts=pM->GetMarkedPoints(); + if (pPts!=NULL) pPts->ForceSort(); + } + //HMHif (bHideHdl) ShowMarkHdl(); // #36987# + if (bChgd) { + MarkListHasChanged(); + } + + return bChgd; +} + +BOOL SdrMarkView::MarkNextPoint(BOOL /*bPrev*/) +{ + ForceUndirtyMrkPnt(); + BOOL bChgd=FALSE; + SortMarkedObjects(); + // ... + if (bChgd) { + MarkListHasChanged(); + } + return bChgd; +} + +BOOL SdrMarkView::MarkNextPoint(const Point& /*rPnt*/, BOOL /*bPrev*/) +{ + ForceUndirtyMrkPnt(); + BOOL bChgd=FALSE; + SortMarkedObjects(); + // ... + if (bChgd) { + MarkListHasChanged(); + } + return bChgd; +} + +const Rectangle& SdrMarkView::GetMarkedPointsRect() const +{ + ForceUndirtyMrkPnt(); + if (bMarkedPointsRectsDirty) ImpSetPointsRects(); + return aMarkedPointsRect; +} + +void SdrMarkView::SetPlusHandlesAlwaysVisible(BOOL bOn) +{ // HandlePaint optimieren !!!!!!! + ForceUndirtyMrkPnt(); + if (bOn!=bPlusHdlAlways) { + //HMHBOOL bVis=IsMarkHdlShown(); + //HMHif (bVis) HideMarkHdl(); + bPlusHdlAlways=bOn; + SetMarkHandles(); + //HMHif (bVis) ShowMarkHdl(); + MarkListHasChanged(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// ImpSetPointsRects() ist fuer PolyPoints und GluePoints! +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkView::ImpSetPointsRects() const +{ + Rectangle aPnts; + Rectangle aGlue; + ULONG nHdlAnz=aHdl.GetHdlCount(); + for (ULONG nHdlNum=0; nHdlNum<nHdlAnz; nHdlNum++) { + const SdrHdl* pHdl=aHdl.GetHdl(nHdlNum); + SdrHdlKind eKind=pHdl->GetKind(); + if ((eKind==HDL_POLY && pHdl->IsSelected()) || eKind==HDL_GLUE) { + Point aPt(pHdl->GetPos()); + Rectangle& rR=eKind==HDL_GLUE ? aGlue : aPnts; + if (rR.IsEmpty()) { + rR=Rectangle(aPt,aPt); + } else { + if (aPt.X()<rR.Left ()) rR.Left ()=aPt.X(); + if (aPt.X()>rR.Right ()) rR.Right ()=aPt.X(); + if (aPt.Y()<rR.Top ()) rR.Top ()=aPt.Y(); + if (aPt.Y()>rR.Bottom()) rR.Bottom()=aPt.Y(); + } + } + } + ((SdrMarkView*)this)->aMarkedPointsRect=aPnts; + ((SdrMarkView*)this)->aMarkedGluePointsRect=aGlue; + ((SdrMarkView*)this)->bMarkedPointsRectsDirty=FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// UndirtyMrkPnt() ist fuer PolyPoints und GluePoints! +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrMarkView::UndirtyMrkPnt() const +{ + BOOL bChg=FALSE; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) { + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + // PolyPoints + SdrUShortCont* pPts=pM->GetMarkedPoints(); + if (pPts!=NULL) { + if (pObj->IsPolyObj()) { + // Ungueltig markierte Punkte entfernen, also alle + // Eintraege die groesser sind als die Punktanzahl des Objekts + sal_uInt32 nMax(pObj->GetPointCount()); + sal_uInt32 nPtNum(0xffffffff); + + pPts->ForceSort(); + + for (sal_uInt32 nIndex(pPts->GetCount()); nIndex > 0L && nPtNum >= nMax;) + { + nIndex--; + nPtNum = pPts->GetObject(nIndex); + + if(nPtNum >= nMax) + { + pPts->Remove(nIndex); + bChg = TRUE; + } + } + } + else + { + DBG_ERROR("SdrMarkView::UndirtyMrkPnt(): Markierte Punkte an einem Objekt, dass kein PolyObj ist!"); + if(pPts && pPts->GetCount()) + { + pPts->Clear(); + bChg = TRUE; + } + } + } + + // GluePoints + pPts=pM->GetMarkedGluePoints(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + if (pPts!=NULL) { + if (pGPL!=NULL) { + // Ungueltig markierte Klebepunkte entfernen, also alle + // Eintraege (Id's) die nicht in der GluePointList des + // Objekts enthalten sind + pPts->ForceSort(); + for (ULONG nIndex=pPts->GetCount(); nIndex>0;) { + nIndex--; + USHORT nId=pPts->GetObject(nIndex); + if (pGPL->FindGluePoint(nId)==SDRGLUEPOINT_NOTFOUND) { + pPts->Remove(nIndex); + bChg=TRUE; + } + } + } else { + if (pPts!=NULL && pPts->GetCount()!=0) { + pPts->Clear(); // Objekt hat keine Klebepunkte (mehr) + bChg=TRUE; + } + } + } + } + if (bChg) ((SdrMarkView*)this)->bMarkedPointsRectsDirty=TRUE; + ((SdrMarkView*)this)->bMrkPntDirty=FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrMarkView::HasMarkableGluePoints() const +{ + BOOL bRet=FALSE; + if (IsGluePointEditMode()) { + ForceUndirtyMrkPnt(); + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz && !bRet; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + + // #i38892# + if(pGPL && pGPL->GetCount()) + { + for(sal_uInt16 a(0); !bRet && a < pGPL->GetCount(); a++) + { + if((*pGPL)[a].IsUserDefined()) + { + bRet = TRUE; + } + } + } + } + } + return bRet; +} + +ULONG SdrMarkView::GetMarkableGluePointCount() const +{ + ULONG nAnz=0; + if (IsGluePointEditMode()) { + ForceUndirtyMrkPnt(); + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + + // #i38892# + if(pGPL && pGPL->GetCount()) + { + for(sal_uInt16 a(0); a < pGPL->GetCount(); a++) + { + if((*pGPL)[a].IsUserDefined()) + { + nAnz++; + } + } + } + } + } + return nAnz; +} + +BOOL SdrMarkView::HasMarkedGluePoints() const +{ + ForceUndirtyMrkPnt(); + BOOL bRet=FALSE; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz && !bRet; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + bRet=pPts!=NULL && pPts->GetCount()!=0; + } + return bRet; +} + +ULONG SdrMarkView::GetMarkedGluePointCount() const +{ + ForceUndirtyMrkPnt(); + ULONG nAnz=0; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + if (pPts!=NULL) nAnz+=pPts->GetCount(); + } + return nAnz; +} + +BOOL SdrMarkView::MarkGluePoints(const Rectangle* pRect, BOOL bUnmark) +{ + if (!IsGluePointEditMode() && !bUnmark) return FALSE; + ForceUndirtyMrkPnt(); + BOOL bChgd=FALSE; + SortMarkedObjects(); + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) { + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + if (bUnmark && pRect==NULL) { // UnmarkAll + if (pPts!=NULL && pPts->GetCount()!=0) { + pPts->Clear(); + bChgd=TRUE; + } + } else { + if (pGPL!=NULL && (pPts!=NULL || !bUnmark)) { + USHORT nGPAnz=pGPL->GetCount(); + for (USHORT nGPNum=0; nGPNum<nGPAnz; nGPNum++) { + const SdrGluePoint& rGP=(*pGPL)[nGPNum]; + + // #i38892# + if(rGP.IsUserDefined()) + { + Point aPos(rGP.GetAbsolutePos(*pObj)); + if (pRect==NULL || pRect->IsInside(aPos)) { + if (pPts==NULL) pPts=pM->ForceMarkedGluePoints(); + else pPts->ForceSort(); + ULONG nPos=pPts->GetPos(rGP.GetId()); + if (!bUnmark && nPos==CONTAINER_ENTRY_NOTFOUND) { + bChgd=TRUE; + pPts->Insert(rGP.GetId()); + } + if (bUnmark && nPos!=CONTAINER_ENTRY_NOTFOUND) { + bChgd=TRUE; + pPts->Remove(nPos); + } + } + } + } + } + } + } + if (bChgd) { + AdjustMarkHdl(); + MarkListHasChanged(); + } + return bChgd; +} + +BOOL SdrMarkView::PickGluePoint(const Point& rPnt, SdrObject*& rpObj, USHORT& rnId, SdrPageView*& rpPV, ULONG nOptions) const +{ + SdrObject* pObj0=rpObj; + //SdrPageView* pPV0=rpPV; + USHORT nId0=rnId; + rpObj=NULL; rpPV=NULL; rnId=0; + if (!IsGluePointEditMode()) return FALSE; + BOOL bBack=(nOptions & SDRSEARCH_BACKWARD) !=0; + BOOL bNext=(nOptions & SDRSEARCH_NEXT) !=0; + OutputDevice* pOut=(OutputDevice*)pActualOutDev; + if (pOut==NULL) pOut=GetFirstOutputDevice(); //GetWin(0); + if (pOut==NULL) return FALSE; + SortMarkedObjects(); + ULONG nMarkAnz=GetMarkedObjectCount(); + ULONG nMarkNum=bBack ? 0 : nMarkAnz; + if (bNext) { + nMarkNum=((SdrMarkView*)this)->TryToFindMarkedObject(pObj0); + if (nMarkNum==CONTAINER_ENTRY_NOTFOUND) return FALSE; + if (!bBack) nMarkNum++; + } + while (bBack ? nMarkNum<nMarkAnz : nMarkNum>0) { + if (!bBack) nMarkNum--; + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrPageView* pPV=pM->GetPageView(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + if (pGPL!=NULL) { + USHORT nNum=pGPL->HitTest(rPnt,*pOut,pObj,bBack,bNext,nId0); + if (nNum!=SDRGLUEPOINT_NOTFOUND) + { + // #i38892# + const SdrGluePoint& rCandidate = (*pGPL)[nNum]; + + if(rCandidate.IsUserDefined()) + { + rpObj=pObj; + rnId=(*pGPL)[nNum].GetId(); + rpPV=pPV; + return TRUE; + } + } + } + bNext=FALSE; // HitNextGluePoint nur beim ersten Obj + if (bBack) nMarkNum++; + } + return FALSE; +} + +BOOL SdrMarkView::MarkGluePoint(const SdrObject* pObj, USHORT nId, const SdrPageView* /*pPV*/, BOOL bUnmark) +{ + if (!IsGluePointEditMode()) return FALSE; + ForceUndirtyMrkPnt(); + BOOL bChgd=FALSE; + if (pObj!=NULL) { + ULONG nMarkPos=TryToFindMarkedObject(pObj); + if (nMarkPos!=CONTAINER_ENTRY_NOTFOUND) { + SdrMark* pM=GetSdrMarkByIndex(nMarkPos); + SdrUShortCont* pPts=bUnmark ? pM->GetMarkedGluePoints() : pM->ForceMarkedGluePoints(); + if (pPts!=NULL) { + ULONG nPointPos=pPts->GetPos(nId); + if (!bUnmark && nPointPos==CONTAINER_ENTRY_NOTFOUND) { + bChgd=TRUE; + pPts->Insert(nId); + } + if (bUnmark && nPointPos!=CONTAINER_ENTRY_NOTFOUND) { + bChgd=TRUE; + pPts->Remove(nPointPos); + } + } + } else { + // Objekt implizit markieren ... + // ... fehlende Implementation + } + } + if (bChgd) { + AdjustMarkHdl(); + MarkListHasChanged(); + } + return bChgd; +} + +BOOL SdrMarkView::IsGluePointMarked(const SdrObject* pObj, USHORT nId) const +{ + ForceUndirtyMrkPnt(); + BOOL bRet=FALSE; + ULONG nPos=((SdrMarkView*)this)->TryToFindMarkedObject(pObj); // casting auf NonConst + if (nPos!=CONTAINER_ENTRY_NOTFOUND) { + const SdrMark* pM=GetSdrMarkByIndex(nPos); + const SdrUShortCont* pPts=pM->GetMarkedGluePoints(); + if (pPts!=NULL) { + bRet=pPts->Exist(nId); + } + } + return bRet; +} + +BOOL SdrMarkView::UnmarkGluePoint(const SdrHdl& rHdl) +{ + if (&rHdl!=NULL && rHdl.GetKind()==HDL_GLUE && rHdl.GetObj()!=NULL) { + return MarkGluePoint(rHdl.GetObj(),(sal_uInt16)rHdl.GetObjHdlNum(),rHdl.GetPageView(),TRUE); + } else return FALSE; +} + +SdrHdl* SdrMarkView::GetGluePointHdl(const SdrObject* pObj, USHORT nId) const +{ + ForceUndirtyMrkPnt(); + ULONG nHdlAnz=aHdl.GetHdlCount(); + for (ULONG nHdlNum=0; nHdlNum<nHdlAnz; nHdlNum++) { + SdrHdl* pHdl=aHdl.GetHdl(nHdlNum); + if (pHdl->GetObj()==pObj && + pHdl->GetKind()==HDL_GLUE && + pHdl->GetObjHdlNum()==nId ) return pHdl; + } + return NULL; +} + +BOOL SdrMarkView::MarkNextGluePoint(BOOL /*bPrev*/) +{ + ForceUndirtyMrkPnt(); + BOOL bChgd=FALSE; + SortMarkedObjects(); + // ... + if (bChgd) { + MarkListHasChanged(); + } + return bChgd; +} + +BOOL SdrMarkView::MarkNextGluePoint(const Point& /*rPnt*/, BOOL /*bPrev*/) +{ + ForceUndirtyMrkPnt(); + BOOL bChgd=FALSE; + SortMarkedObjects(); + // ... + if (bChgd) { + MarkListHasChanged(); + } + return bChgd; +} + +const Rectangle& SdrMarkView::GetMarkedGluePointsRect() const +{ + ForceUndirtyMrkPnt(); + if (bMarkedPointsRectsDirty) ImpSetPointsRects(); + return aMarkedGluePointsRect; +} + diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx new file mode 100644 index 000000000000..6ab27c85aaf0 --- /dev/null +++ b/svx/source/svdraw/svdoashp.cxx @@ -0,0 +1,3504 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/svdoashp.hxx> +#include "unoapi.hxx" +#include <svx/unoshape.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/datetime.hxx> +#include <sfx2/lnkbase.hxx> +#include <tools/urlobj.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/drawing/XCustomShapeEngine.hpp> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include "unopolyhelper.hxx" +#include <comphelper/processfactory.hxx> +#include <svl/urihelper.hxx> +#include <com/sun/star/uno/Sequence.h> +#include <svx/svdogrp.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <svx/svddrag.hxx> +#include <svx/xpool.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include "svditer.hxx" +#include <svx/svdobj.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdattrx.hxx> // NotPersistItems +#include <svx/svdoedge.hxx> // #32383# Die Verbinder nach Move nochmal anbroadcasten +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname +#include <editeng/eeitem.hxx> +#include "editeng/editstat.hxx" +#include <svx/svdoutl.hxx> +#include <editeng/outlobj.hxx> +#include <svx/sdtfchim.hxx> +#include "../customshapes/EnhancedCustomShapeGeometry.hxx" +#include "../customshapes/EnhancedCustomShapeTypeNames.hxx" +#include "../customshapes/EnhancedCustomShape2d.hxx" +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> +#include <editeng/writingmodeitem.hxx> +#include <svx/xlnclit.hxx> +#include <svx/svxids.hrc> +#include <svl/whiter.hxx> +#include <svx/sdr/properties/customshapeproperties.hxx> +#include <svx/sdr/contact/viewcontactofsdrobjcustomshape.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <vcl/bmpacc.hxx> +#include <svx/svdview.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +// #104018# replace macros above with type-safe methods +inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } +inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::drawing; + +static MSO_SPT ImpGetCustomShapeType( const SdrObjCustomShape& rCustoShape ) +{ + MSO_SPT eRetValue = mso_sptNil; + + rtl::OUString aEngine( ( (SdrCustomShapeEngineItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ) ).GetValue() ); + if ( !aEngine.getLength() || aEngine.equalsAscii( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) ) + { + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + Any* pAny = rGeometryItem.GetPropertyValueByName( sType ); + if ( pAny && ( *pAny >>= sShapeType ) ) + eRetValue = EnhancedCustomShapeTypeNames::Get( sShapeType ); + } + return eRetValue; +}; + +static sal_Bool ImpVerticalSwitch( const SdrObjCustomShape& rCustoShape ) +{ + sal_Bool bRet = sal_False; + MSO_SPT eShapeType( ImpGetCustomShapeType( rCustoShape ) ); + switch( eShapeType ) + { + case mso_sptAccentBorderCallout90 : // 2 ortho + case mso_sptBorderCallout1 : // 2 diag + case mso_sptBorderCallout2 : // 3 + { + bRet = sal_True; + } + break; +/* + case mso_sptCallout1 : + case mso_sptAccentCallout1 : + case mso_sptAccentBorderCallout1 : + case mso_sptBorderCallout90 : + case mso_sptCallout90 : + case mso_sptAccentCallout90 : + case mso_sptCallout2 : + case mso_sptCallout3 : + case mso_sptAccentCallout2 : + case mso_sptAccentCallout3 : + case mso_sptBorderCallout3 : + case mso_sptAccentBorderCallout2 : + case mso_sptAccentBorderCallout3 : +*/ + default: break; + } + return bRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i37011# create a clone with all attributes changed to shadow attributes +// and translation executed, too. +SdrObject* ImpCreateShadowObjectClone(const SdrObject& rOriginal, const SfxItemSet& rOriginalSet) +{ + SdrObject* pRetval = 0L; + const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get(SDRATTR_SHADOW)).GetValue()); + + if(bShadow) + { + // create a shadow representing object + const sal_Int32 nXDist(((SdrShadowXDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWXDIST))).GetValue()); + const sal_Int32 nYDist(((SdrShadowYDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWYDIST))).GetValue()); + const ::Color aShadowColor(((SdrShadowColorItem&)(rOriginalSet.Get(SDRATTR_SHADOWCOLOR))).GetColorValue()); + const sal_uInt16 nShadowTransparence(((SdrShadowTransparenceItem&)(rOriginalSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue()); + pRetval = rOriginal.Clone(); + DBG_ASSERT(pRetval, "ImpCreateShadowObjectClone: Could not clone object (!)"); + + // look for used stuff + SdrObjListIter aIterator(rOriginal); + sal_Bool bLineUsed(sal_False); + sal_Bool bAllFillUsed(sal_False); + sal_Bool bSolidFillUsed(sal_False); + sal_Bool bGradientFillUsed(sal_False); + sal_Bool bHatchFillUsed(sal_False); + sal_Bool bBitmapFillUsed(sal_False); + + while(aIterator.IsMore()) + { + SdrObject* pObj = aIterator.Next(); + XFillStyle eFillStyle = ((XFillStyleItem&)(pObj->GetMergedItem(XATTR_FILLSTYLE))).GetValue(); + + if(!bLineUsed) + { + XLineStyle eLineStyle = ((XLineStyleItem&)(pObj->GetMergedItem(XATTR_LINESTYLE))).GetValue(); + + if(XLINE_NONE != eLineStyle) + { + bLineUsed = sal_True; + } + } + + if(!bAllFillUsed) + { + if(!bSolidFillUsed && XFILL_SOLID == eFillStyle) + { + bSolidFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + if(!bGradientFillUsed && XFILL_GRADIENT == eFillStyle) + { + bGradientFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + if(!bHatchFillUsed && XFILL_HATCH == eFillStyle) + { + bHatchFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + if(!bBitmapFillUsed && XFILL_BITMAP == eFillStyle) + { + bBitmapFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + } + } + + // translate to shadow coordinates + pRetval->NbcMove(Size(nXDist, nYDist)); + + // set items as needed + SfxItemSet aTempSet(rOriginalSet); + + // SJ: #40108# :-( if a SvxWritingModeItem (Top->Bottom) is set the text object + // is creating a paraobject, but paraobjects can not be created without model. So + // we are preventing the crash by setting the writing mode always left to right, + // this is not bad since our shadow geometry does not contain text. + aTempSet.Put( SvxWritingModeItem( com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION ) ); + + // no shadow + aTempSet.Put(SdrShadowItem(sal_False)); + aTempSet.Put(SdrShadowXDistItem(0L)); + aTempSet.Put(SdrShadowYDistItem(0L)); + + // line color and transparence like shadow + if(bLineUsed) + { + aTempSet.Put(XLineColorItem(String(), aShadowColor)); + aTempSet.Put(XLineTransparenceItem(nShadowTransparence)); + } + + // fill color and transparence like shadow + if(bSolidFillUsed) + { + aTempSet.Put(XFillColorItem(String(), aShadowColor)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // gradient and transparence like shadow + if(bGradientFillUsed) + { + XGradient aGradient(((XFillGradientItem&)(rOriginalSet.Get(XATTR_FILLGRADIENT))).GetGradientValue()); + sal_uInt8 nStartLuminance(aGradient.GetStartColor().GetLuminance()); + sal_uInt8 nEndLuminance(aGradient.GetEndColor().GetLuminance()); + + if(aGradient.GetStartIntens() != 100) + { + nStartLuminance = (sal_uInt8)(nStartLuminance * ((double)aGradient.GetStartIntens() / 100.0)); + } + + if(aGradient.GetEndIntens() != 100) + { + nEndLuminance = (sal_uInt8)(nEndLuminance * ((double)aGradient.GetEndIntens() / 100.0)); + } + + ::Color aStartColor( + (sal_uInt8)((nStartLuminance * aShadowColor.GetRed()) / 256), + (sal_uInt8)((nStartLuminance * aShadowColor.GetGreen()) / 256), + (sal_uInt8)((nStartLuminance * aShadowColor.GetBlue()) / 256)); + + ::Color aEndColor( + (sal_uInt8)((nEndLuminance * aShadowColor.GetRed()) / 256), + (sal_uInt8)((nEndLuminance * aShadowColor.GetGreen()) / 256), + (sal_uInt8)((nEndLuminance * aShadowColor.GetBlue()) / 256)); + + aGradient.SetStartColor(aStartColor); + aGradient.SetEndColor(aEndColor); + aTempSet.Put(XFillGradientItem(aTempSet.GetPool(), aGradient)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // hatch and transparence like shadow + if(bHatchFillUsed) + { + XHatch aHatch(((XFillHatchItem&)(rOriginalSet.Get(XATTR_FILLHATCH))).GetHatchValue()); + aHatch.SetColor(aShadowColor); + aTempSet.Put(XFillHatchItem(aTempSet.GetPool(), aHatch)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // bitmap and transparence like shadow + if(bBitmapFillUsed) + { + XOBitmap aFillBitmap(((XFillBitmapItem&)(rOriginalSet.Get(XATTR_FILLBITMAP))).GetBitmapValue()); + Bitmap aSourceBitmap(aFillBitmap.GetBitmap()); + BitmapReadAccess* pReadAccess = aSourceBitmap.AcquireReadAccess(); + + if(!aSourceBitmap.IsEmpty()) + { + if(pReadAccess) + { + Bitmap aDestBitmap(aSourceBitmap.GetSizePixel(), 24L); + BitmapWriteAccess* pWriteAccess = aDestBitmap.AcquireWriteAccess(); + + if(pWriteAccess) + { + for(sal_Int32 y(0L); y < pReadAccess->Height(); y++) + { + for(sal_Int32 x(0L); x < pReadAccess->Width(); x++) + { + sal_uInt16 nLuminance((sal_uInt16)pReadAccess->GetLuminance(y, x) + 1); + const BitmapColor aDestColor( + (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetRed()) >> 8L), + (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetGreen()) >> 8L), + (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetBlue()) >> 8L)); + pWriteAccess->SetPixel(y, x, aDestColor); + } + } + + aDestBitmap.ReleaseAccess(pWriteAccess); + aFillBitmap.SetBitmap(aDestBitmap); + } + + aSourceBitmap.ReleaseAccess(pReadAccess); + } + } + + aTempSet.Put(XFillBitmapItem(aTempSet.GetPool(), aFillBitmap)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // set attributes and paint shadow object + pRetval->SetMergedItemSet( aTempSet ); + } + return pRetval; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Reference< XCustomShapeEngine > SdrObjCustomShape::GetCustomShapeEngine( const SdrObjCustomShape* pCustomShape ) +{ + Reference< XCustomShapeEngine > xCustomShapeEngine; + String aEngine(((SdrCustomShapeEngineItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE )).GetValue()); + if ( !aEngine.Len() ) + aEngine = String( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) ); + + Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + + Reference< XShape > aXShape = GetXShapeForSdrObject( (SdrObjCustomShape*)pCustomShape ); + if ( aXShape.is() ) + { + if ( aEngine.Len() && xFactory.is() ) + { + Sequence< Any > aArgument( 1 ); + Sequence< PropertyValue > aPropValues( 1 ); + aPropValues[ 0 ].Name = rtl::OUString::createFromAscii( "CustomShape" ); + aPropValues[ 0 ].Value <<= aXShape; + aArgument[ 0 ] <<= aPropValues; + Reference< XInterface > xInterface( xFactory->createInstanceWithArguments( aEngine, aArgument ) ); + if ( xInterface.is() ) + xCustomShapeEngine = Reference< XCustomShapeEngine >( xInterface, UNO_QUERY ); + } + } + return xCustomShapeEngine; +} +const SdrObject* SdrObjCustomShape::GetSdrObjectFromCustomShape() const +{ + if ( !mXRenderedCustomShape.is() ) + { + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( this ) ); + if ( xCustomShapeEngine.is() ) + ((SdrObjCustomShape*)this)->mXRenderedCustomShape = xCustomShapeEngine->render(); + } + SdrObject* pRenderedCustomShape = mXRenderedCustomShape.is() + ? GetSdrObjectFromXShape( mXRenderedCustomShape ) + : NULL; + return pRenderedCustomShape; +} + +// #i37011# Shadow geometry creation +const SdrObject* SdrObjCustomShape::GetSdrObjectShadowFromCustomShape() const +{ + if(!mpLastShadowGeometry) + { + const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); + if(pSdrObject) + { + const SfxItemSet& rOriginalSet = GetObjectItemSet(); + const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get( SDRATTR_SHADOW )).GetValue()); + + if(bShadow) + { + // create a clone with all attributes changed to shadow attributes + // and translation executed, too. + ((SdrObjCustomShape*)this)->mpLastShadowGeometry = ImpCreateShadowObjectClone(*pSdrObject, rOriginalSet); + } + } + } + + return mpLastShadowGeometry; +} + +sal_Bool SdrObjCustomShape::IsTextPath() const +{ + const rtl::OUString sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) ); + sal_Bool bTextPathOn = sal_False; + SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath ); + if ( pAny ) + *pAny >>= bTextPathOn; + return bTextPathOn; +} + +sal_Bool SdrObjCustomShape::UseNoFillStyle() const +{ + sal_Bool bRet = sal_False; + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + Any* pAny = rGeometryItem.GetPropertyValueByName( sType ); + if ( pAny ) + *pAny >>= sShapeType; + bRet = IsCustomShapeFilledByDefault( EnhancedCustomShapeTypeNames::Get( sType ) ) == 0; + + return bRet; +} + +sal_Bool SdrObjCustomShape::IsMirroredX() const +{ + sal_Bool bMirroredX = sal_False; + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX ); + if ( pAny ) + *pAny >>= bMirroredX; + return bMirroredX; +} +sal_Bool SdrObjCustomShape::IsMirroredY() const +{ + sal_Bool bMirroredY = sal_False; + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY ); + if ( pAny ) + *pAny >>= bMirroredY; + return bMirroredY; +} +void SdrObjCustomShape::SetMirroredX( const sal_Bool bMirrorX ) +{ + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + //com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX ); + PropertyValue aPropVal; + aPropVal.Name = sMirroredX; + aPropVal.Value <<= bMirrorX; + aGeometryItem.SetPropertyValue( aPropVal ); + SetMergedItem( aGeometryItem ); +} +void SdrObjCustomShape::SetMirroredY( const sal_Bool bMirrorY ) +{ + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + //com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY ); + PropertyValue aPropVal; + aPropVal.Name = sMirroredY; + aPropVal.Value <<= bMirrorY; + aGeometryItem.SetPropertyValue( aPropVal ); + SetMergedItem( aGeometryItem ); +} + +double SdrObjCustomShape::GetObjectRotation() const +{ + return fObjectRotation; +} + +double SdrObjCustomShape::GetExtraTextRotation() const +{ + const com::sun::star::uno::Any* pAny; + SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) ); + pAny = rGeometryItem.GetPropertyValueByName( sTextRotateAngle ); + double fExtraTextRotateAngle = 0.0; + if ( pAny ) + *pAny >>= fExtraTextRotateAngle; + return fExtraTextRotateAngle; +} +sal_Bool SdrObjCustomShape::GetTextBounds( Rectangle& rTextBound ) const +{ + sal_Bool bRet = sal_False; + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( this ) ); // a candidate for being cached + if ( xCustomShapeEngine.is() ) + { + awt::Rectangle aR( xCustomShapeEngine->getTextBounds() ); + if ( aR.Width || aR.Height ) + { + rTextBound = Rectangle( Point( aR.X, aR.Y ), Size( aR.Width, aR.Height ) ); + bRet = sal_True; + } + } + return bRet; +} +basegfx::B2DPolyPolygon SdrObjCustomShape::GetLineGeometry( const SdrObjCustomShape* pCustomShape, const sal_Bool bBezierAllowed ) +{ + basegfx::B2DPolyPolygon aRetval; + sal_Bool bRet = sal_False; + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( pCustomShape ) ); + if ( xCustomShapeEngine.is() ) + { + com::sun::star::drawing::PolyPolygonBezierCoords aBezierCoords = xCustomShapeEngine->getLineGeometry(); + try + { + aRetval = SvxConvertPolyPolygonBezierToB2DPolyPolygon( &aBezierCoords ); + if ( !bBezierAllowed && aRetval.areControlPointsUsed()) + { + aRetval = basegfx::tools::adaptiveSubdivideByAngle(aRetval); + } + bRet = sal_True; + } + catch ( const com::sun::star::lang::IllegalArgumentException ) + { + } + } + return aRetval; +} + +std::vector< SdrCustomShapeInteraction > SdrObjCustomShape::GetInteractionHandles( const SdrObjCustomShape* pCustomShape ) const +{ + std::vector< SdrCustomShapeInteraction > xRet; + try + { + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( pCustomShape ) ); + if ( xCustomShapeEngine.is() ) + { + int i; + Sequence< Reference< XCustomShapeHandle > > xInteractionHandles( xCustomShapeEngine->getInteraction() ); + for ( i = 0; i < xInteractionHandles.getLength(); i++ ) + { + if ( xInteractionHandles[ i ].is() ) + { + SdrCustomShapeInteraction aSdrCustomShapeInteraction; + aSdrCustomShapeInteraction.xInteraction = xInteractionHandles[ i ]; + aSdrCustomShapeInteraction.aPosition = xInteractionHandles[ i ]->getPosition(); + + sal_Int32 nMode = 0; + switch( ImpGetCustomShapeType( *this ) ) + { + case mso_sptAccentBorderCallout90 : // 2 ortho + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + else if ( i == 1) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE | CUSTOMSHAPE_HANDLE_ORTHO4; + } + break; + + case mso_sptWedgeRectCallout : + case mso_sptWedgeRRectCallout : + case mso_sptCloudCallout : + case mso_sptWedgeEllipseCallout : + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED; + } + break; + + case mso_sptBorderCallout1 : // 2 diag + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + else if ( i == 1 ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE; + } + break; + case mso_sptBorderCallout2 : // 3 + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + else if ( i == 2 ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE; + } + break; + case mso_sptCallout90 : + case mso_sptAccentCallout90 : + case mso_sptBorderCallout90 : + case mso_sptCallout1 : + case mso_sptCallout2 : + case mso_sptCallout3 : + case mso_sptAccentCallout1 : + case mso_sptAccentCallout2 : + case mso_sptAccentCallout3 : + case mso_sptBorderCallout3 : + case mso_sptAccentBorderCallout1 : + case mso_sptAccentBorderCallout2 : + case mso_sptAccentBorderCallout3 : + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + } + break; + default: break; + } + aSdrCustomShapeInteraction.nMode = nMode; + xRet.push_back( aSdrCustomShapeInteraction ); + } + } + } + } + catch( const uno::RuntimeException& ) + { + } + return xRet; +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section +#define DEFAULT_MINIMUM_SIGNED_COMPARE ((sal_Int32)0x80000000) +#define DEFAULT_MAXIMUM_SIGNED_COMPARE ((sal_Int32)0x7fffffff) + +sdr::properties::BaseProperties* SdrObjCustomShape::CreateObjectSpecificProperties() +{ + return new sdr::properties::CustomShapeProperties(*this); +} + +TYPEINIT1(SdrObjCustomShape,SdrTextObj); +SdrObjCustomShape::SdrObjCustomShape() : + SdrTextObj(), + fObjectRotation( 0.0 ), + mpLastShadowGeometry(0L) +{ + bTextFrame = TRUE; +} + +SdrObjCustomShape::~SdrObjCustomShape() +{ + // delete buffered display geometry + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::MergeDefaultAttributes( const rtl::OUString* pType ) +{ + PropertyValue aPropVal; + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + if ( pType && pType->getLength() ) + { + sal_Int32 nType = pType->toInt32(); + if ( nType ) + sShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >( nType ) ); + else + sShapeType = *pType; + + aPropVal.Name = sType; + aPropVal.Value <<= sShapeType; + aGeometryItem.SetPropertyValue( aPropVal ); + } + else + { + Any *pAny = aGeometryItem.GetPropertyValueByName( sType ); + if ( pAny ) + *pAny >>= sShapeType; + } + MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); + + const sal_Int32* pDefData = NULL; + const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType ); + if ( pDefCustomShape ) + pDefData = pDefCustomShape->pDefData; + + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues; + + ////////////////////// + // AdjustmentValues // + ////////////////////// + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + const Any* pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sAdjustmentValues ); + if ( pAny ) + *pAny >>= seqAdjustmentValues; + if ( pDefCustomShape && pDefData ) // now check if we have to default some adjustment values + { + // first check if there are adjustment values are to be appended + sal_Int32 i, nAdjustmentValues = seqAdjustmentValues.getLength(); + sal_Int32 nAdjustmentDefaults = *pDefData++; + if ( nAdjustmentDefaults > nAdjustmentValues ) + { + seqAdjustmentValues.realloc( nAdjustmentDefaults ); + for ( i = nAdjustmentValues; i < nAdjustmentDefaults; i++ ) + { + seqAdjustmentValues[ i ].Value <<= pDefData[ i ]; + seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE; // com::sun::star::beans::PropertyState_DEFAULT_VALUE; + } + } + // check if there are defaulted adjustment values that should be filled the hard coded defaults (pDefValue) + sal_Int32 nCount = nAdjustmentValues > nAdjustmentDefaults ? nAdjustmentDefaults : nAdjustmentValues; + for ( i = 0; i < nCount; i++ ) + { + if ( seqAdjustmentValues[ i ].State != com::sun::star::beans::PropertyState_DIRECT_VALUE ) + { + seqAdjustmentValues[ i ].Value <<= pDefData[ i ]; + seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE; + } + } + } + aPropVal.Name = sAdjustmentValues; + aPropVal.Value <<= seqAdjustmentValues; + aGeometryItem.SetPropertyValue( aPropVal ); + + /////////////// + // Coordsize // + /////////////// + const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) ); + const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox ); + com::sun::star::awt::Rectangle aViewBox; + if ( !pViewBox || !(*pViewBox >>= aViewBox ) ) + { + if ( pDefCustomShape ) + { + aViewBox.X = 0; + aViewBox.Y = 0; + aViewBox.Width = pDefCustomShape->nCoordWidth; + aViewBox.Height= pDefCustomShape->nCoordHeight; + aPropVal.Name = sViewBox; + aPropVal.Value <<= aViewBox; + aGeometryItem.SetPropertyValue( aPropVal ); + } + } + + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) ); + + ////////////////////// + // Path/Coordinates // + ////////////////////// + const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates; + + sal_Int32 i, nCount = pDefCustomShape->nVertices; + seqCoordinates.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].First, pDefCustomShape->pVertices[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].Second, pDefCustomShape->pVertices[ i ].nValB ); + } + aPropVal.Name = sCoordinates; + aPropVal.Value <<= seqCoordinates; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + ///////////////////// + // Path/GluePoints // + ///////////////////// + const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints; + sal_Int32 i, nCount = pDefCustomShape->nGluePoints; + seqGluePoints.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB ); + } + aPropVal.Name = sGluePoints; + aPropVal.Value <<= seqGluePoints; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + /////////////////// + // Path/Segments // + /////////////////// + const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments; + + sal_Int32 i, nCount = pDefCustomShape->nElements; + seqSegments.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShapeSegment& rSegInfo = seqSegments[ i ]; + sal_uInt16 nSDat = pDefCustomShape->pElements[ i ]; + switch( nSDat >> 8 ) + { + case 0x00 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x20 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x40 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x60 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; + rSegInfo.Count = 0; + } + break; + case 0x80 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH; + rSegInfo.Count = 0; + } + break; + case 0xa1 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa2 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa3 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa4 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa5 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa6 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa7 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xa8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xaa : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL; + rSegInfo.Count = 0; + } + break; + case 0xab : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE; + rSegInfo.Count = 0; + } + break; + default: + case 0xf8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN; + rSegInfo.Count = nSDat; + } + break; + } + } + aPropVal.Name = sSegments; + aPropVal.Value <<= seqSegments; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + /////////////////// + // Path/StretchX // + /////////////////// + const rtl::OUString sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX ); + if ( !pAny && pDefCustomShape ) + { + sal_Int32 nXRef = pDefCustomShape->nXRef; + if ( ( nXRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + { + aPropVal.Name = sStretchX; + aPropVal.Value <<= nXRef; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + } + + /////////////////// + // Path/StretchY // + /////////////////// + const rtl::OUString sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY ); + if ( !pAny && pDefCustomShape ) + { + sal_Int32 nYRef = pDefCustomShape->nYRef; + if ( ( nYRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + { + aPropVal.Name = sStretchY; + aPropVal.Value <<= nYRef; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + } + + ///////////////////// + // Path/TextFrames // + ///////////////////// + const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM ( "TextFrames" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames; + + sal_Int32 i, nCount = pDefCustomShape->nTextRect; + seqTextFrames.realloc( nCount ); + const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect; + for ( i = 0; i < nCount; i++, pRectangles++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.First, pRectangles->nPairA.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.Second, pRectangles->nPairA.nValB ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.First, pRectangles->nPairB.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.Second, pRectangles->nPairB.nValB ); + } + aPropVal.Name = sTextFrames; + aPropVal.Value <<= seqTextFrames; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + /////////////// + // Equations // + /////////////// + const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation ) + { + com::sun::star::uno::Sequence< rtl::OUString > seqEquations; + + sal_Int32 i, nCount = pDefCustomShape->nCalculation; + seqEquations.realloc( nCount ); + const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation; + for ( i = 0; i < nCount; i++, pData++ ) + seqEquations[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] ); + aPropVal.Name = sEquations; + aPropVal.Value <<= seqEquations; + aGeometryItem.SetPropertyValue( aPropVal ); + } + + ///////////// + // Handles // + ///////////// + const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles ) + { + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles; + + sal_Int32 i, n, nCount = pDefCustomShape->nHandles; + const SvxMSDffHandle* pData = pDefCustomShape->pHandles; + seqHandles.realloc( nCount ); + for ( i = 0; i < nCount; i++, pData++ ) + { + sal_Int32 nPropertiesNeeded = 1; // position is always needed + sal_Int32 nFlags = pData->nFlags; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + + n = 0; + com::sun::star::beans::PropertyValues& rPropValues = seqHandles[ i ]; + rPropValues.realloc( nPropertiesNeeded ); + + // POSITION + { + const rtl::OUString sPosition( RTL_CONSTASCII_USTRINGPARAM ( "Position" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, sal_True, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, sal_True, sal_False ); + rPropValues[ n ].Name = sPosition; + rPropValues[ n++ ].Value <<= aPosition; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + { + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + sal_Bool bMirroredX = sal_True; + rPropValues[ n ].Name = sMirroredX; + rPropValues[ n++ ].Value <<= bMirroredX; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + { + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + sal_Bool bMirroredY = sal_True; + rPropValues[ n ].Name = sMirroredY; + rPropValues[ n++ ].Value <<= bMirroredY; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + { + const rtl::OUString sSwitched( RTL_CONSTASCII_USTRINGPARAM ( "Switched" ) ); + sal_Bool bSwitched = sal_True; + rPropValues[ n ].Name = sSwitched; + rPropValues[ n++ ].Value <<= bSwitched; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + const rtl::OUString sPolar( RTL_CONSTASCII_USTRINGPARAM ( "Polar" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First, pData->nCenterX, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sPolar; + rPropValues[ n++ ].Value <<= aCenter; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRadiusRangeMinimum; + rPropValues[ n++ ].Value <<= aRadiusRangeMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRadiusRangeMaximum; + rPropValues[ n++ ].Value <<= aRadiusRangeMaximum; + } + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeXMinimum; + rPropValues[ n++ ].Value <<= aRangeXMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeXMaximum; + rPropValues[ n++ ].Value <<= aRangeXMaximum; + } + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeYMinimum; + rPropValues[ n++ ].Value <<= aRangeYMinimum; + } + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeYMaximum; + rPropValues[ n++ ].Value <<= aRangeYMaximum; + } + } + } + aPropVal.Name = sHandles; + aPropVal.Value <<= seqHandles; + aGeometryItem.SetPropertyValue( aPropVal ); + } + SetMergedItem( aGeometryItem ); +} + +sal_Bool SdrObjCustomShape::IsDefaultGeometry( const DefaultType eDefaultType ) const +{ + sal_Bool bIsDefaultGeometry = sal_False; + + PropertyValue aPropVal; + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + + Any *pAny = aGeometryItem.GetPropertyValueByName( sType ); + if ( pAny ) + *pAny >>= sShapeType; + + MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); + + const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType ); + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) ); + switch( eDefaultType ) + { + case DEFAULT_VIEWBOX : + { + const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) ); + const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox ); + com::sun::star::awt::Rectangle aViewBox; + if ( pViewBox && ( *pViewBox >>= aViewBox ) ) + { + if ( ( aViewBox.Width == pDefCustomShape->nCoordWidth ) + && ( aViewBox.Height == pDefCustomShape->nCoordHeight ) ) + bIsDefaultGeometry = sal_True; + } + } + break; + + case DEFAULT_PATH : + { + const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates ); + if ( pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2; + if ( *pAny >>= seqCoordinates1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nVertices; + seqCoordinates2.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].First, pDefCustomShape->pVertices[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].Second, pDefCustomShape->pVertices[ i ].nValB ); + } + if ( seqCoordinates1 == seqCoordinates2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nVertices == 0 ) || ( pDefCustomShape->pVertices == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_GLUEPOINTS : + { + const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints ); + if ( pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints1, seqGluePoints2; + if ( *pAny >>= seqGluePoints1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nGluePoints; + seqGluePoints2.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB ); + } + if ( seqGluePoints1 == seqGluePoints2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( pDefCustomShape->nGluePoints == 0 ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_SEGMENTS : + { + /////////////////// + // Path/Segments // + /////////////////// + const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments ); + if ( pAny ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments1, seqSegments2; + if ( *pAny >>= seqSegments1 ) + { + if ( pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements ) + { + sal_Int32 i, nCount = pDefCustomShape->nElements; + if ( nCount ) + { + seqSegments2.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShapeSegment& rSegInfo = seqSegments2[ i ]; + sal_uInt16 nSDat = pDefCustomShape->pElements[ i ]; + switch( nSDat >> 8 ) + { + case 0x00 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x20 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x40 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x60 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; + rSegInfo.Count = 0; + } + break; + case 0x80 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH; + rSegInfo.Count = 0; + } + break; + case 0xa1 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa2 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa3 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa4 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa5 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa6 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa7 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xa8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xaa : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL; + rSegInfo.Count = 0; + } + break; + case 0xab : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE; + rSegInfo.Count = 0; + } + break; + default: + case 0xf8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN; + rSegInfo.Count = nSDat; + } + break; + } + } + if ( seqSegments1 == seqSegments2 ) + bIsDefaultGeometry = sal_True; + } + } + else + { + // check if its the default segment description ( M L Z N ) + if ( seqSegments1.getLength() == 4 ) + { + if ( ( seqSegments1[ 0 ].Command == EnhancedCustomShapeSegmentCommand::MOVETO ) + && ( seqSegments1[ 1 ].Command == EnhancedCustomShapeSegmentCommand::LINETO ) + && ( seqSegments1[ 2 ].Command == EnhancedCustomShapeSegmentCommand::CLOSESUBPATH ) + && ( seqSegments1[ 3 ].Command == EnhancedCustomShapeSegmentCommand::ENDSUBPATH ) ) + bIsDefaultGeometry = sal_True; + } + } + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nElements == 0 ) || ( pDefCustomShape->pElements == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_STRETCHX : + { + const rtl::OUString sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX ); + if ( pAny && pDefCustomShape ) + { + sal_Int32 nStretchX = 0; + if ( *pAny >>= nStretchX ) + { + if ( pDefCustomShape->nXRef == nStretchX ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( pDefCustomShape->nXRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_STRETCHY : + { + const rtl::OUString sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY ); + if ( pAny && pDefCustomShape ) + { + sal_Int32 nStretchY = 0; + if ( *pAny >>= nStretchY ) + { + if ( pDefCustomShape->nYRef == nStretchY ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( pDefCustomShape->nYRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_EQUATIONS : + { + const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations ); + if ( pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation ) + { + com::sun::star::uno::Sequence< rtl::OUString > seqEquations1, seqEquations2; + if ( *pAny >>= seqEquations1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nCalculation; + seqEquations2.realloc( nCount ); + + const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation; + for ( i = 0; i < nCount; i++, pData++ ) + seqEquations2[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] ); + + if ( seqEquations1 == seqEquations2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nCalculation == 0 ) || ( pDefCustomShape->pCalculation == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_TEXTFRAMES : + { + const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames ); + if ( pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames1, seqTextFrames2; + if ( *pAny >>= seqTextFrames1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nTextRect; + seqTextFrames2.realloc( nCount ); + const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect; + for ( i = 0; i < nCount; i++, pRectangles++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.First, pRectangles->nPairA.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.Second, pRectangles->nPairA.nValB ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.First, pRectangles->nPairB.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.Second, pRectangles->nPairB.nValB ); + } + if ( seqTextFrames1 == seqTextFrames2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nTextRect == 0 ) || ( pDefCustomShape->pTextRect == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_HANDLES : + { + const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles ); + if ( pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles ) + { + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles1, seqHandles2; + if ( *pAny >>= seqHandles1 ) + { + sal_Int32 i, n, nCount = pDefCustomShape->nHandles; + const SvxMSDffHandle* pData = pDefCustomShape->pHandles; + seqHandles2.realloc( nCount ); + for ( i = 0; i < nCount; i++, pData++ ) + { + sal_Int32 nPropertiesNeeded = 1; // position is always needed + sal_Int32 nFlags = pData->nFlags; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + + n = 0; + com::sun::star::beans::PropertyValues& rPropValues = seqHandles2[ i ]; + rPropValues.realloc( nPropertiesNeeded ); + + // POSITION + { + const rtl::OUString sPosition( RTL_CONSTASCII_USTRINGPARAM ( "Position" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, sal_True, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, sal_True, sal_False ); + rPropValues[ n ].Name = sPosition; + rPropValues[ n++ ].Value <<= aPosition; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + { + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + sal_Bool bMirroredX = sal_True; + rPropValues[ n ].Name = sMirroredX; + rPropValues[ n++ ].Value <<= bMirroredX; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + { + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + sal_Bool bMirroredY = sal_True; + rPropValues[ n ].Name = sMirroredY; + rPropValues[ n++ ].Value <<= bMirroredY; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + { + const rtl::OUString sSwitched( RTL_CONSTASCII_USTRINGPARAM ( "Switched" ) ); + sal_Bool bSwitched = sal_True; + rPropValues[ n ].Name = sSwitched; + rPropValues[ n++ ].Value <<= bSwitched; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + const rtl::OUString sPolar( RTL_CONSTASCII_USTRINGPARAM ( "Polar" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First, pData->nCenterX, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sPolar; + rPropValues[ n++ ].Value <<= aCenter; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRadiusRangeMinimum; + rPropValues[ n++ ].Value <<= aRadiusRangeMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRadiusRangeMaximum; + rPropValues[ n++ ].Value <<= aRadiusRangeMaximum; + } + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeXMinimum; + rPropValues[ n++ ].Value <<= aRangeXMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeXMaximum; + rPropValues[ n++ ].Value <<= aRangeXMaximum; + } + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeYMinimum; + rPropValues[ n++ ].Value <<= aRangeYMinimum; + } + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeYMaximum; + rPropValues[ n++ ].Value <<= aRangeYMaximum; + } + } + } + if ( seqHandles1 == seqHandles2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nHandles == 0 ) || ( pDefCustomShape->pHandles == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + } + return bIsDefaultGeometry; +} + +void SdrObjCustomShape::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bResizeFreeAllowed=fObjectRotation == 0.0; + rInfo.bResizePropAllowed=TRUE; + rInfo.bRotateFreeAllowed=TRUE; + rInfo.bRotate90Allowed =TRUE; + rInfo.bMirrorFreeAllowed=TRUE; + rInfo.bMirror45Allowed =TRUE; + rInfo.bMirror90Allowed =TRUE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =TRUE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bNoContortion =TRUE; + + // #i37011# + if ( mXRenderedCustomShape.is() ) + { + const SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape ); + if ( pRenderedCustomShape ) + { + // #i37262# + // Iterate self over the contained objects, since there are combinations of + // polygon and curve objects. In that case, aInfo.bCanConvToPath and + // aInfo.bCanConvToPoly would be false. What is needed here is an or, not an and. + SdrObjListIter aIterator(*pRenderedCustomShape); + while(aIterator.IsMore()) + { + SdrObject* pCandidate = aIterator.Next(); + SdrObjTransformInfoRec aInfo; + pCandidate->TakeObjInfo(aInfo); + + // set path and poly conversion if one is possible since + // this object will first be broken + const sal_Bool bCanConvToPathOrPoly(aInfo.bCanConvToPath || aInfo.bCanConvToPoly); + if(rInfo.bCanConvToPath != bCanConvToPathOrPoly) + { + rInfo.bCanConvToPath = bCanConvToPathOrPoly; + } + + if(rInfo.bCanConvToPoly != bCanConvToPathOrPoly) + { + rInfo.bCanConvToPoly = bCanConvToPathOrPoly; + } + + if(rInfo.bCanConvToContour != aInfo.bCanConvToContour) + { + rInfo.bCanConvToContour = aInfo.bCanConvToContour; + } + } + } + } +} + +void SdrObjCustomShape::SetModel(SdrModel* pNewModel) +{ + SdrTextObj::SetModel(pNewModel); + mXRenderedCustomShape.clear(); +} + +UINT16 SdrObjCustomShape::GetObjIdentifier() const +{ + return UINT16(OBJ_CUSTOMSHAPE); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObjCustomShape::RecalcSnapRect() +{ + SdrTextObj::RecalcSnapRect(); +} +const Rectangle& SdrObjCustomShape::GetSnapRect() const +{ + return SdrTextObj::GetSnapRect(); +} +const Rectangle& SdrObjCustomShape::GetCurrentBoundRect() const +{ + return SdrTextObj::GetCurrentBoundRect(); +} +const Rectangle& SdrObjCustomShape::GetLogicRect() const +{ + return SdrTextObj::GetLogicRect(); +} +void SdrObjCustomShape::NbcSetSnapRect( const Rectangle& rRect ) +{ + aRect=rRect; + ImpJustifyRect(aRect); + InvalidateRenderGeometry(); + Rectangle aTextBound( aRect ); + if ( GetTextBounds( aTextBound ) ) + { + if ( pModel==NULL || !pModel->IsPasteResize() ) + { + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + long nTWdt=aTextBound.GetWidth ()-1-nHDist; if (nTWdt<0) nTWdt=0; + long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0; + if ( IsAutoGrowWidth() ) + NbcSetMinTextFrameWidth( nTWdt ); + if ( IsAutoGrowHeight() ) + NbcSetMinTextFrameHeight( nTHgt ); + NbcAdjustTextFrameWidthAndHeight(); + } + } + ImpCheckShear(); + SetRectsDirty(); + SetChanged(); +} +void SdrObjCustomShape::SetSnapRect( const Rectangle& rRect ) +{ + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetLastBoundRect(); + NbcSetSnapRect( rRect ); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} +void SdrObjCustomShape::NbcSetLogicRect( const Rectangle& rRect ) +{ + aRect = rRect; + ImpJustifyRect( aRect ); + InvalidateRenderGeometry(); + Rectangle aTextBound( aRect ); + if ( GetTextBounds( aTextBound ) ) + { + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + + long nTWdt=aTextBound.GetWidth()-1-nHDist; if (nTWdt<0) nTWdt=0; + long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0; + if ( IsAutoGrowWidth() ) + NbcSetMinTextFrameWidth( nTWdt ); + if ( IsAutoGrowHeight() ) + NbcSetMinTextFrameHeight( nTHgt ); + NbcAdjustTextFrameWidthAndHeight(); + } + SetRectsDirty(); + SetChanged(); +} +void SdrObjCustomShape::SetLogicRect( const Rectangle& rRect ) +{ + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetLastBoundRect(); + NbcSetLogicRect(rRect); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} +void SdrObjCustomShape::Move( const Size& rSiz ) +{ + if ( rSiz.Width() || rSiz.Height() ) + { + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcMove(rSiz); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} +void SdrObjCustomShape::NbcMove( const Size& rSiz ) +{ + SdrTextObj::NbcMove( rSiz ); + if ( mXRenderedCustomShape.is() ) + { + SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape ); + if ( pRenderedCustomShape ) + { + // #i97149# the visualisation shape needs to be informed + // about change, too + pRenderedCustomShape->ActionChanged(); + pRenderedCustomShape->NbcMove( rSiz ); + } + } + + // #i37011# adapt geometry shadow + if(mpLastShadowGeometry) + { + mpLastShadowGeometry->NbcMove( rSiz ); + } +} +void SdrObjCustomShape::Resize( const Point& rRef, const Fraction& xFact, const Fraction& yFact ) +{ + SdrTextObj::Resize( rRef, xFact, yFact ); +} + +void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, const Fraction& ryFact ) +{ + Fraction xFact( rxFact ); + Fraction yFact( ryFact ); + + // taking care of handles that should not been changed + Rectangle aOld( aRect ); + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + + SdrTextObj::NbcResize( rRef, xFact, yFact ); + + if ( ( xFact.GetNumerator() != xFact.GetDenominator() ) + || ( yFact.GetNumerator()!= yFact.GetDenominator() ) ) + { + if ( ( ( xFact.GetNumerator() < 0 ) && ( xFact.GetDenominator() > 0 ) ) || + ( ( xFact.GetNumerator() > 0 ) && ( xFact.GetDenominator() < 0 ) ) ) + { + SetMirroredX( IsMirroredX() == sal_False ); + } + if ( ( ( yFact.GetNumerator() < 0 ) && ( yFact.GetDenominator() > 0 ) ) || + ( ( yFact.GetNumerator() > 0 ) && ( yFact.GetDenominator() < 0 ) ) ) + { + SetMirroredY( IsMirroredY() == sal_False ); + } + } + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X ) + { + sal_Int32 nX = ( aIter->aPosition.X - aOld.Left() ) + aRect.Left(); + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) ); + } + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y ) + { + sal_Int32 nY = ( aIter->aPosition.Y - aOld.Top() ) + aRect.Top(); + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) ); + } + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + InvalidateRenderGeometry(); +} +void SdrObjCustomShape::NbcRotate( const Point& rRef, long nWink, double sn, double cs ) +{ + sal_Bool bMirroredX = IsMirroredX(); + sal_Bool bMirroredY = IsMirroredY(); + + fObjectRotation = fmod( fObjectRotation, 360.0 ); + if ( fObjectRotation < 0 ) + fObjectRotation = 360 + fObjectRotation; + + // the rotation angle for ashapes is stored in fObjectRotation, this rotation + // has to be applied to the text object (which is internally using aGeo.nWink). + SdrTextObj::NbcRotate( aRect.TopLeft(), -aGeo.nDrehWink, // retrieving the unrotated text object + sin( (-aGeo.nDrehWink) * F_PI18000 ), + cos( (-aGeo.nDrehWink) * F_PI18000 ) ); + aGeo.nDrehWink = 0; // resetting aGeo data + aGeo.RecalcSinCos(); + + long nW = (long)( fObjectRotation * 100 ); // applying our object rotation + if ( bMirroredX ) + nW = 36000 - nW; + if ( bMirroredY ) + nW = 18000 - nW; + nW = nW % 36000; + if ( nW < 0 ) + nW = 36000 + nW; + SdrTextObj::NbcRotate( aRect.TopLeft(), nW, // applying text rotation + sin( nW * F_PI18000 ), + cos( nW * F_PI18000 ) ); + + int nSwap = 0; + if ( bMirroredX ) + nSwap ^= 1; + if ( bMirroredY ) + nSwap ^= 1; + + double fWink = nWink; // updating to our new object rotation + fWink /= 100.0; + fObjectRotation = fmod( nSwap ? fObjectRotation - fWink : fObjectRotation + fWink, 360.0 ); + if ( fObjectRotation < 0 ) + fObjectRotation = 360 + fObjectRotation; + + SdrTextObj::NbcRotate( rRef, nWink, sn, cs ); // applying text rotation + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::NbcMirror( const Point& rRef1, const Point& rRef2 ) +{ + // storing horizontal and vertical flipping without modifying the rotate angle + + sal_Bool bHorz = sal_False; + sal_Bool bVert = sal_False; + if ( rRef1.X() == rRef2.X() ) + bHorz = sal_True; + if ( rRef1.Y() == rRef2.Y() ) + bVert = sal_True; + if ( !bHorz && !bVert ) + bHorz = bVert = sal_True; + + if ( bHorz || bVert ) + { + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + + ///////////////// + // "MirroredX" // + ///////////////// + if ( bHorz ) + { + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX ); + if ( pAny ) + { + sal_Bool bFlip = sal_Bool(); + if ( *pAny >>= bFlip ) + { + if ( bFlip ) + bHorz = sal_False; + } + } + PropertyValue aPropVal; + aPropVal.Name = sMirroredX; + aPropVal.Value <<= bHorz; + aGeometryItem.SetPropertyValue( aPropVal ); + } + + ///////////////// + // "MirroredY" // + ///////////////// + if ( bVert ) + { + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY ); + if ( pAny ) + { + sal_Bool bFlip = sal_Bool(); + if ( *pAny >>= bFlip ) + { + if ( bFlip ) + bVert = sal_False; + } + } + PropertyValue aPropVal; + aPropVal.Name = sMirroredY; + aPropVal.Value <<= bVert; + aGeometryItem.SetPropertyValue( aPropVal ); + } + SetMergedItem( aGeometryItem ); + } + SdrTextObj::NbcMirror( rRef1, rRef2 ); + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::Shear( const Point& rRef, long nWink, double tn, FASTBOOL bVShear ) +{ + SdrTextObj::Shear( rRef, nWink, tn, bVShear ); + InvalidateRenderGeometry(); +} +void SdrObjCustomShape::NbcShear( const Point& rRef, long nWink, double tn, FASTBOOL bVShear ) +{ + long nDrehWink = aGeo.nDrehWink; + if ( nDrehWink ) + { + aGeo.nDrehWink = -nDrehWink; + aGeo.RecalcSinCos(); + NbcRotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos ); + } + SdrTextObj::NbcShear(rRef,nWink,tn,bVShear); + if ( nDrehWink ) + { + aGeo.nDrehWink = nDrehWink; + aGeo.RecalcSinCos(); + Rotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos ); + } + InvalidateRenderGeometry(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrGluePoint SdrObjCustomShape::GetVertexGluePoint(USHORT nPosNum) const +{ + INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue(); + + // #i25616# + if(!LineIsOutsideGeometry()) + { + nWdt++; + nWdt /= 2; + } + + Point aPt; + switch (nPosNum) { + case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break; + case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break; + case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break; + case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break; + } + if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + aPt-=GetSnapRect().Center(); + SdrGluePoint aGP(aPt); + aGP.SetPercent(FALSE); + return aGP; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// #i38892# +void SdrObjCustomShape::ImpCheckCustomGluePointsAreAdded() +{ + const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); + + if(pSdrObject) + { + const SdrGluePointList* pSource = pSdrObject->GetGluePointList(); + + if(pSource && pSource->GetCount()) + { + if(!SdrTextObj::GetGluePointList()) + { + SdrTextObj::ForceGluePointList(); + } + + const SdrGluePointList* pList = SdrTextObj::GetGluePointList(); + + if(pList) + { + SdrGluePointList aNewList; + sal_uInt16 a; + + for(a = 0; a < pSource->GetCount(); a++) + { + SdrGluePoint aCopy((*pSource)[a]); + aCopy.SetUserDefined(FALSE); + aNewList.Insert(aCopy); + } + + sal_Bool bMirroredX = IsMirroredX(); + sal_Bool bMirroredY = IsMirroredY(); + + long nShearWink = aGeo.nShearWink; + double fTan = aGeo.nTan; + + if ( aGeo.nDrehWink || nShearWink || bMirroredX || bMirroredY ) + { + Polygon aPoly( aRect ); + if( nShearWink ) + { + USHORT nPointCount=aPoly.GetSize(); + for (USHORT i=0; i<nPointCount; i++) + ShearPoint(aPoly[i],aRect.Center(), fTan, FALSE ); + } + if ( aGeo.nDrehWink ) + aPoly.Rotate( aRect.Center(), aGeo.nDrehWink / 10 ); + + Rectangle aBoundRect( aPoly.GetBoundRect() ); + sal_Int32 nXDiff = aBoundRect.Left() - aRect.Left(); + sal_Int32 nYDiff = aBoundRect.Top() - aRect.Top(); + + if (nShearWink&&((bMirroredX&&!bMirroredY)||(bMirroredY&&!bMirroredX))) + { + nShearWink = -nShearWink; + fTan = -fTan; + } + + Point aRef( aRect.GetWidth() / 2, aRect.GetHeight() / 2 ); + for ( a = 0; a < aNewList.GetCount(); a++ ) + { + SdrGluePoint& rPoint = aNewList[ a ]; + Point aGlue( rPoint.GetPos() ); + if ( nShearWink ) + ShearPoint( aGlue, aRef, fTan ); + + RotatePoint( aGlue, aRef, sin( fObjectRotation * F_PI180 ), cos( fObjectRotation * F_PI180 ) ); + if ( bMirroredX ) + aGlue.X() = aRect.GetWidth() - aGlue.X(); + if ( bMirroredY ) + aGlue.Y() = aRect.GetHeight() - aGlue.Y(); + aGlue.X() -= nXDiff; + aGlue.Y() -= nYDiff; + rPoint.SetPos( aGlue ); + } + } + + for(a = 0; a < pList->GetCount(); a++) + { + const SdrGluePoint& rCandidate = (*pList)[a]; + + if(rCandidate.IsUserDefined()) + { + aNewList.Insert(rCandidate); + } + } + + // copy new list to local. This is NOT very convenient behaviour, the local + // GluePointList should not be set, but be delivered by using GetGluePointList(), + // maybe on demand. Since the local object is changed here, this is assumed to + // be a result of GetGluePointList and thus the list is copied + if(pPlusData) + { + *pPlusData->pGluePoints = aNewList; + } + } + } + } +} + +// #i38892# +const SdrGluePointList* SdrObjCustomShape::GetGluePointList() const +{ + ((SdrObjCustomShape*)this)->ImpCheckCustomGluePointsAreAdded(); + return SdrTextObj::GetGluePointList(); +} + +// #i38892# +//SdrGluePointList* SdrObjCustomShape::GetGluePointList() +//{ +// ImpCheckCustomGluePointsAreAdded(); +// return SdrTextObj::GetGluePointList(); +//} + +// #i38892# +SdrGluePointList* SdrObjCustomShape::ForceGluePointList() +{ + if(SdrTextObj::ForceGluePointList()) + { + ImpCheckCustomGluePointsAreAdded(); + return SdrTextObj::ForceGluePointList(); + } + else + { + return 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_uInt32 SdrObjCustomShape::GetHdlCount() const +{ + const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount()); + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + return ( aInteractionHandles.size() + nBasicHdlCount ); +} + +SdrHdl* SdrObjCustomShape::GetHdl( sal_uInt32 nHdlNum ) const +{ + SdrHdl* pH = NULL; + const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount()); + + if ( nHdlNum < nBasicHdlCount ) + pH = SdrTextObj::GetHdl( nHdlNum ); + else + { + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + const sal_uInt32 nCustomShapeHdlNum(nHdlNum - nBasicHdlCount); + + if ( nCustomShapeHdlNum < aInteractionHandles.size() ) + { + if ( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction.is() ) + { + try + { + com::sun::star::awt::Point aPosition( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction->getPosition() ); + pH = new SdrHdl( Point( aPosition.X, aPosition.Y ), HDL_CUSTOMSHAPE1 ); + pH->SetPointNum( nCustomShapeHdlNum ); + pH->SetObj( (SdrObject*)this ); + } + catch ( const uno::RuntimeException& ) + { + } + } + } + } + return pH; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrObjCustomShape::hasSpecialDrag() const +{ + return true; +} + +bool SdrObjCustomShape::beginSpecialDrag(SdrDragStat& rDrag) const +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + + if(pHdl && HDL_CUSTOMSHAPE1 == pHdl->GetKind()) + { + rDrag.SetEndDragChangesAttributes(true); + rDrag.SetNoSnap(true); + } + else + { + const SdrHdl* pHdl2 = rDrag.GetHdl(); + const SdrHdlKind eHdl((pHdl2 == NULL) ? HDL_MOVE : pHdl2->GetKind()); + + switch( eHdl ) + { + case HDL_UPLFT : + case HDL_UPPER : + case HDL_UPRGT : + case HDL_LEFT : + case HDL_RIGHT : + case HDL_LWLFT : + case HDL_LOWER : + case HDL_LWRGT : + case HDL_MOVE : + { + break; + } + default: + { + return false; + } + } + } + + return true; +} + +void SdrObjCustomShape::DragResizeCustomShape( const Rectangle& rNewRect, SdrObjCustomShape* pObj ) const +{ + Rectangle aOld( pObj->aRect ); + sal_Bool bOldMirroredX( pObj->IsMirroredX() ); + sal_Bool bOldMirroredY( pObj->IsMirroredY() ); + + Rectangle aNewRect( rNewRect ); + aNewRect.Justify(); + + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) ); + + GeoStat aGeoStat( pObj->GetGeoStat() ); + if ( aNewRect.TopLeft()!= pObj->aRect.TopLeft() && + ( pObj->aGeo.nDrehWink || pObj->aGeo.nShearWink ) ) + { + Point aNewPos( aNewRect.TopLeft() ); + if ( pObj->aGeo.nShearWink ) ShearPoint( aNewPos, aOld.TopLeft(), aGeoStat.nTan ); + if ( pObj->aGeo.nDrehWink ) RotatePoint(aNewPos, aOld.TopLeft(), aGeoStat.nSin, aGeoStat.nCos ); + aNewRect.SetPos( aNewPos ); + } + if ( aNewRect != pObj->aRect ) + { + pObj->SetLogicRect( aNewRect ); + pObj->InvalidateRenderGeometry(); + + if ( rNewRect.Left() > rNewRect.Right() ) + { + Point aTop( ( pObj->GetSnapRect().Left() + pObj->GetSnapRect().Right() ) >> 1, pObj->GetSnapRect().Top() ); + Point aBottom( aTop.X(), aTop.Y() + 1000 ); + pObj->NbcMirror( aTop, aBottom ); + } + if ( rNewRect.Top() > rNewRect.Bottom() ) + { + Point aLeft( pObj->GetSnapRect().Left(), ( pObj->GetSnapRect().Top() + pObj->GetSnapRect().Bottom() ) >> 1 ); + Point aRight( aLeft.X() + 1000, aLeft.Y() ); + pObj->NbcMirror( aLeft, aRight ); + } + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X ) + { + sal_Int32 nX; + if ( bOldMirroredX ) + { + nX = ( aIter->aPosition.X - aOld.Right() ); + if ( rNewRect.Left() > rNewRect.Right() ) + nX = pObj->aRect.Left() - nX; + else + nX += pObj->aRect.Right(); + } + else + { + nX = ( aIter->aPosition.X - aOld.Left() ); + if ( rNewRect.Left() > rNewRect.Right() ) + nX = pObj->aRect.Right() - nX; + else + nX += pObj->aRect.Left(); + } + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) ); + } + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y ) + { + sal_Int32 nY; + if ( bOldMirroredY ) + { + nY = ( aIter->aPosition.Y - aOld.Bottom() ); + if ( rNewRect.Top() > rNewRect.Bottom() ) + nY = pObj->aRect.Top() - nY; + else + nY += pObj->aRect.Bottom(); + } + else + { + nY = ( aIter->aPosition.Y - aOld.Top() ); + if ( rNewRect.Top() > rNewRect.Bottom() ) + nY = pObj->aRect.Bottom() - nY; + else + nY += pObj->aRect.Top(); + } + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) ); + } + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + } +} + +void SdrObjCustomShape::DragMoveCustomShapeHdl( const Point aDestination, const sal_uInt16 nCustomShapeHdlNum, SdrObjCustomShape* pObj ) const +{ + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) ); + if ( nCustomShapeHdlNum < aInteractionHandles.size() ) + { + SdrCustomShapeInteraction aInteractionHandle( aInteractionHandles[ nCustomShapeHdlNum ] ); + if ( aInteractionHandle.xInteraction.is() ) + { + try + { + com::sun::star::awt::Point aPt( aDestination.X(), aDestination.Y() ); + if ( aInteractionHandle.nMode & CUSTOMSHAPE_HANDLE_MOVE_SHAPE ) + { + sal_Int32 nXDiff = aPt.X - aInteractionHandle.aPosition.X; + sal_Int32 nYDiff = aPt.Y - aInteractionHandle.aPosition.Y; + + pObj->aRect.Move( nXDiff, nYDiff ); + pObj->aOutRect.Move( nXDiff, nYDiff ); + pObj->maSnapRect.Move( nXDiff, nYDiff ); + pObj->SetRectsDirty(sal_True); + pObj->InvalidateRenderGeometry(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + { + if ( aIter->xInteraction.is() ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + } + aIter++; + } + } + aInteractionHandle.xInteraction->setControllerPosition( aPt ); + } + catch ( const uno::RuntimeException& ) + { + } + } + } +} + +bool SdrObjCustomShape::applySpecialDrag(SdrDragStat& rDrag) +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + const SdrHdlKind eHdl((pHdl == NULL) ? HDL_MOVE : pHdl->GetKind()); + + switch(eHdl) + { + case HDL_CUSTOMSHAPE1 : + { + rDrag.SetEndDragChangesGeoAndAttributes(true); + DragMoveCustomShapeHdl( rDrag.GetNow(), (sal_uInt16)pHdl->GetPointNum(), this ); + SetRectsDirty(); + InvalidateRenderGeometry(); + SetChanged(); + break; + } + + case HDL_UPLFT : + case HDL_UPPER : + case HDL_UPRGT : + case HDL_LEFT : + case HDL_RIGHT : + case HDL_LWLFT : + case HDL_LOWER : + case HDL_LWRGT : + { + DragResizeCustomShape(ImpDragCalcRect(rDrag), this); + break; + } + case HDL_MOVE : + { + Move(Size(rDrag.GetDX(), rDrag.GetDY())); + break; + } + default: break; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObjCustomShape::DragCreateObject( SdrDragStat& rStat ) +{ + Rectangle aRect1; + rStat.TakeCreateRect( aRect1 ); + + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + + sal_uInt32 nDefaultObjectSizeWidth = 3000; // default width from SDOptions ? + sal_uInt32 nDefaultObjectSizeHeight= 3000; + + if ( ImpVerticalSwitch( *this ) ) + { + SetMirroredX( aRect1.Left() > aRect1.Right() ); + + aRect1 = Rectangle( rStat.GetNow(), Size( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ) ); + // subtracting the horizontal difference of the latest handle from shape position + if ( aInteractionHandles.size() ) + { + sal_Int32 nHandlePos = aInteractionHandles[ aInteractionHandles.size() - 1 ].xInteraction->getPosition().X; + aRect1.Move( aRect.Left() - nHandlePos, 0 ); + } + } + ImpJustifyRect( aRect1 ); + rStat.SetActionRect( aRect1 ); + aRect = aRect1; + SetRectsDirty(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_CREATE_FIXED ) + aIter->xInteraction->setControllerPosition( awt::Point( rStat.GetStart().X(), rStat.GetStart().Y() ) ); + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + + SetBoundRectDirty(); + bSnapRectDirty=TRUE; +} + +FASTBOOL SdrObjCustomShape::BegCreate( SdrDragStat& rDrag ) +{ + return SdrTextObj::BegCreate( rDrag ); +} + +FASTBOOL SdrObjCustomShape::MovCreate(SdrDragStat& rStat) +{ + SdrView* pView = rStat.GetView(); // #i37448# + if( pView && pView->IsSolidDragging() ) + { + InvalidateRenderGeometry(); + } + DragCreateObject( rStat ); + SetRectsDirty(); + return TRUE; +} + +FASTBOOL SdrObjCustomShape::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd ) +{ + DragCreateObject( rStat ); + + if ( bTextFrame ) + { + if ( IsAutoGrowHeight() ) + { + // MinTextHeight + long nHgt=aRect.GetHeight()-1; + if (nHgt==1) nHgt=0; + NbcSetMinTextFrameHeight( nHgt ); + } + if ( IsAutoGrowWidth() ) + { + // MinTextWidth + long nWdt=aRect.GetWidth()-1; + if (nWdt==1) nWdt=0; + NbcSetMinTextFrameWidth( nWdt ); + } + // Textrahmen neu berechnen + NbcAdjustTextFrameWidthAndHeight(); + } + SetRectsDirty(); + return ( eCmd == SDRCREATE_FORCEEND || rStat.GetPointAnz() >= 2 ); +} + +basegfx::B2DPolyPolygon SdrObjCustomShape::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const +{ + return GetLineGeometry( this, sal_False ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// in context with the SdrObjCustomShape the SdrTextAutoGrowHeightItem == true -> Resize Shape to fit text, +// the SdrTextAutoGrowWidthItem == true -> Word wrap text in Shape +FASTBOOL SdrObjCustomShape::IsAutoGrowHeight() const +{ + const SfxItemSet& rSet = GetMergedItemSet(); + FASTBOOL bIsAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue(); + if ( bIsAutoGrowHeight && IsVerticalWriting() ) + bIsAutoGrowHeight = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == FALSE; + return bIsAutoGrowHeight; +} +FASTBOOL SdrObjCustomShape::IsAutoGrowWidth() const +{ + const SfxItemSet& rSet = GetMergedItemSet(); + FASTBOOL bIsAutoGrowWidth = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue(); + if ( bIsAutoGrowWidth && !IsVerticalWriting() ) + bIsAutoGrowWidth = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == FALSE; + return bIsAutoGrowWidth; +} + +/* The following method is identical to the SdrTextObj::SetVerticalWriting method, the only difference + is that the SdrAutoGrowWidthItem and SdrAutoGrowHeightItem are not exchanged if the vertical writing + mode has been changed */ + +void SdrObjCustomShape::SetVerticalWriting( sal_Bool bVertical ) +{ + ForceOutlinerParaObject(); + + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + + DBG_ASSERT( pOutlinerParaObject, "SdrTextObj::SetVerticalWriting() without OutlinerParaObject!" ); + + if( pOutlinerParaObject ) + { + if(pOutlinerParaObject->IsVertical() != (bool)bVertical) + { + // get item settings + const SfxItemSet& rSet = GetObjectItemSet(); + + // #103516# Also exchange hor/ver adjust items + SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue(); + SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue(); + + // rescue object size + Rectangle aObjectRect = GetSnapRect(); + + // prepare ItemSet to set exchanged width and height items + SfxItemSet aNewSet(*rSet.GetPool(), + SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT, + // #103516# Expanded item ranges to also support hor and ver adjust. + SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST, + SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST, + 0, 0); + + aNewSet.Put(rSet); + + // #103516# Exchange horz and vert adjusts + switch(eVert) + { + case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break; + case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break; + case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break; + case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break; + } + switch(eHorz) + { + case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break; + case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break; + case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break; + case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break; + } + + SetObjectItemSet( aNewSet ); + pOutlinerParaObject = GetOutlinerParaObject(); + if ( pOutlinerParaObject ) + pOutlinerParaObject->SetVertical(bVertical); + + // restore object size + SetSnapRect(aObjectRect); + } + } +} +FASTBOOL SdrObjCustomShape::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHgt, FASTBOOL bWdt) const +{ + if ( pModel && HasText() && !rR.IsEmpty() ) + { + FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth(); + FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight(); + if ( bWdtGrow || bHgtGrow ) + { + Rectangle aR0(rR); + long nHgt=0,nMinHgt=0,nMaxHgt=0; + long nWdt=0,nMinWdt=0,nMaxWdt=0; + Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--; + Size aMaxSiz(100000,100000); + Size aTmpSiz(pModel->GetMaxObjSize()); + if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); + if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); + if (bWdtGrow) + { + nMinWdt=GetMinTextFrameWidth(); + nMaxWdt=GetMaxTextFrameWidth(); + if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width(); + if (nMinWdt<=0) nMinWdt=1; + aSiz.Width()=nMaxWdt; + } + if (bHgtGrow) + { + nMinHgt=GetMinTextFrameHeight(); + nMaxHgt=GetMaxTextFrameHeight(); + if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height(); + if (nMinHgt<=0) nMinHgt=1; + aSiz.Height()=nMaxHgt; + } + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + aSiz.Width()-=nHDist; + aSiz.Height()-=nVDist; + if ( aSiz.Width() < 2 ) + aSiz.Width() = 2; // Mindestgroesse 2 + if ( aSiz.Height() < 2 ) + aSiz.Height() = 2; // Mindestgroesse 2 + + if(pEdtOutl) + { + pEdtOutl->SetMaxAutoPaperSize( aSiz ); + if (bWdtGrow) + { + Size aSiz2(pEdtOutl->CalcTextSize()); + nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz + if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz + } else + { + nHgt=pEdtOutl->GetTextHeight()+1; // lieber etwas Tolleranz + } + } + else + { + Outliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetPaperSize(aSiz); + rOutliner.SetUpdateMode(TRUE); + // !!! hier sollte ich wohl auch noch mal die Optimierung mit + // bPortionInfoChecked usw einbauen + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if( pOutlinerParaObject != NULL ) + { + rOutliner.SetText(*pOutlinerParaObject); + rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); + } + if ( bWdtGrow ) + { + Size aSiz2(rOutliner.CalcTextSize()); + nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz + if ( bHgtGrow ) + nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz + } + else + nHgt = rOutliner.GetTextHeight()+1; // lieber etwas Tolleranz + rOutliner.Clear(); + } + if ( nWdt < nMinWdt ) + nWdt = nMinWdt; + if ( nWdt > nMaxWdt ) + nWdt = nMaxWdt; + nWdt += nHDist; + if ( nWdt < 1 ) + nWdt = 1; // nHDist kann auch negativ sein + if ( nHgt < nMinHgt ) + nHgt = nMinHgt; + if ( nHgt > nMaxHgt ) + nHgt = nMaxHgt; + nHgt+=nVDist; + if ( nHgt < 1 ) + nHgt = 1; // nVDist kann auch negativ sein + long nWdtGrow = nWdt-(rR.Right()-rR.Left()); + long nHgtGrow = nHgt-(rR.Bottom()-rR.Top()); + if ( nWdtGrow == 0 ) + bWdtGrow = FALSE; + if ( nHgtGrow == 0 ) + bHgtGrow=FALSE; + if ( bWdtGrow || bHgtGrow ) + { + if ( bWdtGrow ) + { + SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); + if ( eHAdj == SDRTEXTHORZADJUST_LEFT ) + rR.Right()+=nWdtGrow; + else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT ) + rR.Left()-=nWdtGrow; + else + { + long nWdtGrow2=nWdtGrow/2; + rR.Left()-=nWdtGrow2; + rR.Right()=rR.Left()+nWdt; + } + } + if ( bHgtGrow ) + { + SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); + if ( eVAdj == SDRTEXTVERTADJUST_TOP ) + rR.Bottom()+=nHgtGrow; + else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM ) + rR.Top()-=nHgtGrow; + else + { + long nHgtGrow2=nHgtGrow/2; + rR.Top()-=nHgtGrow2; + rR.Bottom()=rR.Top()+nHgt; + } + } + if ( aGeo.nDrehWink ) + { + Point aD1(rR.TopLeft()); + aD1-=aR0.TopLeft(); + Point aD2(aD1); + RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos); + aD2-=aD1; + rR.Move(aD2.X(),aD2.Y()); + } + return TRUE; + } + } + } + return FALSE; +} + +Rectangle SdrObjCustomShape::ImpCalculateTextFrame( const FASTBOOL bHgt, const FASTBOOL bWdt ) +{ + Rectangle aReturnValue; + + Rectangle aOldTextRect( aRect ); // <- initial text rectangle + + Rectangle aNewTextRect( aRect ); // <- new text rectangle returned from the custom shape renderer, + GetTextBounds( aNewTextRect ); // it depends to the current logical shape size + + Rectangle aAdjustedTextRect( aNewTextRect ); // <- new text rectangle is being tested by AdjustTextFrameWidthAndHeight to ensure + if ( AdjustTextFrameWidthAndHeight( aAdjustedTextRect, bHgt, bWdt ) ) // that the new text rectangle is matching the current text size from the outliner + { + if ( ( aAdjustedTextRect != aNewTextRect ) && ( aOldTextRect != aAdjustedTextRect ) ) + { + aReturnValue = aRect; + double fXScale = (double)aOldTextRect.GetWidth() / (double)aNewTextRect.GetWidth(); + double fYScale = (double)aOldTextRect.GetHeight() / (double)aNewTextRect.GetHeight(); + double fRightDiff = (double)( aAdjustedTextRect.Right() - aNewTextRect.Right() ) * fXScale; + double fLeftDiff = (double)( aAdjustedTextRect.Left() - aNewTextRect.Left() ) * fXScale; + double fTopDiff = (double)( aAdjustedTextRect.Top() - aNewTextRect.Top() ) * fYScale; + double fBottomDiff= (double)( aAdjustedTextRect.Bottom()- aNewTextRect.Bottom()) * fYScale; + aReturnValue.Left() += (sal_Int32)fLeftDiff; + aReturnValue.Right() += (sal_Int32)fRightDiff; + aReturnValue.Top() += (sal_Int32)fTopDiff; + aReturnValue.Bottom() += (sal_Int32)fBottomDiff; + } + } + return aReturnValue; +} + +FASTBOOL SdrObjCustomShape::NbcAdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) +{ + Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt ); + sal_Bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect ); + if ( bRet ) + { + // taking care of handles that should not been changed + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + + aRect = aNewTextRect; + SetRectsDirty(); + SetChanged(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + InvalidateRenderGeometry(); + } + return bRet; +} +FASTBOOL SdrObjCustomShape::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) +{ + Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt ); + sal_Bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect ); + if ( bRet ) + { + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetCurrentBoundRect(); + + // taking care of handles that should not been changed + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + +// SendRepaintBroadcast(); + aRect = aNewTextRect; + SetRectsDirty(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + + InvalidateRenderGeometry(); + SetChanged(); +// SendRepaintBroadcast(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } + return bRet; +} +sal_Bool SdrObjCustomShape::BegTextEdit( SdrOutliner& rOutl ) +{ + return SdrTextObj::BegTextEdit( rOutl ); +} +void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const +{ + Size aPaperMin,aPaperMax; + Rectangle aViewInit; + TakeTextAnchorRect( aViewInit ); + if ( aGeo.nDrehWink ) + { + Point aCenter(aViewInit.Center()); + aCenter-=aViewInit.TopLeft(); + Point aCenter0(aCenter); + RotatePoint(aCenter,Point(),aGeo.nSin,aGeo.nCos); + aCenter-=aCenter0; + aViewInit.Move(aCenter.X(),aCenter.Y()); + } + Size aAnkSiz(aViewInit.GetSize()); + aAnkSiz.Width()--; aAnkSiz.Height()--; // weil GetSize() ein draufaddiert + Size aMaxSiz(1000000,1000000); + if (pModel!=NULL) { + Size aTmpSiz(pModel->GetMaxObjSize()); + if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); + if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); + } + SdrTextHorzAdjust eHAdj(GetTextHorizontalAdjust()); + SdrTextVertAdjust eVAdj(GetTextVerticalAdjust()); + + long nMinWdt = GetMinTextFrameWidth(); + long nMinHgt = GetMinTextFrameHeight(); + long nMaxWdt = GetMaxTextFrameWidth(); + long nMaxHgt = GetMaxTextFrameHeight(); + if (nMinWdt<1) nMinWdt=1; + if (nMinHgt<1) nMinHgt=1; + if ( nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width() ) + nMaxWdt = aMaxSiz.Width(); + if ( nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height() ) + nMaxHgt=aMaxSiz.Height(); + + if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue()) + { + if ( IsVerticalWriting() ) + { + nMaxHgt = aAnkSiz.Height(); + nMinHgt = nMaxHgt; + } + else + { + nMaxWdt = aAnkSiz.Width(); + nMinWdt = nMaxWdt; + } + } + aPaperMax.Width()=nMaxWdt; + aPaperMax.Height()=nMaxHgt; + + aPaperMin.Width()=nMinWdt; + aPaperMin.Height()=nMinHgt; + + if ( pViewMin ) + { + *pViewMin = aViewInit; + + long nXFree = aAnkSiz.Width() - aPaperMin.Width(); + if ( eHAdj == SDRTEXTHORZADJUST_LEFT ) + pViewMin->Right() -= nXFree; + else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT ) + pViewMin->Left() += nXFree; + else { pViewMin->Left() += nXFree / 2; pViewMin->Right() = pViewMin->Left() + aPaperMin.Width(); } + + long nYFree = aAnkSiz.Height() - aPaperMin.Height(); + if ( eVAdj == SDRTEXTVERTADJUST_TOP ) + pViewMin->Bottom() -= nYFree; + else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM ) + pViewMin->Top() += nYFree; + else { pViewMin->Top() += nYFree / 2; pViewMin->Bottom() = pViewMin->Top() + aPaperMin.Height(); } + } + + if( IsVerticalWriting() ) + aPaperMin.Width() = 0; + else + aPaperMin.Height() = 0; // #33102# + + if( eHAdj != SDRTEXTHORZADJUST_BLOCK ) + aPaperMin.Width()=0; + + // #103516# For complete ver adjust support, set paper min height to 0, here. + if(SDRTEXTVERTADJUST_BLOCK != eVAdj ) + aPaperMin.Height() = 0; + + if (pPaperMin!=NULL) *pPaperMin=aPaperMin; + if (pPaperMax!=NULL) *pPaperMax=aPaperMax; + if (pViewInit!=NULL) *pViewInit=aViewInit; +} +void SdrObjCustomShape::EndTextEdit( SdrOutliner& rOutl ) +{ + SdrTextObj::EndTextEdit( rOutl ); + InvalidateRenderGeometry(); +} +void SdrObjCustomShape::TakeTextAnchorRect( Rectangle& rAnchorRect ) const +{ + if ( GetTextBounds( rAnchorRect ) ) + { + Point aRotateRef( maSnapRect.Center() ); + rAnchorRect.Left() += GetTextLeftDistance(); + rAnchorRect.Top() += GetTextUpperDistance(); + rAnchorRect.Right() -= GetTextRightDistance(); + rAnchorRect.Bottom() -= GetTextLowerDistance(); + ImpJustifyRect( rAnchorRect ); + + if ( rAnchorRect.GetWidth() < 2 ) + rAnchorRect.Right() = rAnchorRect.Left() + 1; // minimal width is 2 + if ( rAnchorRect.GetHeight() < 2 ) + rAnchorRect.Bottom() = rAnchorRect.Top() + 1; // minimal height is 2 + if ( aGeo.nDrehWink ) + { + Point aP( rAnchorRect.TopLeft() ); + RotatePoint( aP, aRotateRef, aGeo.nSin, aGeo. nCos ); + rAnchorRect.SetPos( aP ); + } + } + else + SdrTextObj::TakeTextAnchorRect( rAnchorRect ); +} +void SdrObjCustomShape::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, + Rectangle* pAnchorRect, BOOL /*bLineWidth*/) const +{ + Rectangle aAnkRect; // Rect innerhalb dem geankert wird + TakeTextAnchorRect(aAnkRect); + SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); + SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); + ULONG nStat0=rOutliner.GetControlWord(); + Size aNullSize; + + rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE); + rOutliner.SetMinAutoPaperSize(aNullSize); + sal_Int32 nMaxAutoPaperWidth = 1000000; + sal_Int32 nMaxAutoPaperHeight= 1000000; + + long nAnkWdt=aAnkRect.GetWidth(); + long nAnkHgt=aAnkRect.GetHeight(); + + if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue()) + { + if ( IsVerticalWriting() ) + nMaxAutoPaperHeight = nAnkHgt; + else + nMaxAutoPaperWidth = nAnkWdt; + } + if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting()) + { + rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0)); + } + + if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting()) + { + rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt)); + } + rOutliner.SetMaxAutoPaperSize( Size( nMaxAutoPaperWidth, nMaxAutoPaperHeight ) ); + rOutliner.SetPaperSize( aNullSize ); + + // Text in den Outliner stecken - ggf. den aus dem EditOutliner + OutlinerParaObject* pPara= GetOutlinerParaObject(); + if (pEdtOutl && !bNoEditText) + pPara=pEdtOutl->CreateParaObject(); + + if (pPara) + { + BOOL bHitTest = FALSE; + if( pModel ) + bHitTest = &pModel->GetHitTestOutliner() == &rOutliner; + + const SdrTextObj* pTestObj = rOutliner.GetTextObj(); + if( !pTestObj || !bHitTest || pTestObj != this || + pTestObj->GetOutlinerParaObject() != GetOutlinerParaObject() ) + { + if( bHitTest ) + rOutliner.SetTextObj( this ); + + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetText(*pPara); + } + } + else + { + rOutliner.SetTextObj( NULL ); + } + if (pEdtOutl && !bNoEditText && pPara) + delete pPara; + + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetControlWord(nStat0); + + SdrText* pText = getActiveText(); + if( pText ) + pText->CheckPortionInfo( rOutliner ); + + Point aTextPos(aAnkRect.TopLeft()); + Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() hat etwas Toleranz drauf, oder? + + // #106653# + // For draw objects containing text correct hor/ver alignment if text is bigger + // than the object itself. Without that correction, the text would always be + // formatted to the left edge (or top edge when vertical) of the draw object. + + if( !IsTextFrame() ) + { + if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting()) + { + // #110129# + // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTHORZADJUST_BLOCK == eHAdj) + { + eHAdj = SDRTEXTHORZADJUST_CENTER; + } + } + + if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting()) + { + // #110129# + // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTVERTADJUST_BLOCK == eVAdj) + { + eVAdj = SDRTEXTVERTADJUST_CENTER; + } + } + } + + if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT) + { + long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width(); + if (eHAdj==SDRTEXTHORZADJUST_CENTER) + aTextPos.X()+=nFreeWdt/2; + if (eHAdj==SDRTEXTHORZADJUST_RIGHT) + aTextPos.X()+=nFreeWdt; + } + if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM) + { + long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height(); + if (eVAdj==SDRTEXTVERTADJUST_CENTER) + aTextPos.Y()+=nFreeHgt/2; + if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) + aTextPos.Y()+=nFreeHgt; + } + if (aGeo.nDrehWink!=0) + RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos); + + if (pAnchorRect) + *pAnchorRect=aAnkRect; + + // rTextRect ist bei ContourFrame in einigen Faellen nicht korrekt + rTextRect=Rectangle(aTextPos,aTextSiz); +} + +void SdrObjCustomShape::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject) +{ + SdrTextObj::NbcSetOutlinerParaObject( pTextObject ); + SetBoundRectDirty(); + SetRectsDirty(TRUE); + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::operator=(const SdrObject& rObj) +{ + SdrTextObj::operator=( rObj ); + aName =((SdrObjCustomShape&)rObj).aName; + fObjectRotation = ((SdrObjCustomShape&)rObj).fObjectRotation; + InvalidateRenderGeometry(); +} + + +void SdrObjCustomShape::TakeObjNameSingul(XubString& rName) const +{ + rName = ImpGetResStr(STR_ObjNameSingulCUSTOMSHAPE); + String aNm( GetName() ); + if( aNm.Len() ) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aNm; + rName += sal_Unicode('\''); + } +} + +void SdrObjCustomShape::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralCUSTOMSHAPE); +} + +basegfx::B2DPolyPolygon SdrObjCustomShape::TakeXorPoly() const +{ + return GetLineGeometry( (SdrObjCustomShape*)this, sal_False ); +} + +basegfx::B2DPolyPolygon SdrObjCustomShape::TakeContour() const +{ + const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); + if ( pSdrObject ) + return pSdrObject->TakeContour(); + return basegfx::B2DPolyPolygon(); +} + +SdrObject* SdrObjCustomShape::DoConvertToPolyObj(BOOL bBezier) const +{ + // #i37011# + SdrObject* pRetval = 0L; + SdrObject* pRenderedCustomShape = 0L; + + if ( !mXRenderedCustomShape.is() ) + { + // force CustomShape + ((SdrObjCustomShape*)this)->GetSdrObjectFromCustomShape(); + } + + if ( mXRenderedCustomShape.is() ) + { + pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape ); + } + + if ( pRenderedCustomShape ) + { + SdrObject* pCandidate = pRenderedCustomShape->Clone(); + DBG_ASSERT(pCandidate, "SdrObjCustomShape::DoConvertToPolyObj: Could not clone SdrObject (!)"); + pCandidate->SetModel(GetModel()); + pRetval = pCandidate->DoConvertToPolyObj(bBezier); + SdrObject::Free( pCandidate ); + + if(pRetval) + { + const sal_Bool bShadow(((SdrShadowItem&)GetMergedItem(SDRATTR_SHADOW)).GetValue()); + if(bShadow) + { + pRetval->SetMergedItem(SdrShadowItem(sal_True)); + } + } + + if(HasText() && !IsTextPath()) + { + pRetval = ImpConvertAddText(pRetval, bBezier); + } + } + + return pRetval; +} + +void SdrObjCustomShape::NbcSetStyleSheet( SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr ) +{ + // #i40944# + InvalidateRenderGeometry(); + SdrObject::NbcSetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr ); +} + +void SdrObjCustomShape::SetPage( SdrPage* pNewPage ) +{ + SdrTextObj::SetPage( pNewPage ); + + if( pNewPage ) + { + // invalidating rectangles by SetRectsDirty is not sufficient, + // AdjustTextFrameWidthAndHeight() also has to be made, both + // actions are done by NbcSetSnapRect + Rectangle aTmp( aRect ); //creating temporary rectangle #i61108# + NbcSetSnapRect( aTmp ); + } +} + +SdrObjGeoData* SdrObjCustomShape::NewGeoData() const +{ + return new SdrAShapeObjGeoData; +} + +void SdrObjCustomShape::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrTextObj::SaveGeoData( rGeo ); + SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo; + rAGeo.fObjectRotation = fObjectRotation; + rAGeo.bMirroredX = IsMirroredX(); + rAGeo.bMirroredY = IsMirroredY(); + + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + Any* pAny( ( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ).GetPropertyValueByName( sAdjustmentValues ) ); + if ( pAny ) + *pAny >>= rAGeo.aAdjustmentSeq; +} + +void SdrObjCustomShape::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrTextObj::RestGeoData( rGeo ); + SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo; + fObjectRotation = rAGeo.fObjectRotation; + SetMirroredX( rAGeo.bMirroredX ); + SetMirroredY( rAGeo.bMirroredY ); + + SdrCustomShapeGeometryItem rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + PropertyValue aPropVal; + aPropVal.Name = sAdjustmentValues; + aPropVal.Value <<= rAGeo.aAdjustmentSeq; + rGeometryItem.SetPropertyValue( aPropVal ); + SetMergedItem( rGeometryItem ); + + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) +{ + // break up matrix + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate, fShearX; + rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings + // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale.setX(fabs(aScale.getX())); + aScale.setY(fabs(aScale.getY())); + fRotate = fmod(fRotate + F_PI, F_2PI); + } + + // reset object shear and rotations + aGeo.nDrehWink = 0; + aGeo.RecalcSinCos(); + aGeo.nShearWink = 0; + aGeo.RecalcTan(); + + // force metric to pool metric + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // position + aTranslate.setX(ImplMMToTwips(aTranslate.getX())); + aTranslate.setY(ImplMMToTwips(aTranslate.getY())); + + // size + aScale.setX(ImplMMToTwips(aScale.getX())); + aScale.setY(ImplMMToTwips(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); + } + } + } + + // if anchor is used, make position relative to it + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // build and set BaseRect (use scale) + Point aPoint = Point(); + Size aSize(FRound(aScale.getX()), FRound(aScale.getY())); + Rectangle aBaseRect(aPoint, aSize); + SetSnapRect(aBaseRect); + + // shear? + if(!basegfx::fTools::equalZero(fShearX)) + { + GeoStat aGeoStat; + aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0); + aGeoStat.RecalcTan(); + Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, FALSE); + } + + // rotation? + if(!basegfx::fTools::equalZero(fRotate)) + { + GeoStat aGeoStat; + + // #i78696# + // fRotate is mathematically correct, but aGeoStat.nDrehWink is + // mirrored -> mirror value here + aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000)); + aGeoStat.RecalcSinCos(); + Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos); + } + + // translate? + if(!aTranslate.equalZero()) + { + Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY()))); + } +} + +// taking fObjectRotation instead of aGeo.nWink +sal_Bool SdrObjCustomShape::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const +{ + // get turn and shear +// double fRotate = (aGeo.nDrehWink / 100.0) * F_PI180; + double fRotate = fObjectRotation * F_PI180; + double fShearX = (aGeo.nShearWink / 100.0) * F_PI180; + + // get aRect, this is the unrotated snaprect + Rectangle aRectangle(aRect); + + sal_Bool bMirroredX = IsMirroredX(); + sal_Bool bMirroredY = IsMirroredY(); + if ( bMirroredX || bMirroredY ) + { // we have to retrieve the unmirrored rect + + GeoStat aNewGeo( aGeo ); + + if ( bMirroredX ) + { + Polygon aPol( Rect2Poly( aRect, aNewGeo ) ); + Rectangle aBoundRect( aPol.GetBoundRect() ); + + Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() ); + Point aRef2( aRef1.X(), aRef1.Y() + 1000 ); + USHORT i; + USHORT nPntAnz=aPol.GetSize(); + for (i=0; i<nPntAnz; i++) + { + MirrorPoint(aPol[i],aRef1,aRef2); + } + // Polygon wenden und etwas schieben + Polygon aPol0(aPol); + aPol[0]=aPol0[1]; + aPol[1]=aPol0[0]; + aPol[2]=aPol0[3]; + aPol[3]=aPol0[2]; + aPol[4]=aPol0[1]; + Poly2Rect(aPol,aRectangle,aNewGeo); + } + if ( bMirroredY ) + { + Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) ); + Rectangle aBoundRect( aPol.GetBoundRect() ); + + Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 ); + Point aRef2( aRef1.X() + 1000, aRef1.Y() ); + USHORT i; + USHORT nPntAnz=aPol.GetSize(); + for (i=0; i<nPntAnz; i++) + { + MirrorPoint(aPol[i],aRef1,aRef2); + } + // Polygon wenden und etwas schieben + Polygon aPol0(aPol); + aPol[0]=aPol0[1]; + aPol[1]=aPol0[0]; + aPol[2]=aPol0[3]; + aPol[3]=aPol0[2]; + aPol[4]=aPol0[1]; + Poly2Rect(aPol,aRectangle,aNewGeo); + } + } + + // fill other values + basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight()); + basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top()); + + // position maybe relative to anchorpos, convert + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // force MapUnit to 100th mm + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // postion + aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); + aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); + + // size + aScale.setX(ImplTwipsToMM(aScale.getX())); + aScale.setY(ImplTwipsToMM(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); + } + } + } + + // build matrix + rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX), + basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate, + aTranslate); + + return sal_False; +} + +sdr::contact::ViewContact* SdrObjCustomShape::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrObjCustomShape(*this); +} + +// #i33136# +bool SdrObjCustomShape::doConstructOrthogonal(const ::rtl::OUString& rName) +{ + bool bRetval(false); + static ::rtl::OUString Imps_sNameASOrtho_quadrat( RTL_CONSTASCII_USTRINGPARAM( "quadrat" ) ); + static ::rtl::OUString Imps_sNameASOrtho_round_quadrat( RTL_CONSTASCII_USTRINGPARAM( "round-quadrat" ) ); + static ::rtl::OUString Imps_sNameASOrtho_circle( RTL_CONSTASCII_USTRINGPARAM( "circle" ) ); + static ::rtl::OUString Imps_sNameASOrtho_circle_pie( RTL_CONSTASCII_USTRINGPARAM( "circle-pie" ) ); + static ::rtl::OUString Imps_sNameASOrtho_ring( RTL_CONSTASCII_USTRINGPARAM( "ring" ) ); + + if(Imps_sNameASOrtho_quadrat.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_round_quadrat.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_circle.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_circle_pie.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_ring.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + + return bRetval; +} + +// #i37011# centralize throw-away of render geometry +void SdrObjCustomShape::InvalidateRenderGeometry() +{ + mXRenderedCustomShape = 0L; + SdrObject::Free( mpLastShadowGeometry ); + mpLastShadowGeometry = 0L; +} + +// eof diff --git a/svx/source/svdraw/svdoattr.cxx b/svx/source/svdraw/svdoattr.cxx new file mode 100644 index 000000000000..81c1ca029ede --- /dev/null +++ b/svx/source/svdraw/svdoattr.cxx @@ -0,0 +1,180 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdoattr.hxx> +#include <svx/xpool.hxx> +#include "svditext.hxx" +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdattrx.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdorect.hxx> +#include <svx/svdocirc.hxx> +#include <svx/svdomeas.hxx> +#include <svl/smplhint.hxx> +#include <svl/itemiter.hxx> +#include <svx/xenum.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xtextit0.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbtoxy.hxx> +#include <svx/xftshit.hxx> + + +#include <editeng/colritem.hxx> +#include "editeng/fontitem.hxx" +#include <editeng/fhgtitem.hxx> + +//#include <editeng/charscaleitem.hxx> +#include <svx/xlnstcit.hxx> +#include <svx/xlnwtit.hxx> +#include <svl/style.hxx> +#include <svl/style.hxx> +#include <svl/whiter.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xlnedcit.hxx> +#include <editeng/adjitem.hxx> +#include <svx/xflbckit.hxx> +#include <svx/xtable.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/sdr/properties/attributeproperties.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include "svx/xlinjoit.hxx" +#include <svdoimp.hxx> + +////////////////////////////////////////////////////////////////////////////// + +sdr::properties::BaseProperties* SdrAttrObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::AttributeProperties(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrAttrObj,SdrObject); + +SdrAttrObj::SdrAttrObj() +{ +} + +SdrAttrObj::~SdrAttrObj() +{ +} + +const Rectangle& SdrAttrObj::GetSnapRect() const +{ + if(bSnapRectDirty) + { + ((SdrAttrObj*)this)->RecalcSnapRect(); + ((SdrAttrObj*)this)->bSnapRectDirty = false; + } + + return maSnapRect; +} + +void SdrAttrObj::SetModel(SdrModel* pNewModel) +{ + SdrModel* pOldModel = pModel; + + // test for correct pool in ItemSet; move to new pool if necessary + if(pNewModel && GetObjectItemPool() && GetObjectItemPool() != &pNewModel->GetItemPool()) + { + MigrateItemPool(GetObjectItemPool(), &pNewModel->GetItemPool(), pNewModel); + } + + // call parent + SdrObject::SetModel(pNewModel); + + // modify properties + GetProperties().SetModel(pOldModel, pNewModel); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// syntactical sugar for ItemSet accesses + +void __EXPORT SdrAttrObj::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + SfxSimpleHint *pSimple = PTR_CAST(SfxSimpleHint, &rHint); + BOOL bDataChg(pSimple && SFX_HINT_DATACHANGED == pSimple->GetId()); + + if(bDataChg) + { + Rectangle aBoundRect = GetLastBoundRect(); + SetBoundRectDirty(); + SetRectsDirty(sal_True); + + // This may have lead to object change + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect); + } +} + +sal_Int32 SdrAttrObj::ImpGetLineWdt() const +{ + sal_Int32 nRetval(0); + + if(XLINE_NONE != ((XLineStyleItem&)(GetObjectItem(XATTR_LINESTYLE))).GetValue()) + { + nRetval = ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue(); + } + + return nRetval; +} + +BOOL SdrAttrObj::HasFill() const +{ + return bClosedObj && ((XFillStyleItem&)(GetProperties().GetObjectItemSet().Get(XATTR_FILLSTYLE))).GetValue()!=XFILL_NONE; +} + +BOOL SdrAttrObj::HasLine() const +{ + return ((XLineStyleItem&)(GetProperties().GetObjectItemSet().Get(XATTR_LINESTYLE))).GetValue()!=XLINE_NONE; +} + +// eof diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx new file mode 100644 index 000000000000..b9d3e24592ee --- /dev/null +++ b/svx/source/svdraw/svdobj.cxx @@ -0,0 +1,3310 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <com/sun/star/lang/XComponent.hpp> + +#define _USE_MATH_DEFINES +#include <math.h> +#include <vcl/metaact.hxx> // fuer TakeContour +#include <vcl/cvtsvm.hxx> +#include <tools/line.hxx> +#include <tools/bigint.hxx> +#include <tools/diagnose_ex.h> +#include <vector> +#include <svx/svdobj.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdhdl.hxx> +#include <svx/svddrag.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdovirt.hxx> // Fuer Add/Del Ref +#include <svx/svdview.hxx> // fuer Dragging (Ortho abfragen) +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname +#include <svx/svdogrp.hxx> // Factory +#include <svx/svdopath.hxx> // Factory +#include <svx/svdoedge.hxx> // Factory +#include <svx/svdorect.hxx> // Factory +#include <svx/svdocirc.hxx> // Factory +#include <svx/svdotext.hxx> // Factory +#include <svx/svdomeas.hxx> // Factory +#include <svx/svdograf.hxx> // Factory +#include <svx/svdoole2.hxx> // Factory +#include <svx/svdocapt.hxx> // Factory +#include <svx/svdopage.hxx> // Factory +#include <svx/svdouno.hxx> // Factory +#include <svx/svdattrx.hxx> // NotPersistItems +#include <svx/svdoashp.hxx> +#include <svx/svdomedia.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xlnstcit.hxx> +#include <svx/xlnedcit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xflclit.hxx> +#include "svditer.hxx" +#include <svx/xlntrit.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xflftrit.hxx> +#include "svx/xlinjoit.hxx" +#include <svx/unopage.hxx> +#include <editeng/eeitem.hxx> +#include <svx/xenum.hxx> +#include <svx/xgrad.hxx> +#include <svx/xhatch.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/svdpool.hxx> +#include <editeng/editeng.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <svl/whiter.hxx> + +// #97849# +#include <svx/fmmodel.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/objface.hxx> +#include "svdoimp.hxx" +#include <vcl/graphictools.hxx> +#include <svtools/colorcfg.hxx> +#include <svx/sdr/properties/emptyproperties.hxx> +#include <svx/sdr/contact/viewcontactofsdrobj.hxx> +#include <svx/sdr/contact/viewcontactofgraphic.hxx> +#include <svx/sdr/contact/objectcontactofobjlistpainter.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/range/b2drange.hxx> +#include <svx/unoshape.hxx> +#include <vcl/virdev.hxx> +#include <basegfx/polygon/b2dpolypolygoncutter.hxx> +#include <drawinglayer/processor2d/contourextractor2d.hxx> +#include <drawinglayer/processor2d/linegeometryextractor2d.hxx> +#include <svx/polysc3d.hxx> +#include "svx/svdotable.hxx" +#include "svx/shapepropertynotifier.hxx" +#include <svx/sdrhittesthelper.hxx> +#include <svx/svdundo.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <svx/sdrobjectfilter.hxx> + +using namespace ::com::sun::star; + +// #104018# replace macros above with type-detecting methods +inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } +inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT0(SdrObjUserCall); + +SdrObjUserCall::~SdrObjUserCall() +{ +} + +void SdrObjUserCall::Changed(const SdrObject& /*rObj*/, SdrUserCallType /*eType*/, const Rectangle& /*rOldBoundRect*/) +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT0(SdrObjUserData); + +void SdrObjUserData::operator=(const SdrObjUserData& /*rData*/) // nicht implementiert +{ +} + +sal_Bool SdrObjUserData::operator==(const SdrObjUserData& /*rData*/) const // nicht implementiert +{ + return FALSE; +} + +sal_Bool SdrObjUserData::operator!=(const SdrObjUserData& /*rData*/) const // nicht implementiert +{ + return FALSE; +} + +SdrObjUserData::~SdrObjUserData() +{ +} + +FASTBOOL SdrObjUserData::HasMacro(const SdrObject* /*pObj*/) const +{ + return FALSE; +} + +SdrObject* SdrObjUserData::CheckMacroHit(const SdrObjMacroHitRec& rRec, const SdrObject* pObj) const +{ + if(pObj) + { + if(rRec.pPageView) + { + return SdrObjectPrimitiveHit(*pObj, rRec.aPos, rRec.nTol, *rRec.pPageView, rRec.pVisiLayer, false); + } + } + + return 0; +} + +Pointer SdrObjUserData::GetMacroPointer(const SdrObjMacroHitRec& /*rRec*/, const SdrObject* /*pObj*/) const +{ + return Pointer(POINTER_REFHAND); +} + +void SdrObjUserData::PaintMacro(OutputDevice& rOut, const Rectangle& /*rDirtyRect*/, const SdrObjMacroHitRec& /*rRec*/, const SdrObject* pObj) const +{ + if(!pObj) + return; + + const RasterOp eRop(rOut.GetRasterOp()); + const basegfx::B2DPolyPolygon aPolyPolygon(pObj->TakeXorPoly()); + const sal_uInt32 nCount(aPolyPolygon.count()); + + rOut.SetLineColor(COL_BLACK); + rOut.SetFillColor(); + rOut.SetRasterOp(ROP_INVERT); + + for(sal_uInt32 a(0); a < nCount; a++) + { + rOut.DrawPolyLine(aPolyPolygon.getB2DPolygon(a)); + } + + rOut.SetRasterOp(eRop); +} + +FASTBOOL SdrObjUserData::DoMacro(const SdrObjMacroHitRec& /*rRec*/, SdrObject* /*pObj*/) +{ + return FALSE; +} + +XubString SdrObjUserData::GetMacroPopupComment(const SdrObjMacroHitRec& /*rRec*/, const SdrObject* /*pObj*/) const +{ + return String(); +} + +void SdrObjUserDataList::Clear() +{ + USHORT nAnz=GetUserDataCount(); + for (USHORT i=0; i<nAnz; i++) { + delete GetUserData(i); + } + aList.Clear(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +DBG_NAME(SdrObjGeoData); + +SdrObjGeoData::SdrObjGeoData(): + pGPL(NULL), + bMovProt(FALSE), + bSizProt(FALSE), + bNoPrint(FALSE), + bClosedObj(FALSE), + mbVisible(true), + mnLayerID(0) +{ + DBG_CTOR(SdrObjGeoData,NULL); +} + +SdrObjGeoData::~SdrObjGeoData() +{ + DBG_DTOR(SdrObjGeoData,NULL); + delete pGPL; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT0(SdrObjPlusData); + +SdrObjPlusData::SdrObjPlusData(): + pBroadcast(NULL), + pUserDataList(NULL), + pGluePoints(NULL), + pAutoTimer(NULL) +{ +} + +SdrObjPlusData::~SdrObjPlusData() +{ + if (pBroadcast !=NULL) delete pBroadcast; + if (pUserDataList!=NULL) delete pUserDataList; + if (pGluePoints !=NULL) delete pGluePoints; + if (pAutoTimer !=NULL) delete pAutoTimer; +} + +SdrObjPlusData* SdrObjPlusData::Clone(SdrObject* pObj1) const +{ + SdrObjPlusData* pNeuPlusData=new SdrObjPlusData; + if (pUserDataList!=NULL) { + USHORT nAnz=pUserDataList->GetUserDataCount(); + if (nAnz!=0) { + pNeuPlusData->pUserDataList=new SdrObjUserDataList; + for (USHORT i=0; i<nAnz; i++) { + SdrObjUserData* pNeuUserData=pUserDataList->GetUserData(i)->Clone(pObj1); + if (pNeuUserData!=NULL) { + pNeuPlusData->pUserDataList->InsertUserData(pNeuUserData); + } else { + DBG_ERROR("SdrObjPlusData::Clone(): UserData.Clone() liefert NULL"); + } + } + } + } + if (pGluePoints!=NULL) pNeuPlusData->pGluePoints=new SdrGluePointList(*pGluePoints); + // MtfAnimator wird auch nicht mitkopiert + + // #i68101# + // copy object name, title and description + pNeuPlusData->aObjName = aObjName; + pNeuPlusData->aObjTitle = aObjTitle; + pNeuPlusData->aObjDescription = aObjDescription; + + if (pAutoTimer!=NULL) { + pNeuPlusData->pAutoTimer=new AutoTimer; + // Handler, etc. nicht mitkopieren! + } + + // For HTMLName: Do not clone, leave uninitialized (empty string) + + return pNeuPlusData; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@@@@ @@@@@@ @@@@@ @@@@ @@@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@ @@@@@ @@@@ @@@@@ @@@@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrObject::CreateObjectSpecificProperties() +{ + return new sdr::properties::EmptyProperties(*this); +} + +sdr::properties::BaseProperties& SdrObject::GetProperties() const +{ + if(!mpProperties) + { + const_cast< SdrObject* >(this)->mpProperties = + const_cast< SdrObject* >(this)->CreateObjectSpecificProperties(); + } + + return *mpProperties; +} + +////////////////////////////////////////////////////////////////////////////// +// ObjectUser section + +void SdrObject::AddObjectUser(sdr::ObjectUser& rNewUser) +{ + maObjectUsers.push_back(&rNewUser); +} + +void SdrObject::RemoveObjectUser(sdr::ObjectUser& rOldUser) +{ + const ::sdr::ObjectUserVector::iterator aFindResult = ::std::find(maObjectUsers.begin(), maObjectUsers.end(), &rOldUser); + if(aFindResult != maObjectUsers.end()) + { + maObjectUsers.erase(aFindResult); + } +} + +////////////////////////////////////////////////////////////////////////////// +// #110094# DrawContact section + +sdr::contact::ViewContact* SdrObject::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrObj(*this); +} + +sdr::contact::ViewContact& SdrObject::GetViewContact() const +{ + if(!mpViewContact) + { + const_cast< SdrObject* >(this)->mpViewContact = + const_cast< SdrObject* >(this)->CreateObjectSpecificViewContact(); + } + + return *mpViewContact; +} + +// DrawContact support: Methods for handling Object changes +void SdrObject::ActionChanged() const +{ + // Do necessary ViewContact actions + GetViewContact().ActionChanged(); +} + +////////////////////////////////////////////////////////////////////////////// + +void SdrObject::SetBoundRectDirty() +{ + aOutRect = Rectangle(); +} + +////////////////////////////////////////////////////////////////////////////// + +DBG_NAME(SdrObject); +TYPEINIT1(SdrObject,SfxListener); + +SdrObject::SdrObject() + :mpProperties(0L) + ,mpViewContact(0L) + ,pObjList(NULL) + ,pPage(NULL) + ,pModel(NULL) + ,pUserCall(NULL) + ,pPlusData(NULL) + ,nOrdNum(0) + ,mnNavigationPosition(SAL_MAX_UINT32) + ,mnLayerID(0) + ,mpSvxShape( NULL ) + ,maWeakUnoShape() +{ + DBG_CTOR(SdrObject,NULL); + bVirtObj =FALSE; + bSnapRectDirty =TRUE; + bNetLock =FALSE; + bInserted =FALSE; + bGrouped =FALSE; + bMovProt =FALSE; + bSizProt =FALSE; + bNoPrint =FALSE; + bEmptyPresObj =FALSE; + bNotVisibleAsMaster=FALSE; + bClosedObj =FALSE; + mbVisible = true; + + // #i25616# + mbLineIsOutsideGeometry = sal_False; + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_False; + + //#110094#-1 + //bWriterFlyFrame =FALSE; + + bNotMasterCachable=FALSE; + bIsEdge=FALSE; + bIs3DObj=FALSE; + bMarkProt=FALSE; + bIsUnoObj=FALSE; +} + +SdrObject::~SdrObject() +{ + // tell all the registered ObjectUsers that the page is in destruction + ::sdr::ObjectUserVector aListCopy(maObjectUsers.begin(), maObjectUsers.end()); + for(::sdr::ObjectUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++) + { + sdr::ObjectUser* pObjectUser = *aIterator; + DBG_ASSERT(pObjectUser, "SdrObject::~SdrObject: corrupt ObjectUser list (!)"); + pObjectUser->ObjectInDestruction(*this); + } + + // Clear the vector. This means that user do not need to call RemoveObjectUser() + // when they get called from ObjectInDestruction(). + maObjectUsers.clear(); + + try + { + SvxShape* pSvxShape = getSvxShape(); + if ( pSvxShape ) + { + OSL_ENSURE(!pSvxShape->HasSdrObjectOwnership(),"Please check where this call come from and replace it with SdrObject::Free"); + pSvxShape->InvalidateSdrObject(); + uno::Reference< lang::XComponent > xShapeComp( getWeakUnoShape(), uno::UNO_QUERY_THROW ); + xShapeComp->dispose(); + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + DBG_DTOR(SdrObject,NULL); + SendUserCall(SDRUSERCALL_DELETE, GetLastBoundRect()); + if (pPlusData!=NULL) delete pPlusData; + + if(mpProperties) + { + delete mpProperties; + mpProperties = 0L; + } + + // #110094# + if(mpViewContact) + { + delete mpViewContact; + mpViewContact = 0L; + } +} + +void SdrObject::Free( SdrObject*& _rpObject ) +{ + SdrObject* pObject = _rpObject; _rpObject = NULL; + if ( pObject == NULL ) + // nothing to do + return; + + SvxShape* pShape = pObject->getSvxShape(); + if ( pShape && pShape->HasSdrObjectOwnership() ) + // only the shape is allowed to delete me, and will reset the ownership before doing so + return; + + delete pObject; +} + +SdrObjPlusData* SdrObject::NewPlusData() const +{ + return new SdrObjPlusData; +} + +void SdrObject::SetRectsDirty(sal_Bool bNotMyself) +{ + if (!bNotMyself) { + SetBoundRectDirty(); + bSnapRectDirty=TRUE; + } + if (pObjList!=NULL) { + pObjList->SetRectsDirty(); + } +} + +void SdrObject::SetModel(SdrModel* pNewModel) +{ + if(pNewModel && pPage) + { + if(pPage->GetModel() != pNewModel) + { + pPage = NULL; + } + } + + // update listeners at possible api wrapper object + if( pModel != pNewModel ) + { + SvxShape* pShape = getSvxShape(); + if( pShape ) + pShape->ChangeModel( pNewModel ); + } + + pModel = pNewModel; +} + +void SdrObject::SetObjList(SdrObjList* pNewObjList) +{ + pObjList=pNewObjList; +} + +void SdrObject::SetPage(SdrPage* pNewPage) +{ + pPage=pNewPage; + if (pPage!=NULL) { + SdrModel* pMod=pPage->GetModel(); + if (pMod!=pModel && pMod!=NULL) { + SetModel(pMod); + }} +} + +// init global static itempool +SdrItemPool* SdrObject::mpGlobalItemPool = NULL; + +SdrItemPool& SdrObject::GetGlobalDrawObjectItemPool() +{ + if(!mpGlobalItemPool) + { + mpGlobalItemPool = new SdrItemPool(); + SfxItemPool* pGlobalOutlPool = EditEngine::CreatePool(); + mpGlobalItemPool->SetSecondaryPool(pGlobalOutlPool); + mpGlobalItemPool->SetDefaultMetric((SfxMapUnit)SdrEngineDefaults::GetMapUnit()); + mpGlobalItemPool->FreezeIdRanges(); + } + + return *mpGlobalItemPool; +} + +void SdrObject::FreeGlobalDrawObjectItemPool() +{ + // code for deletion of GlobalItemPool + if(mpGlobalItemPool) + { + SfxItemPool* pGlobalOutlPool = mpGlobalItemPool->GetSecondaryPool(); + SfxItemPool::Free(mpGlobalItemPool); + SfxItemPool::Free(pGlobalOutlPool); + } +} + +SdrItemPool* SdrObject::GetObjectItemPool() const +{ + if(pModel) + return (SdrItemPool*)(&pModel->GetItemPool()); + + // use a static global default pool + return &SdrObject::GetGlobalDrawObjectItemPool(); +} + +UINT32 SdrObject::GetObjInventor() const +{ + return SdrInventor; +} + +UINT16 SdrObject::GetObjIdentifier() const +{ + return UINT16(OBJ_NONE); +} + +void SdrObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bRotateFreeAllowed=FALSE; + rInfo.bMirrorFreeAllowed=FALSE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =FALSE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bCanConvToPath =FALSE; + rInfo.bCanConvToPoly =FALSE; + rInfo.bCanConvToContour = FALSE; + rInfo.bCanConvToPathLineToArea=FALSE; + rInfo.bCanConvToPolyLineToArea=FALSE; +} + +SdrLayerID SdrObject::GetLayer() const +{ + return mnLayerID; +} + +void SdrObject::getMergedHierarchyLayerSet(SetOfByte& rSet) const +{ + rSet.Set(GetLayer()); + SdrObjList* pOL=GetSubList(); + if (pOL!=NULL) { + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG nObjNum=0; nObjNum<nObjAnz; nObjNum++) { + pOL->GetObj(nObjNum)->getMergedHierarchyLayerSet(rSet); + } + } +} + +void SdrObject::NbcSetLayer(SdrLayerID nLayer) +{ + if(GetLayer() != nLayer) + { + mnLayerID = nLayer; + } +} + +void SdrObject::SetLayer(SdrLayerID nLayer) +{ + NbcSetLayer(nLayer); + SetChanged(); + BroadcastObjectChange(); +} + +void SdrObject::AddListener(SfxListener& rListener) +{ + ImpForcePlusData(); + if (pPlusData->pBroadcast==NULL) pPlusData->pBroadcast=new SfxBroadcaster; + rListener.StartListening(*pPlusData->pBroadcast); +} + +void SdrObject::RemoveListener(SfxListener& rListener) +{ + if (pPlusData!=NULL && pPlusData->pBroadcast!=NULL) { + rListener.EndListening(*pPlusData->pBroadcast); + if (!pPlusData->pBroadcast->HasListeners()) { + delete pPlusData->pBroadcast; + pPlusData->pBroadcast=NULL; + } + } +} + +void SdrObject::AddReference(SdrVirtObj& rVrtObj) +{ + AddListener(rVrtObj); +} + +void SdrObject::DelReference(SdrVirtObj& rVrtObj) +{ + RemoveListener(rVrtObj); +} + +AutoTimer* SdrObject::ForceAutoTimer() +{ + ImpForcePlusData(); + if (pPlusData->pAutoTimer==NULL) pPlusData->pAutoTimer=new AutoTimer; + return pPlusData->pAutoTimer; +} + +FASTBOOL SdrObject::HasRefPoint() const +{ + return FALSE; +} + +Point SdrObject::GetRefPoint() const +{ + return GetCurrentBoundRect().Center(); +} + +void SdrObject::SetRefPoint(const Point& /*rPnt*/) +{ +} + +SdrObjList* SdrObject::GetSubList() const +{ + return NULL; +} + +SdrObject* SdrObject::GetUpGroup() const +{ + return pObjList!=NULL ? pObjList->GetOwnerObj() : NULL; +} + +void SdrObject::SetName(const String& rStr) +{ + if(rStr.Len() && !pPlusData) + { + ImpForcePlusData(); + } + + if(pPlusData && pPlusData->aObjName != rStr) + { + // --> OD 2009-07-09 #i73249# + // Undo/Redo for setting object's name + bool bUndo( false ); + if ( GetModel() && GetModel()->IsUndoEnabled() ) + { + bUndo = true; + SdrUndoAction* pUndoAction = + GetModel()->GetSdrUndoFactory().CreateUndoObjectStrAttr( + *this, + SdrUndoObjStrAttr::OBJ_NAME, + GetName(), + rStr ); + GetModel()->BegUndo( pUndoAction->GetComment() ); + GetModel()->AddUndo( pUndoAction ); + } + // <-- + pPlusData->aObjName = rStr; + // --> OD 2009-07-09 #i73249# + if ( bUndo ) + { + GetModel()->EndUndo(); + } + // <-- + SetChanged(); + BroadcastObjectChange(); + } +} + +String SdrObject::GetName() const +{ + if(pPlusData) + { + return pPlusData->aObjName; + } + + return String(); +} + +void SdrObject::SetTitle(const String& rStr) +{ + if(rStr.Len() && !pPlusData) + { + ImpForcePlusData(); + } + + if(pPlusData && pPlusData->aObjTitle != rStr) + { + // --> OD 2009-07-13 #i73249# + // Undo/Redo for setting object's title + bool bUndo( false ); + if ( GetModel() && GetModel()->IsUndoEnabled() ) + { + bUndo = true; + SdrUndoAction* pUndoAction = + GetModel()->GetSdrUndoFactory().CreateUndoObjectStrAttr( + *this, + SdrUndoObjStrAttr::OBJ_TITLE, + GetTitle(), + rStr ); + GetModel()->BegUndo( pUndoAction->GetComment() ); + GetModel()->AddUndo( pUndoAction ); + } + // <-- + pPlusData->aObjTitle = rStr; + // --> OD 2009-07-13 #i73249# + if ( bUndo ) + { + GetModel()->EndUndo(); + } + // <-- + SetChanged(); + BroadcastObjectChange(); + } +} + +String SdrObject::GetTitle() const +{ + if(pPlusData) + { + return pPlusData->aObjTitle; + } + + return String(); +} + +void SdrObject::SetDescription(const String& rStr) +{ + if(rStr.Len() && !pPlusData) + { + ImpForcePlusData(); + } + + if(pPlusData && pPlusData->aObjDescription != rStr) + { + // --> OD 2009-07-13 #i73249# + // Undo/Redo for setting object's description + bool bUndo( false ); + if ( GetModel() && GetModel()->IsUndoEnabled() ) + { + bUndo = true; + SdrUndoAction* pUndoAction = + GetModel()->GetSdrUndoFactory().CreateUndoObjectStrAttr( + *this, + SdrUndoObjStrAttr::OBJ_DESCRIPTION, + GetDescription(), + rStr ); + GetModel()->BegUndo( pUndoAction->GetComment() ); + GetModel()->AddUndo( pUndoAction ); + } + // <-- + pPlusData->aObjDescription = rStr; + // --> OD 2009-07-13 #i73249# + if ( bUndo ) + { + GetModel()->EndUndo(); + } + // <-- + SetChanged(); + BroadcastObjectChange(); + } +} + +String SdrObject::GetDescription() const +{ + if(pPlusData) + { + return pPlusData->aObjDescription; + } + + return String(); +} + +void SdrObject::SetHTMLName(const String& rStr) +{ + if(rStr.Len() && !pPlusData) + { + ImpForcePlusData(); + } + + if(pPlusData && pPlusData->aObjName != rStr) + { + pPlusData->aHTMLName = rStr; + SetChanged(); + } +} + +String SdrObject::GetHTMLName() const +{ + if(pPlusData) + { + return pPlusData->aHTMLName; + } + + return String(); +} + +UINT32 SdrObject::GetOrdNum() const +{ + if (pObjList!=NULL) { + if (pObjList->IsObjOrdNumsDirty()) { + pObjList->RecalcObjOrdNums(); + } + } else ((SdrObject*)this)->nOrdNum=0; + return nOrdNum; +} + + + + +sal_uInt32 SdrObject::GetNavigationPosition (void) +{ + if (pObjList!=NULL && pObjList->RecalcNavigationPositions()) + { + return mnNavigationPosition; + } + else + return GetOrdNum(); +} + + + + +void SdrObject::SetNavigationPosition (const sal_uInt32 nNewPosition) +{ + mnNavigationPosition = nNewPosition; +} + + + + +// #111111# +// To make clearer that this method may trigger RecalcBoundRect and thus may be +// expensive and somtimes problematic (inside a bigger object change You will get +// non-useful BoundRects sometimes) i rename that method from GetBoundRect() to +// GetCurrentBoundRect(). +const Rectangle& SdrObject::GetCurrentBoundRect() const +{ + if(aOutRect.IsEmpty()) + { + const_cast< SdrObject* >(this)->RecalcBoundRect(); + } + + return aOutRect; +} + +// #111111# +// To have a possibility to get the last calculated BoundRect e.g for producing +// the first rectangle for repaints (old and new need to be used) without forcing +// a RecalcBoundRect (which may be problematical and expensive sometimes) i add here +// a new method for accessing the last BoundRect. +const Rectangle& SdrObject::GetLastBoundRect() const +{ + return aOutRect; +} + +void SdrObject::RecalcBoundRect() +{ + // #i101680# suppress BoundRect calculations on import(s) + if(pModel && pModel->isLocked() ) + return; + + // central new method which will calculate the BoundRect using primitive geometry + if(aOutRect.IsEmpty()) + { + const drawinglayer::primitive2d::Primitive2DSequence xPrimitives(GetViewContact().getViewIndependentPrimitive2DSequence()); + + if(xPrimitives.hasElements()) + { + // use neutral ViewInformation and get the range of the primitives + const drawinglayer::geometry::ViewInformation2D aViewInformation2D(0); + const basegfx::B2DRange aRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xPrimitives, aViewInformation2D)); + + if(!aRange.isEmpty()) + { + aOutRect = Rectangle( + (sal_Int32)floor(aRange.getMinX()), (sal_Int32)floor(aRange.getMinY()), + (sal_Int32)ceil(aRange.getMaxX()), (sal_Int32)ceil(aRange.getMaxY())); + return; + } + } + } +} + +void SdrObject::BroadcastObjectChange() const +{ + if( pModel && pModel->isLocked() ) + return; + + sal_Bool bPlusDataBroadcast(pPlusData && pPlusData->pBroadcast); + sal_Bool bObjectChange(IsInserted() && pModel); + + if(bPlusDataBroadcast || bObjectChange) + { + SdrHint aHint(*this); + + if(bPlusDataBroadcast) + { + pPlusData->pBroadcast->Broadcast(aHint); + } + + if(bObjectChange) + { + pModel->Broadcast(aHint); + } + } +} + +void SdrObject::SetChanged() +{ + // #110094#-11 + // For test purposes, use the new ViewContact for change + // notification now. + ActionChanged(); + + if(IsInserted() && pModel) + { + pModel->SetChanged(); + } +} + +// Tooling for painting a single object to a OutputDevice. +sal_Bool SdrObject::SingleObjectPainter(OutputDevice& rOut) const +{ + sdr::contact::SdrObjectVector aObjectVector; + aObjectVector.push_back(const_cast< SdrObject* >(this)); + + sdr::contact::ObjectContactOfObjListPainter aPainter(rOut, aObjectVector, GetPage()); + sdr::contact::DisplayInfo aDisplayInfo; + + // do processing + aPainter.ProcessDisplay(aDisplayInfo); + + return sal_True; +} + +BOOL SdrObject::LineGeometryUsageIsNecessary() const +{ + XLineStyle eXLS = (XLineStyle)((const XLineStyleItem&)GetMergedItem(XATTR_LINESTYLE)).GetValue(); + return (eXLS != XLINE_NONE); +} + +SdrObject* SdrObject::Clone() const +{ + SdrObject* pObj=SdrObjFactory::MakeNewObject(GetObjInventor(),GetObjIdentifier(),NULL); + if (pObj!=NULL) { + pObj->pModel=pModel; + pObj->pPage=pPage; + *pObj=*this; + } + return pObj; +} + +void SdrObject::operator=(const SdrObject& rObj) +{ + if(mpProperties) + { + delete mpProperties; + mpProperties = 0L; + } + + // #110094# + if(mpViewContact) + { + delete mpViewContact; + mpViewContact = 0L; + } + + // The Clone() method uses the local copy constructor from the individual + // sdr::properties::BaseProperties class. Since the target class maybe for another + // draw object a SdrObject needs to be provided, as in the nromal constructor. + mpProperties = &rObj.GetProperties().Clone(*this); + + pModel =rObj.pModel; + aOutRect=rObj.aOutRect; + mnLayerID = rObj.mnLayerID; + aAnchor =rObj.aAnchor; + bVirtObj=rObj.bVirtObj; + bSizProt=rObj.bSizProt; + bMovProt=rObj.bMovProt; + bNoPrint=rObj.bNoPrint; + mbVisible=rObj.mbVisible; + bMarkProt=rObj.bMarkProt; + //EmptyPresObj wird nicht kopiert: nun doch! (25-07-1995, Joe) + bEmptyPresObj =rObj.bEmptyPresObj; + //NotVisibleAsMaster wird nicht kopiert: nun doch! (25-07-1995, Joe) + bNotVisibleAsMaster=rObj.bNotVisibleAsMaster; + bSnapRectDirty=TRUE; //rObj.bSnapRectDirty; + bNotMasterCachable=rObj.bNotMasterCachable; + if (pPlusData!=NULL) { delete pPlusData; pPlusData=NULL; } + if (rObj.pPlusData!=NULL) { + pPlusData=rObj.pPlusData->Clone(this); + } + if (pPlusData!=NULL && pPlusData->pBroadcast!=NULL) { + delete pPlusData->pBroadcast; // der Broadcaster wird nicht mitkopiert + pPlusData->pBroadcast=NULL; + } +} + +void SdrObject::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulNONE); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrObject::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralNONE); +} + +void SdrObject::ImpTakeDescriptionStr(USHORT nStrCacheID, XubString& rStr, USHORT nVal) const +{ + rStr = ImpGetResStr(nStrCacheID); + + sal_Char aSearchText1[] = "%1"; + sal_Char aSearchText2[] = "%2"; + xub_StrLen nPos = rStr.SearchAscii(aSearchText1); + + if(nPos != STRING_NOTFOUND) + { + rStr.Erase(nPos, 2); + + XubString aObjName; + + TakeObjNameSingul(aObjName); + rStr.Insert(aObjName, nPos); + } + + nPos = rStr.SearchAscii(aSearchText2); + + if(nPos != STRING_NOTFOUND) + { + rStr.Erase(nPos, 2); + rStr.Insert(UniString::CreateFromInt32(nVal), nPos); + } +} + +XubString SdrObject::GetWinkStr(long nWink, FASTBOOL bNoDegChar) const +{ + XubString aStr; + if (pModel!=NULL) { + pModel->TakeWinkStr(nWink,aStr,bNoDegChar); + } + return aStr; +} + +XubString SdrObject::GetMetrStr(long nVal, MapUnit /*eWantMap*/, FASTBOOL bNoUnitChars) const +{ + XubString aStr; + if (pModel!=NULL) { + pModel->TakeMetricStr(nVal,aStr,bNoUnitChars); + } + return aStr; +} + +basegfx::B2DPolyPolygon SdrObject::TakeXorPoly() const +{ + basegfx::B2DPolyPolygon aRetval; + const Rectangle aR(GetCurrentBoundRect()); + const basegfx::B2DRange aRange(aR.Left(), aR.Top(), aR.Right(), aR.Bottom()); + aRetval.append(basegfx::tools::createPolygonFromRect(aRange)); + + return aRetval; +} + +basegfx::B2DPolyPolygon SdrObject::TakeContour() const +{ + basegfx::B2DPolyPolygon aRetval; + + // create cloned object without text, but with XLINE_SOLID, + // COL_BLACK as line color and XFILL_NONE + SdrObject* pClone = Clone(); + + if(pClone) + { + const SdrTextObj* pTextObj = dynamic_cast< const SdrTextObj* >(this); + + if(pTextObj) + { + // no text and no text animation + pClone->SetMergedItem(SdrTextAniKindItem(SDRTEXTANI_NONE)); + pClone->SetOutlinerParaObject(0); + } + + const SdrEdgeObj* pEdgeObj = dynamic_cast< const SdrEdgeObj* >(this); + + if(pEdgeObj) + { + // create connections if connector, will be cleaned up when + // deleting the connector again + SdrObject* pLeft = pEdgeObj->GetConnectedNode(TRUE); + SdrObject* pRight = pEdgeObj->GetConnectedNode(FALSE); + + if(pLeft) + { + pClone->ConnectToNode(TRUE, pLeft); + } + + if(pRight) + { + pClone->ConnectToNode(FALSE, pRight); + } + } + + SfxItemSet aNewSet(*GetObjectItemPool()); + + // #i101980# ignore LineWidth; that's what the old implementation + // did. With linewidth, the result may be huge due to fat/thick + // line decompositions + aNewSet.Put(XLineWidthItem(0)); + + // solid black lines and no fill + aNewSet.Put(XLineStyleItem(XLINE_SOLID)); + aNewSet.Put(XLineColorItem(String(), Color(COL_BLACK))); + aNewSet.Put(XFillStyleItem(XFILL_NONE)); + pClone->SetMergedItemSet(aNewSet); + + // get sequence from clone + const sdr::contact::ViewContact& rVC(pClone->GetViewContact()); + const drawinglayer::primitive2d::Primitive2DSequence xSequence(rVC.getViewIndependentPrimitive2DSequence()); + + if(xSequence.hasElements()) + { + // use neutral ViewInformation + const drawinglayer::geometry::ViewInformation2D aViewInformation2D(0); + + // create extractor, process and get result + drawinglayer::processor2d::ContourExtractor2D aExtractor(aViewInformation2D); + aExtractor.process(xSequence); + const std::vector< basegfx::B2DPolyPolygon >& rResult(aExtractor.getExtractedContour()); + const sal_uInt32 nSize(rResult.size()); + + // when count is one, it is implied that the object has only it's normal + // contour anyways and TakeCountour() is to return an empty PolyPolygon + // (see old implementation for historical reasons) + if(nSize > 1) + { + // the topology for contour is correctly a vector of PolyPolygons; for + // historical reasons cut it back to a single PolyPolygon here + for(sal_uInt32 a(0); a < nSize; a++) + { + aRetval.append(rResult[a]); + } + } + } + + delete pClone; + } + + return aRetval; +} + +sal_uInt32 SdrObject::GetHdlCount() const +{ + return 8L; +} + +SdrHdl* SdrObject::GetHdl(sal_uInt32 nHdlNum) const +{ + SdrHdl* pH=NULL; + const Rectangle& rR=GetSnapRect(); + switch (nHdlNum) { + case 0: pH=new SdrHdl(rR.TopLeft(), HDL_UPLFT); break; // Oben links + case 1: pH=new SdrHdl(rR.TopCenter(), HDL_UPPER); break; // Oben + case 2: pH=new SdrHdl(rR.TopRight(), HDL_UPRGT); break; // Oben rechts + case 3: pH=new SdrHdl(rR.LeftCenter(), HDL_LEFT ); break; // Links + case 4: pH=new SdrHdl(rR.RightCenter(), HDL_RIGHT); break; // Rechts + case 5: pH=new SdrHdl(rR.BottomLeft(), HDL_LWLFT); break; // Unten links + case 6: pH=new SdrHdl(rR.BottomCenter(),HDL_LOWER); break; // Unten + case 7: pH=new SdrHdl(rR.BottomRight(), HDL_LWRGT); break; // Unten rechts + } + return pH; +} + +sal_uInt32 SdrObject::GetPlusHdlCount(const SdrHdl& /*rHdl*/) const +{ + return 0L; +} + +SdrHdl* SdrObject::GetPlusHdl(const SdrHdl& /*rHdl*/, sal_uInt32 /*nPlNum*/) const +{ + return 0L; +} + +void SdrObject::AddToHdlList(SdrHdlList& rHdlList) const +{ + sal_uInt32 nAnz=GetHdlCount(); + for (sal_uInt32 i=0L; i<nAnz; i++) { + SdrHdl* pHdl=GetHdl(i); + if (pHdl!=NULL) { + rHdlList.AddHdl(pHdl); + } + } +} + +Rectangle SdrObject::ImpDragCalcRect(const SdrDragStat& rDrag) const +{ + Rectangle aTmpRect(GetSnapRect()); + Rectangle aRect(aTmpRect); + const SdrHdl* pHdl=rDrag.GetHdl(); + SdrHdlKind eHdl=pHdl==NULL ? HDL_MOVE : pHdl->GetKind(); + FASTBOOL bEcke=(eHdl==HDL_UPLFT || eHdl==HDL_UPRGT || eHdl==HDL_LWLFT || eHdl==HDL_LWRGT); + FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho(); + FASTBOOL bBigOrtho=bEcke && bOrtho && rDrag.GetView()->IsBigOrtho(); + Point aPos(rDrag.GetNow()); + FASTBOOL bLft=(eHdl==HDL_UPLFT || eHdl==HDL_LEFT || eHdl==HDL_LWLFT); + FASTBOOL bRgt=(eHdl==HDL_UPRGT || eHdl==HDL_RIGHT || eHdl==HDL_LWRGT); + FASTBOOL bTop=(eHdl==HDL_UPRGT || eHdl==HDL_UPPER || eHdl==HDL_UPLFT); + FASTBOOL bBtm=(eHdl==HDL_LWRGT || eHdl==HDL_LOWER || eHdl==HDL_LWLFT); + if (bLft) aTmpRect.Left() =aPos.X(); + if (bRgt) aTmpRect.Right() =aPos.X(); + if (bTop) aTmpRect.Top() =aPos.Y(); + if (bBtm) aTmpRect.Bottom()=aPos.Y(); + if (bOrtho) { // Ortho + long nWdt0=aRect.Right() -aRect.Left(); + long nHgt0=aRect.Bottom()-aRect.Top(); + long nXMul=aTmpRect.Right() -aTmpRect.Left(); + long nYMul=aTmpRect.Bottom()-aTmpRect.Top(); + long nXDiv=nWdt0; + long nYDiv=nHgt0; + FASTBOOL bXNeg=(nXMul<0)!=(nXDiv<0); + FASTBOOL bYNeg=(nYMul<0)!=(nYDiv<0); + nXMul=Abs(nXMul); + nYMul=Abs(nYMul); + nXDiv=Abs(nXDiv); + nYDiv=Abs(nYDiv); + Fraction aXFact(nXMul,nXDiv); // Fractions zum kuerzen + Fraction aYFact(nYMul,nYDiv); // und zum vergleichen + nXMul=aXFact.GetNumerator(); + nYMul=aYFact.GetNumerator(); + nXDiv=aXFact.GetDenominator(); + nYDiv=aYFact.GetDenominator(); + if (bEcke) { // Eckpunkthandles + FASTBOOL bUseX=(aXFact<aYFact) != bBigOrtho; + if (bUseX) { + long nNeed=long(BigInt(nHgt0)*BigInt(nXMul)/BigInt(nXDiv)); + if (bYNeg) nNeed=-nNeed; + if (bTop) aTmpRect.Top()=aTmpRect.Bottom()-nNeed; + if (bBtm) aTmpRect.Bottom()=aTmpRect.Top()+nNeed; + } else { + long nNeed=long(BigInt(nWdt0)*BigInt(nYMul)/BigInt(nYDiv)); + if (bXNeg) nNeed=-nNeed; + if (bLft) aTmpRect.Left()=aTmpRect.Right()-nNeed; + if (bRgt) aTmpRect.Right()=aTmpRect.Left()+nNeed; + } + } else { // Scheitelpunkthandles + if ((bLft || bRgt) && nXDiv!=0) { + long nHgt0b=aRect.Bottom()-aRect.Top(); + long nNeed=long(BigInt(nHgt0b)*BigInt(nXMul)/BigInt(nXDiv)); + aTmpRect.Top()-=(nNeed-nHgt0b)/2; + aTmpRect.Bottom()=aTmpRect.Top()+nNeed; + } + if ((bTop || bBtm) && nYDiv!=0) { + long nWdt0b=aRect.Right()-aRect.Left(); + long nNeed=long(BigInt(nWdt0b)*BigInt(nYMul)/BigInt(nYDiv)); + aTmpRect.Left()-=(nNeed-nWdt0b)/2; + aTmpRect.Right()=aTmpRect.Left()+nNeed; + } + } + } + aTmpRect.Justify(); + return aTmpRect; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrObject::hasSpecialDrag() const +{ + return false; +} + +bool SdrObject::supportsFullDrag() const +{ + return true; +} + +SdrObject* SdrObject::getFullDragClone() const +{ + // default uses simple clone + return Clone(); +} + +bool SdrObject::beginSpecialDrag(SdrDragStat& rDrag) const +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + + SdrHdlKind eHdl = (pHdl == NULL) ? HDL_MOVE : pHdl->GetKind(); + + if(eHdl==HDL_UPLFT || eHdl==HDL_UPPER || eHdl==HDL_UPRGT || + eHdl==HDL_LEFT || eHdl==HDL_RIGHT || eHdl==HDL_LWLFT || + eHdl==HDL_LOWER || eHdl==HDL_LWRGT) + { + return true; + } + + return false; +} + +bool SdrObject::applySpecialDrag(SdrDragStat& rDrag) +{ + Rectangle aNewRect(ImpDragCalcRect(rDrag)); + + if(aNewRect != GetSnapRect()) + { + NbcSetSnapRect(aNewRect); + } + + return true; +} + +String SdrObject::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const +{ + return String(); +} + +basegfx::B2DPolyPolygon SdrObject::getSpecialDragPoly(const SdrDragStat& /*rDrag*/) const +{ + // default has nothing to add + return basegfx::B2DPolyPolygon(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Create +FASTBOOL SdrObject::BegCreate(SdrDragStat& rStat) +{ + rStat.SetOrtho4Possible(); + Rectangle aRect1(rStat.GetStart(), rStat.GetNow()); + aRect1.Justify(); + rStat.SetActionRect(aRect1); + aOutRect = aRect1; + return TRUE; +} + +FASTBOOL SdrObject::MovCreate(SdrDragStat& rStat) +{ + rStat.TakeCreateRect(aOutRect); + rStat.SetActionRect(aOutRect); + aOutRect.Justify(); + + // #i101648# for naked (non-derived) SdrObjects, do not invalidate aOutRect + // by calling SetBoundRectDirty(); aOutRect IS the geometry for such objects. + // No derivation implementation calls the parent implementation, so this will + // cause no further prolems + // + // SetBoundRectDirty(); + // bSnapRectDirty=TRUE; + + return TRUE; +} + +FASTBOOL SdrObject::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + rStat.TakeCreateRect(aOutRect); + aOutRect.Justify(); + + // #i101648# see description at MovCreate + // + // SetRectsDirty(); + + return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); +} + +void SdrObject::BrkCreate(SdrDragStat& /*rStat*/) +{ +} + +FASTBOOL SdrObject::BckCreate(SdrDragStat& /*rStat*/) +{ + return FALSE; +} + +basegfx::B2DPolyPolygon SdrObject::TakeCreatePoly(const SdrDragStat& rDrag) const +{ + Rectangle aRect1; + rDrag.TakeCreateRect(aRect1); + aRect1.Justify(); + + basegfx::B2DPolyPolygon aRetval; + const basegfx::B2DRange aRange(aRect1.Left(), aRect1.Top(), aRect1.Right(), aRect1.Bottom()); + aRetval.append(basegfx::tools::createPolygonFromRect(aRange)); + return aRetval; +} + +Pointer SdrObject::GetCreatePointer() const +{ + return Pointer(POINTER_CROSS); +} + +// Transformationen +void SdrObject::NbcMove(const Size& rSiz) +{ + MoveRect(aOutRect,rSiz); + SetRectsDirty(); +} + +void SdrObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0); + FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0); + if (bXMirr || bYMirr) { + Point aRef1(GetSnapRect().Center()); + if (bXMirr) { + Point aRef2(aRef1); + aRef2.Y()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + if (bYMirr) { + Point aRef2(aRef1); + aRef2.X()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + } + ResizeRect(aOutRect,rRef,xFact,yFact); + SetRectsDirty(); +} + +void SdrObject::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + SetGlueReallyAbsolute(TRUE); + aOutRect.Move(-rRef.X(),-rRef.Y()); + Rectangle R(aOutRect); + if (sn==1.0 && cs==0.0) { // 90deg + aOutRect.Left() =-R.Bottom(); + aOutRect.Right() =-R.Top(); + aOutRect.Top() =R.Left(); + aOutRect.Bottom()=R.Right(); + } else if (sn==0.0 && cs==-1.0) { // 180deg + aOutRect.Left() =-R.Right(); + aOutRect.Right() =-R.Left(); + aOutRect.Top() =-R.Bottom(); + aOutRect.Bottom()=-R.Top(); + } else if (sn==-1.0 && cs==0.0) { // 270deg + aOutRect.Left() =R.Top(); + aOutRect.Right() =R.Bottom(); + aOutRect.Top() =-R.Right(); + aOutRect.Bottom()=-R.Left(); + } + aOutRect.Move(rRef.X(),rRef.Y()); + aOutRect.Justify(); // Sicherheitshalber + SetRectsDirty(); + NbcRotateGluePoints(rRef,nWink,sn,cs); + SetGlueReallyAbsolute(FALSE); +} + +void SdrObject::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + SetGlueReallyAbsolute(TRUE); + aOutRect.Move(-rRef1.X(),-rRef1.Y()); + Rectangle R(aOutRect); + long dx=rRef2.X()-rRef1.X(); + long dy=rRef2.Y()-rRef1.Y(); + if (dx==0) { // Vertikale Achse + aOutRect.Left() =-R.Right(); + aOutRect.Right()=-R.Left(); + } else if (dy==0) { // Horizontale Achse + aOutRect.Top() =-R.Bottom(); + aOutRect.Bottom()=-R.Top(); + } else if (dx==dy) { /* 45 Grad Achse \ */ + aOutRect.Left() =R.Top(); + aOutRect.Right() =R.Bottom(); + aOutRect.Top() =R.Left(); + aOutRect.Bottom()=R.Right(); + } else if (dx==-dy) { // 45 Grad Achse / + aOutRect.Left() =-R.Bottom(); + aOutRect.Right() =-R.Top(); + aOutRect.Top() =-R.Right(); + aOutRect.Bottom()=-R.Left(); + } + aOutRect.Move(rRef1.X(),rRef1.Y()); + aOutRect.Justify(); // Sicherheitshalber + SetRectsDirty(); + NbcMirrorGluePoints(rRef1,rRef2); + SetGlueReallyAbsolute(FALSE); +} + +void SdrObject::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + SetGlueReallyAbsolute(TRUE); + NbcShearGluePoints(rRef,nWink,tn,bVShear); + SetGlueReallyAbsolute(FALSE); +} + +void SdrObject::Move(const Size& rSiz) +{ + if (rSiz.Width()!=0 || rSiz.Height()!=0) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcMove(rSiz); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} + +void SdrObject::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + if (xFact.GetNumerator()!=xFact.GetDenominator() || yFact.GetNumerator()!=yFact.GetDenominator()) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcResize(rRef,xFact,yFact); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrObject::Rotate(const Point& rRef, long nWink, double sn, double cs) +{ + if (nWink!=0) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcRotate(rRef,nWink,sn,cs); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrObject::Mirror(const Point& rRef1, const Point& rRef2) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcMirror(rRef1,rRef2); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +void SdrObject::Shear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + if (nWink!=0) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcShear(rRef,nWink,tn,bVShear); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrObject::NbcSetRelativePos(const Point& rPnt) +{ + Point aRelPos0(GetSnapRect().TopLeft()-aAnchor); + Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y()); + NbcMove(aSiz); // Der ruft auch das SetRectsDirty() +} + +void SdrObject::SetRelativePos(const Point& rPnt) +{ + if (rPnt!=GetRelativePos()) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetRelativePos(rPnt); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} + +Point SdrObject::GetRelativePos() const +{ + return GetSnapRect().TopLeft()-aAnchor; +} + +void SdrObject::NbcSetAnchorPos(const Point& rPnt) +{ + Size aSiz(rPnt.X()-aAnchor.X(),rPnt.Y()-aAnchor.Y()); + aAnchor=rPnt; + NbcMove(aSiz); // Der ruft auch das SetRectsDirty() +} + +void SdrObject::SetAnchorPos(const Point& rPnt) +{ + if (rPnt!=aAnchor) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetAnchorPos(rPnt); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} + +const Point& SdrObject::GetAnchorPos() const +{ + return aAnchor; +} + +void SdrObject::RecalcSnapRect() +{ +} + +const Rectangle& SdrObject::GetSnapRect() const +{ + return aOutRect; +} + +void SdrObject::NbcSetSnapRect(const Rectangle& rRect) +{ + aOutRect=rRect; +} + +const Rectangle& SdrObject::GetLogicRect() const +{ + return GetSnapRect(); +} + +void SdrObject::NbcSetLogicRect(const Rectangle& rRect) +{ + NbcSetSnapRect(rRect); +} + +void SdrObject::AdjustToMaxRect( const Rectangle& rMaxRect, bool /* bShrinkOnly = false */ ) +{ + SetLogicRect( rMaxRect ); +} + +void SdrObject::SetSnapRect(const Rectangle& rRect) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetSnapRect(rRect); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +void SdrObject::SetLogicRect(const Rectangle& rRect) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetLogicRect(rRect); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +long SdrObject::GetRotateAngle() const +{ + return 0; +} + +long SdrObject::GetShearAngle(FASTBOOL /*bVertical*/) const +{ + return 0; +} + +sal_uInt32 SdrObject::GetSnapPointCount() const +{ + return GetPointCount(); +} + +Point SdrObject::GetSnapPoint(sal_uInt32 i) const +{ + return GetPoint(i); +} + +sal_Bool SdrObject::IsPolyObj() const +{ + return sal_False; +} + +sal_uInt32 SdrObject::GetPointCount() const +{ + return 0L; +} + +Point SdrObject::GetPoint(sal_uInt32 /*i*/) const +{ + return Point(); +} + +void SdrObject::SetPoint(const Point& rPnt, sal_uInt32 i) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetPoint(rPnt, i); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +void SdrObject::NbcSetPoint(const Point& /*rPnt*/, sal_uInt32 /*i*/) +{ +} + +FASTBOOL SdrObject::HasTextEdit() const +{ + return FALSE; +} + +sal_Bool SdrObject::BegTextEdit(SdrOutliner& /*rOutl*/) +{ + return FALSE; +} + +void SdrObject::EndTextEdit(SdrOutliner& /*rOutl*/) +{ +} + +void SdrObject::SetOutlinerParaObject(OutlinerParaObject* pTextObject) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetOutlinerParaObject(pTextObject); + SetChanged(); + BroadcastObjectChange(); + if (GetCurrentBoundRect()!=aBoundRect0) { + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrObject::NbcSetOutlinerParaObject(OutlinerParaObject* /*pTextObject*/) +{ +} + +OutlinerParaObject* SdrObject::GetOutlinerParaObject() const +{ + return NULL; +} + +void SdrObject::NbcReformatText() +{ +} + +void SdrObject::ReformatText() +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + NbcReformatText(); + SetChanged(); + BroadcastObjectChange(); + if (GetCurrentBoundRect()!=aBoundRect0) { + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrObject::BurnInStyleSheetAttributes() +{ + GetProperties().ForceStyleToHardAttributes(); +} + +#define Imp2ndKennung (0x434F4D43) +SdrObjUserData* SdrObject::ImpGetMacroUserData() const +{ + SdrObjUserData* pData=NULL; + USHORT nAnz=GetUserDataCount(); + for (USHORT nNum=nAnz; nNum>0 && pData==NULL;) { + nNum--; + pData=GetUserData(nNum); + if (!pData->HasMacro(this)) pData=NULL; + } + return pData; +} + +FASTBOOL SdrObject::HasMacro() const +{ + SdrObjUserData* pData=ImpGetMacroUserData(); + return pData!=NULL ? pData->HasMacro(this) : FALSE; +} + +SdrObject* SdrObject::CheckMacroHit(const SdrObjMacroHitRec& rRec) const +{ + SdrObjUserData* pData = ImpGetMacroUserData(); + + if(pData) + { + return pData->CheckMacroHit(rRec, this); + } + + if(rRec.pPageView) + { + return SdrObjectPrimitiveHit(*this, rRec.aPos, rRec.nTol, *rRec.pPageView, rRec.pVisiLayer, false); + } + + return 0; +} + +Pointer SdrObject::GetMacroPointer(const SdrObjMacroHitRec& rRec) const +{ + SdrObjUserData* pData=ImpGetMacroUserData(); + if (pData!=NULL) { + return pData->GetMacroPointer(rRec,this); + } + return Pointer(POINTER_REFHAND); +} + +void SdrObject::PaintMacro(OutputDevice& rOut, const Rectangle& rDirtyRect, const SdrObjMacroHitRec& rRec) const +{ + SdrObjUserData* pData=ImpGetMacroUserData(); + + if(pData) + { + pData->PaintMacro(rOut,rDirtyRect,rRec,this); + } + else + { + const RasterOp eRop(rOut.GetRasterOp()); + const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly()); + const sal_uInt32 nCount(aPolyPolygon.count()); + + rOut.SetLineColor(COL_BLACK); + rOut.SetFillColor(); + rOut.SetRasterOp(ROP_INVERT); + + for(sal_uInt32 a(0); a < nCount; a++) + { + rOut.DrawPolyLine(aPolyPolygon.getB2DPolygon(a)); + } + + rOut.SetRasterOp(eRop); + } +} + +FASTBOOL SdrObject::DoMacro(const SdrObjMacroHitRec& rRec) +{ + SdrObjUserData* pData=ImpGetMacroUserData(); + if (pData!=NULL) { + return pData->DoMacro(rRec,this); + } + return FALSE; +} + +XubString SdrObject::GetMacroPopupComment(const SdrObjMacroHitRec& rRec) const +{ + SdrObjUserData* pData=ImpGetMacroUserData(); + if (pData!=NULL) { + return pData->GetMacroPopupComment(rRec,this); + } + return String(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObjGeoData* SdrObject::NewGeoData() const +{ + return new SdrObjGeoData; +} + +void SdrObject::SaveGeoData(SdrObjGeoData& rGeo) const +{ + rGeo.aBoundRect =GetCurrentBoundRect(); + rGeo.aAnchor =aAnchor ; + rGeo.bMovProt =bMovProt ; + rGeo.bSizProt =bSizProt ; + rGeo.bNoPrint =bNoPrint ; + rGeo.mbVisible =mbVisible ; + rGeo.bClosedObj =bClosedObj ; + rGeo.mnLayerID = mnLayerID; + + // Benutzerdefinierte Klebepunkte + if (pPlusData!=NULL && pPlusData->pGluePoints!=NULL) { + if (rGeo.pGPL!=NULL) { + *rGeo.pGPL=*pPlusData->pGluePoints; + } else { + rGeo.pGPL=new SdrGluePointList(*pPlusData->pGluePoints); + } + } else { + if (rGeo.pGPL!=NULL) { + delete rGeo.pGPL; + rGeo.pGPL=NULL; + } + } +} + +void SdrObject::RestGeoData(const SdrObjGeoData& rGeo) +{ + SetRectsDirty(); + aOutRect =rGeo.aBoundRect ; + aAnchor =rGeo.aAnchor ; + bMovProt =rGeo.bMovProt ; + bSizProt =rGeo.bSizProt ; + bNoPrint =rGeo.bNoPrint ; + mbVisible =rGeo.mbVisible ; + bClosedObj =rGeo.bClosedObj ; + mnLayerID = rGeo.mnLayerID; + + // Benutzerdefinierte Klebepunkte + if (rGeo.pGPL!=NULL) { + ImpForcePlusData(); + if (pPlusData->pGluePoints!=NULL) { + *pPlusData->pGluePoints=*rGeo.pGPL; + } else { + pPlusData->pGluePoints=new SdrGluePointList(*rGeo.pGPL); + } + } else { + if (pPlusData!=NULL && pPlusData->pGluePoints!=NULL) { + delete pPlusData->pGluePoints; + pPlusData->pGluePoints=NULL; + } + } +} + +SdrObjGeoData* SdrObject::GetGeoData() const +{ + SdrObjGeoData* pGeo=NewGeoData(); + SaveGeoData(*pGeo); + return pGeo; +} + +void SdrObject::SetGeoData(const SdrObjGeoData& rGeo) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + RestGeoData(rGeo); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// ItemSet access + +const SfxItemSet& SdrObject::GetObjectItemSet() const +{ + return GetProperties().GetObjectItemSet(); +} + +const SfxItemSet& SdrObject::GetMergedItemSet() const +{ + return GetProperties().GetMergedItemSet(); +} + +void SdrObject::SetObjectItem(const SfxPoolItem& rItem) +{ + GetProperties().SetObjectItem(rItem); +} + +void SdrObject::SetMergedItem(const SfxPoolItem& rItem) +{ + GetProperties().SetMergedItem(rItem); +} + +void SdrObject::ClearObjectItem(const sal_uInt16 nWhich) +{ + GetProperties().ClearObjectItem(nWhich); +} + +void SdrObject::ClearMergedItem(const sal_uInt16 nWhich) +{ + GetProperties().ClearMergedItem(nWhich); +} + +void SdrObject::SetObjectItemSet(const SfxItemSet& rSet) +{ + GetProperties().SetObjectItemSet(rSet); +} + +void SdrObject::SetMergedItemSet(const SfxItemSet& rSet, sal_Bool bClearAllItems) +{ + GetProperties().SetMergedItemSet(rSet, bClearAllItems); +} + +const SfxPoolItem& SdrObject::GetObjectItem(const sal_uInt16 nWhich) const +{ + return GetObjectItemSet().Get(nWhich); +} + +const SfxPoolItem& SdrObject::GetMergedItem(const sal_uInt16 nWhich) const +{ + return GetMergedItemSet().Get(nWhich); +} + +void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet& rSet, sal_Bool bClearAllItems) +{ + GetProperties().SetMergedItemSetAndBroadcast(rSet, bClearAllItems); +} + +void SdrObject::ApplyNotPersistAttr(const SfxItemSet& rAttr) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + NbcApplyNotPersistAttr(rAttr); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +void SdrObject::NbcApplyNotPersistAttr(const SfxItemSet& rAttr) +{ + const Rectangle& rSnap=GetSnapRect(); + const Rectangle& rLogic=GetLogicRect(); + Point aRef1(rSnap.Center()); + Point aRef2(aRef1); aRef2.Y()++; + const SfxPoolItem *pPoolItem=NULL; + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,TRUE,&pPoolItem)==SFX_ITEM_SET) { + aRef1.X()=((const SdrTransformRef1XItem*)pPoolItem)->GetValue(); + } + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,TRUE,&pPoolItem)==SFX_ITEM_SET) { + aRef1.Y()=((const SdrTransformRef1YItem*)pPoolItem)->GetValue(); + } + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,TRUE,&pPoolItem)==SFX_ITEM_SET) { + aRef2.X()=((const SdrTransformRef2XItem*)pPoolItem)->GetValue(); + } + if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,TRUE,&pPoolItem)==SFX_ITEM_SET) { + aRef2.Y()=((const SdrTransformRef2YItem*)pPoolItem)->GetValue(); + } + + Rectangle aNewSnap(rSnap); + if (rAttr.GetItemState(SDRATTR_MOVEX,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrMoveXItem*)pPoolItem)->GetValue(); + aNewSnap.Move(n,0); + } + if (rAttr.GetItemState(SDRATTR_MOVEY,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrMoveYItem*)pPoolItem)->GetValue(); + aNewSnap.Move(0,n); + } + if (rAttr.GetItemState(SDRATTR_ONEPOSITIONX,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrOnePositionXItem*)pPoolItem)->GetValue(); + aNewSnap.Move(n-aNewSnap.Left(),0); + } + if (rAttr.GetItemState(SDRATTR_ONEPOSITIONY,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrOnePositionYItem*)pPoolItem)->GetValue(); + aNewSnap.Move(0,n-aNewSnap.Top()); + } + if (rAttr.GetItemState(SDRATTR_ONESIZEWIDTH,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrOneSizeWidthItem*)pPoolItem)->GetValue(); + aNewSnap.Right()=aNewSnap.Left()+n; + } + if (rAttr.GetItemState(SDRATTR_ONESIZEHEIGHT,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrOneSizeHeightItem*)pPoolItem)->GetValue(); + aNewSnap.Bottom()=aNewSnap.Top()+n; + } + if (aNewSnap!=rSnap) { + if (aNewSnap.GetSize()==rSnap.GetSize()) { + NbcMove(Size(aNewSnap.Left()-rSnap.Left(),aNewSnap.Top()-rSnap.Top())); + } else { + NbcSetSnapRect(aNewSnap); + } + } + + if (rAttr.GetItemState(SDRATTR_SHEARANGLE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrShearAngleItem*)pPoolItem)->GetValue(); + n-=GetShearAngle(); + if (n!=0) { + double nTan=tan(n*nPi180); + NbcShear(aRef1,n,nTan,FALSE); + } + } + if (rAttr.GetItemState(SDRATTR_ROTATEANGLE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrRotateAngleItem*)pPoolItem)->GetValue(); + n-=GetRotateAngle(); + if (n!=0) { + double nSin=sin(n*nPi180); + double nCos=cos(n*nPi180); + NbcRotate(aRef1,n,nSin,nCos); + } + } + if (rAttr.GetItemState(SDRATTR_ROTATEONE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrRotateOneItem*)pPoolItem)->GetValue(); + double nSin=sin(n*nPi180); + double nCos=cos(n*nPi180); + NbcRotate(aRef1,n,nSin,nCos); + } + if (rAttr.GetItemState(SDRATTR_HORZSHEARONE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrHorzShearOneItem*)pPoolItem)->GetValue(); + double nTan=tan(n*nPi180); + NbcShear(aRef1,n,nTan,FALSE); + } + if (rAttr.GetItemState(SDRATTR_VERTSHEARONE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrVertShearOneItem*)pPoolItem)->GetValue(); + double nTan=tan(n*nPi180); + NbcShear(aRef1,n,nTan,TRUE); + } + + if (rAttr.GetItemState(SDRATTR_OBJMOVEPROTECT,TRUE,&pPoolItem)==SFX_ITEM_SET) { + bool b=((const SdrObjMoveProtectItem*)pPoolItem)->GetValue(); + SetMoveProtect(b); + } + if (rAttr.GetItemState(SDRATTR_OBJSIZEPROTECT,TRUE,&pPoolItem)==SFX_ITEM_SET) { + bool b=((const SdrObjSizeProtectItem*)pPoolItem)->GetValue(); + SetResizeProtect(b); + } + + /* #67368# move protect always sets size protect */ + if( IsMoveProtect() ) + SetResizeProtect( true ); + + if (rAttr.GetItemState(SDRATTR_OBJPRINTABLE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + bool b=((const SdrObjPrintableItem*)pPoolItem)->GetValue(); + SetPrintable(b); + } + + if (rAttr.GetItemState(SDRATTR_OBJVISIBLE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + bool b=((const SdrObjVisibleItem*)pPoolItem)->GetValue(); + SetVisible(b); + } + + SdrLayerID nLayer=SDRLAYER_NOTFOUND; + if (rAttr.GetItemState(SDRATTR_LAYERID,TRUE,&pPoolItem)==SFX_ITEM_SET) { + nLayer=((const SdrLayerIdItem*)pPoolItem)->GetValue(); + } + if (rAttr.GetItemState(SDRATTR_LAYERNAME,TRUE,&pPoolItem)==SFX_ITEM_SET && pModel!=NULL) { + XubString aLayerName=((const SdrLayerNameItem*)pPoolItem)->GetValue(); + const SdrLayerAdmin* pLayAd=pPage!=NULL ? &pPage->GetLayerAdmin() : pModel!=NULL ? &pModel->GetLayerAdmin() : NULL; + if (pLayAd!=NULL) { + const SdrLayer* pLayer=pLayAd->GetLayer(aLayerName, TRUE); + if (pLayer!=NULL) { + nLayer=pLayer->GetID(); + } + } + + } + if (nLayer!=SDRLAYER_NOTFOUND) { + NbcSetLayer(nLayer); + } + + if (rAttr.GetItemState(SDRATTR_OBJECTNAME,TRUE,&pPoolItem)==SFX_ITEM_SET) { + XubString aName=((const SdrObjectNameItem*)pPoolItem)->GetValue(); + SetName(aName); + } + Rectangle aNewLogic(rLogic); + if (rAttr.GetItemState(SDRATTR_LOGICSIZEWIDTH,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrLogicSizeWidthItem*)pPoolItem)->GetValue(); + aNewLogic.Right()=aNewLogic.Left()+n; + } + if (rAttr.GetItemState(SDRATTR_LOGICSIZEHEIGHT,TRUE,&pPoolItem)==SFX_ITEM_SET) { + long n=((const SdrLogicSizeHeightItem*)pPoolItem)->GetValue(); + aNewLogic.Bottom()=aNewLogic.Top()+n; + } + if (aNewLogic!=rLogic) { + NbcSetLogicRect(aNewLogic); + } + Fraction aResizeX(1,1); + Fraction aResizeY(1,1); + if (rAttr.GetItemState(SDRATTR_RESIZEXONE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + aResizeX*=((const SdrResizeXOneItem*)pPoolItem)->GetValue(); + } + if (rAttr.GetItemState(SDRATTR_RESIZEYONE,TRUE,&pPoolItem)==SFX_ITEM_SET) { + aResizeY*=((const SdrResizeYOneItem*)pPoolItem)->GetValue(); + } + if (aResizeX!=Fraction(1,1) || aResizeY!=Fraction(1,1)) { + NbcResize(aRef1,aResizeX,aResizeY); + } +} + +void lcl_SetItem(SfxItemSet& rAttr, FASTBOOL bMerge, const SfxPoolItem& rItem) +{ + if (bMerge) rAttr.MergeValue(rItem,TRUE); + else rAttr.Put(rItem); +} + +void SdrObject::TakeNotPersistAttr(SfxItemSet& rAttr, FASTBOOL bMerge) const +{ + const Rectangle& rSnap=GetSnapRect(); + const Rectangle& rLogic=GetLogicRect(); + lcl_SetItem(rAttr,bMerge,SdrObjMoveProtectItem(IsMoveProtect())); + lcl_SetItem(rAttr,bMerge,SdrObjSizeProtectItem(IsResizeProtect())); + lcl_SetItem(rAttr,bMerge,SdrObjPrintableItem(IsPrintable())); + lcl_SetItem(rAttr,bMerge,SdrObjVisibleItem(IsVisible())); + lcl_SetItem(rAttr,bMerge,SdrRotateAngleItem(GetRotateAngle())); + lcl_SetItem(rAttr,bMerge,SdrShearAngleItem(GetShearAngle())); + lcl_SetItem(rAttr,bMerge,SdrOneSizeWidthItem(rSnap.GetWidth()-1)); + lcl_SetItem(rAttr,bMerge,SdrOneSizeHeightItem(rSnap.GetHeight()-1)); + lcl_SetItem(rAttr,bMerge,SdrOnePositionXItem(rSnap.Left())); + lcl_SetItem(rAttr,bMerge,SdrOnePositionYItem(rSnap.Top())); + if (rLogic.GetWidth()!=rSnap.GetWidth()) { + lcl_SetItem(rAttr,bMerge,SdrLogicSizeWidthItem(rLogic.GetWidth()-1)); + } + if (rLogic.GetHeight()!=rSnap.GetHeight()) { + lcl_SetItem(rAttr,bMerge,SdrLogicSizeHeightItem(rLogic.GetHeight()-1)); + } + XubString aName(GetName()); + + if(aName.Len()) + { + lcl_SetItem(rAttr, bMerge, SdrObjectNameItem(aName)); + } + + lcl_SetItem(rAttr,bMerge,SdrLayerIdItem(GetLayer())); + const SdrLayerAdmin* pLayAd=pPage!=NULL ? &pPage->GetLayerAdmin() : pModel!=NULL ? &pModel->GetLayerAdmin() : NULL; + if (pLayAd!=NULL) { + const SdrLayer* pLayer=pLayAd->GetLayerPerID(GetLayer()); + if (pLayer!=NULL) { + lcl_SetItem(rAttr,bMerge,SdrLayerNameItem(pLayer->GetName())); + } + } + Point aRef1(rSnap.Center()); + Point aRef2(aRef1); aRef2.Y()++; + lcl_SetItem(rAttr,bMerge,SdrTransformRef1XItem(aRef1.X())); + lcl_SetItem(rAttr,bMerge,SdrTransformRef1YItem(aRef1.Y())); + lcl_SetItem(rAttr,bMerge,SdrTransformRef2XItem(aRef2.X())); + lcl_SetItem(rAttr,bMerge,SdrTransformRef2YItem(aRef2.Y())); +} + +SfxStyleSheet* SdrObject::GetStyleSheet() const +{ + return GetProperties().GetStyleSheet(); +} + +void SdrObject::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr) +{ + Rectangle aBoundRect0; + + if(pUserCall) + aBoundRect0 = GetLastBoundRect(); + + // #110094#-14 SendRepaintBroadcast(); + NbcSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect0); +} + +void SdrObject::NbcSetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr) +{ + // only allow graphic and presentation styles for shapes + if( pNewStyleSheet && (pNewStyleSheet->GetFamily() == SFX_STYLE_FAMILY_PARA) && (pNewStyleSheet->GetFamily() == SFX_STYLE_FAMILY_PAGE) ) + return; + + GetProperties().SetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr); +} + +// Das Broadcasting beim Setzen der Attribute wird vom AttrObj gemanagt +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrObject::IsNode() const +{ + return TRUE; +} + +SdrGluePoint SdrObject::GetVertexGluePoint(USHORT nPosNum) const +{ + // #i41936# Use SnapRect for default GluePoints + const Rectangle aR(GetSnapRect()); + Point aPt; + + switch(nPosNum) + { + case 0 : aPt = aR.TopCenter(); break; + case 1 : aPt = aR.RightCenter(); break; + case 2 : aPt = aR.BottomCenter(); break; + case 3 : aPt = aR.LeftCenter(); break; + } + + aPt -= aR.Center(); + SdrGluePoint aGP(aPt); + aGP.SetPercent(FALSE); + + return aGP; +} + +SdrGluePoint SdrObject::GetCornerGluePoint(USHORT nPosNum) const +{ + Rectangle aR(GetCurrentBoundRect()); + Point aPt; + switch (nPosNum) { + case 0 : aPt=aR.TopLeft(); break; + case 1 : aPt=aR.TopRight(); break; + case 2 : aPt=aR.BottomRight(); break; + case 3 : aPt=aR.BottomLeft(); break; + } + aPt-=GetSnapRect().Center(); + SdrGluePoint aGP(aPt); + aGP.SetPercent(FALSE); + return aGP; +} + +const SdrGluePointList* SdrObject::GetGluePointList() const +{ + if (pPlusData!=NULL) return pPlusData->pGluePoints; + return NULL; +} + +//SdrGluePointList* SdrObject::GetGluePointList() +//{ +// if (pPlusData!=NULL) return pPlusData->pGluePoints; +// return NULL; +//} + +SdrGluePointList* SdrObject::ForceGluePointList() +{ + ImpForcePlusData(); + if (pPlusData->pGluePoints==NULL) { + pPlusData->pGluePoints=new SdrGluePointList; + } + return pPlusData->pGluePoints; +} + +void SdrObject::SetGlueReallyAbsolute(FASTBOOL bOn) +{ + // erst Const-Aufruf um zu sehen, ob + // ueberhaupt Klebepunkte da sind + // const-Aufruf erzwingen! + if (GetGluePointList()!=NULL) { + SdrGluePointList* pGPL=ForceGluePointList(); + pGPL->SetReallyAbsolute(bOn,*this); + } +} + +void SdrObject::NbcRotateGluePoints(const Point& rRef, long nWink, double sn, double cs) +{ + // erst Const-Aufruf um zu sehen, ob + // ueberhaupt Klebepunkte da sind + // const-Aufruf erzwingen! + if (GetGluePointList()!=NULL) { + SdrGluePointList* pGPL=ForceGluePointList(); + pGPL->Rotate(rRef,nWink,sn,cs,this); + } +} + +void SdrObject::NbcMirrorGluePoints(const Point& rRef1, const Point& rRef2) +{ + // erst Const-Aufruf um zu sehen, ob + // ueberhaupt Klebepunkte da sind + // const-Aufruf erzwingen! + if (GetGluePointList()!=NULL) { + SdrGluePointList* pGPL=ForceGluePointList(); + pGPL->Mirror(rRef1,rRef2,this); + } +} + +void SdrObject::NbcShearGluePoints(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + // erst Const-Aufruf um zu sehen, ob + // ueberhaupt Klebepunkte da sind + // const-Aufruf erzwingen! + if (GetGluePointList()!=NULL) { + SdrGluePointList* pGPL=ForceGluePointList(); + pGPL->Shear(rRef,nWink,tn,bVShear,this); + } +} + +FASTBOOL SdrObject::IsEdge() const +{ + return FALSE; +} + +void SdrObject::ConnectToNode(FASTBOOL /*bTail1*/, SdrObject* /*pObj*/) +{ +} + +void SdrObject::DisconnectFromNode(FASTBOOL /*bTail1*/) +{ +} + +SdrObject* SdrObject::GetConnectedNode(FASTBOOL /*bTail1*/) const +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObject* SdrObject::ImpConvertToContourObj(SdrObject* pRet, BOOL bForceLineDash) const +{ + bool bNoChange(true); + + if(pRet->LineGeometryUsageIsNecessary()) + { + basegfx::B2DPolyPolygon aMergedLineFillPolyPolygon; + basegfx::B2DPolyPolygon aMergedHairlinePolyPolygon; + const drawinglayer::primitive2d::Primitive2DSequence xSequence(pRet->GetViewContact().getViewIndependentPrimitive2DSequence()); + + if(xSequence.hasElements()) + { + // use neutral ViewInformation + const drawinglayer::geometry::ViewInformation2D aViewInformation2D(0); + + // create extractor, process and get result + drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D); + aExtractor.process(xSequence); + + // #i102241# check for line results + const std::vector< basegfx::B2DPolygon >& rHairlineVector = aExtractor.getExtractedHairlines(); + + if(rHairlineVector.size()) + { + // for SdrObject creation, just copy all to a single Hairline-PolyPolygon + for(sal_uInt32 a(0); a < rHairlineVector.size(); a++) + { + aMergedHairlinePolyPolygon.append(rHairlineVector[a]); + } + } + + // #i102241# check for fill rsults + const std::vector< basegfx::B2DPolyPolygon >& rLineFillVector(aExtractor.getExtractedLineFills()); + + if(rLineFillVector.size()) + { + // merge to a single PolyPolygon (OR) + aMergedLineFillPolyPolygon = basegfx::tools::mergeToSinglePolyPolygon(rLineFillVector); + } + } + + // || aMergedHairlinePolyPolygon.Count() removed; the conversion is ONLY + // useful when new closed filled polygons are created + if(aMergedLineFillPolyPolygon.count() || (bForceLineDash && aMergedHairlinePolyPolygon.count())) + { + SfxItemSet aSet(pRet->GetMergedItemSet()); + XFillStyle eOldFillStyle = ((const XFillStyleItem&)(aSet.Get(XATTR_FILLSTYLE))).GetValue(); + SdrPathObj* aLinePolygonPart = NULL; + SdrPathObj* aLineHairlinePart = NULL; + bool bBuildGroup(false); + + if(aMergedLineFillPolyPolygon.count()) + { + // create SdrObject for filled line geometry + aLinePolygonPart = new SdrPathObj(OBJ_PATHFILL, aMergedLineFillPolyPolygon); + aLinePolygonPart->SetModel(pRet->GetModel()); + + // correct item properties + aSet.Put(XLineWidthItem(0L)); + aSet.Put(XLineStyleItem(XLINE_NONE)); + Color aColorLine = ((const XLineColorItem&)(aSet.Get(XATTR_LINECOLOR))).GetColorValue(); + UINT16 nTransLine = ((const XLineTransparenceItem&)(aSet.Get(XATTR_LINETRANSPARENCE))).GetValue(); + aSet.Put(XFillColorItem(XubString(), aColorLine)); + aSet.Put(XFillStyleItem(XFILL_SOLID)); + aSet.Put(XFillTransparenceItem(nTransLine)); + + aLinePolygonPart->SetMergedItemSet(aSet); + } + + if(aMergedHairlinePolyPolygon.count()) + { + // create SdrObject for hairline geometry + // OBJ_PATHLINE is necessary here, not OBJ_PATHFILL. This is intended + // to get a non-filled object. If the poly is closed, the PathObj takes care for + // the correct closed state. + aLineHairlinePart = new SdrPathObj(OBJ_PATHLINE, aMergedHairlinePolyPolygon); + aLineHairlinePart->SetModel(pRet->GetModel()); + + aSet.Put(XLineWidthItem(0L)); + aSet.Put(XFillStyleItem(XFILL_NONE)); + aSet.Put(XLineStyleItem(XLINE_SOLID)); + + // it is also necessary to switch off line start and ends here + aSet.Put(XLineStartWidthItem(0)); + aSet.Put(XLineEndWidthItem(0)); + + aLineHairlinePart->SetMergedItemSet(aSet); + + if(aLinePolygonPart) + { + bBuildGroup = true; + } + } + + // check if original geometry should be added (e.g. filled and closed) + bool bAddOriginalGeometry(false); + SdrPathObj* pPath = PTR_CAST(SdrPathObj, pRet); + + if(pPath && pPath->IsClosed()) + { + if(eOldFillStyle != XFILL_NONE) + { + // #107600# use new boolean here + bAddOriginalGeometry = true; + } + } + + // do we need a group? + if(bBuildGroup || bAddOriginalGeometry) + { + SdrObject* pGroup = new SdrObjGroup; + pGroup->SetModel(pRet->GetModel()); + + if(bAddOriginalGeometry) + { + // Add a clone of the original geometry. + aSet.ClearItem(); + aSet.Put(pRet->GetMergedItemSet()); + aSet.Put(XLineStyleItem(XLINE_NONE)); + aSet.Put(XLineWidthItem(0L)); + + SdrObject* pClone = pRet->Clone(); + + pClone->SetModel(pRet->GetModel()); + pClone->SetMergedItemSet(aSet); + + pGroup->GetSubList()->NbcInsertObject(pClone); + } + + if(aLinePolygonPart) + { + pGroup->GetSubList()->NbcInsertObject(aLinePolygonPart); + } + + if(aLineHairlinePart) + { + pGroup->GetSubList()->NbcInsertObject(aLineHairlinePart); + } + + pRet = pGroup; + + // be more careful with the state describing bool + bNoChange = false; + } + else + { + if(aLinePolygonPart) + { + pRet = aLinePolygonPart; + // be more careful with the state describing bool + bNoChange = false; + } + else if(aLineHairlinePart) + { + pRet = aLineHairlinePart; + // be more careful with the state describing bool + bNoChange = false; + } + } + } + } + + if(bNoChange) + { + // due to current method usage, create and return a clone when nothing has changed + SdrObject* pClone = pRet->Clone(); + pClone->SetModel(pRet->GetModel()); + pRet = pClone; + } + + return pRet; +} + +// convert this path object to contour object, even when it is a group +SdrObject* SdrObject::ConvertToContourObj(SdrObject* pRet, BOOL bForceLineDash) const +{ + if(pRet->ISA(SdrObjGroup)) + { + SdrObjList* pObjList2 = pRet->GetSubList(); + SdrObject* pGroup = new SdrObjGroup; + pGroup->SetModel(pRet->GetModel()); + + for(UINT32 a=0;a<pObjList2->GetObjCount();a++) + { + SdrObject* pIterObj = pObjList2->GetObj(a); + pGroup->GetSubList()->NbcInsertObject(ConvertToContourObj(pIterObj, bForceLineDash)); + } + + pRet = pGroup; + } + else + { + if(pRet && pRet->ISA(SdrPathObj)) + { + SdrPathObj* pPathObj = (SdrPathObj*)pRet; + + // bezier geometry got created, even for straight edges since the given + // object is a result of DoConvertToPolyObj. For conversion to contour + // this is not really needed and can be reduced again AFAP + pPathObj->SetPathPoly(basegfx::tools::simplifyCurveSegments(pPathObj->GetPathPoly())); + } + + pRet = ImpConvertToContourObj(pRet, bForceLineDash); + } + + // #i73441# preserve LayerID + if(pRet && pRet->GetLayer() != GetLayer()) + { + pRet->SetLayer(GetLayer()); + } + + return pRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObject* SdrObject::ConvertToPolyObj(BOOL bBezier, BOOL bLineToArea) const +{ + SdrObject* pRet = DoConvertToPolyObj(bBezier); + + if(pRet && bLineToArea) + { + SdrObject* pNewRet = ConvertToContourObj(pRet); + delete pRet; + pRet = pNewRet; + } + + // #i73441# preserve LayerID + if(pRet && pRet->GetLayer() != GetLayer()) + { + pRet->SetLayer(GetLayer()); + } + + return pRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObject* SdrObject::DoConvertToPolyObj(BOOL /*bBezier*/) const +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObject::SetInserted(sal_Bool bIns) +{ + if (bIns!=IsInserted()) { + bInserted=bIns; + Rectangle aBoundRect0(GetLastBoundRect()); + if (bIns) SendUserCall(SDRUSERCALL_INSERTED,aBoundRect0); + else SendUserCall(SDRUSERCALL_REMOVED,aBoundRect0); + + if (pPlusData!=NULL && pPlusData->pBroadcast!=NULL) { // #42522# + SdrHint aHint(*this); + aHint.SetKind(bIns?HINT_OBJINSERTED:HINT_OBJREMOVED); + pPlusData->pBroadcast->Broadcast(aHint); + } + } +} + +void SdrObject::SetMoveProtect(sal_Bool bProt) +{ + if(IsMoveProtect() != bProt) + { + // #i77187# secured and simplified + bMovProt = bProt; + SetChanged(); + BroadcastObjectChange(); + } +} + +void SdrObject::SetResizeProtect(sal_Bool bProt) +{ + if(IsResizeProtect() != bProt) + { + // #i77187# secured and simplified + bSizProt = bProt; + SetChanged(); + BroadcastObjectChange(); + } +} + +void SdrObject::SetPrintable(sal_Bool bPrn) +{ + if( bPrn == bNoPrint ) + { + bNoPrint=!bPrn; + SetChanged(); + if (IsInserted() && pModel!=NULL) + { + SdrHint aHint(*this); + pModel->Broadcast(aHint); + } + } +} + +void SdrObject::SetVisible(sal_Bool bVisible) +{ + if( bVisible != mbVisible ) + { + mbVisible = bVisible; + SetChanged(); + if (IsInserted() && pModel!=NULL) + { + SdrHint aHint(*this); + pModel->Broadcast(aHint); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +USHORT SdrObject::GetUserDataCount() const +{ + if (pPlusData==NULL || pPlusData->pUserDataList==NULL) return 0; + return pPlusData->pUserDataList->GetUserDataCount(); +} + +SdrObjUserData* SdrObject::GetUserData(USHORT nNum) const +{ + if (pPlusData==NULL || pPlusData->pUserDataList==NULL) return NULL; + return pPlusData->pUserDataList->GetUserData(nNum); +} + +void SdrObject::InsertUserData(SdrObjUserData* pData, USHORT nPos) +{ + if (pData!=NULL) { + ImpForcePlusData(); + if (pPlusData->pUserDataList==NULL) pPlusData->pUserDataList=new SdrObjUserDataList; + pPlusData->pUserDataList->InsertUserData(pData,nPos); + } else { + DBG_ERROR("SdrObject::InsertUserData(): pData ist NULL-Pointer"); + } +} + +void SdrObject::DeleteUserData(USHORT nNum) +{ + USHORT nAnz=GetUserDataCount(); + if (nNum<nAnz) { + pPlusData->pUserDataList->DeleteUserData(nNum); + if (nAnz==1) { + delete pPlusData->pUserDataList; + pPlusData->pUserDataList=NULL; + } + } else { + DBG_ERROR("SdrObject::DeleteUserData(): ungueltiger Index"); + } +} + +void SdrObject::SendUserCall(SdrUserCallType eUserCall, const Rectangle& rBoundRect) const +{ + SdrObjGroup* pGroup = NULL; + + if( pObjList && pObjList->GetListKind() == SDROBJLIST_GROUPOBJ ) + pGroup = (SdrObjGroup*) pObjList->GetOwnerObj(); + + if ( pUserCall ) + { + // UserCall ausfuehren + pUserCall->Changed( *this, eUserCall, rBoundRect ); + } + + while( pGroup ) + { + // Gruppe benachrichtigen + if( pGroup->GetUserCall() ) + { + SdrUserCallType eChildUserType = SDRUSERCALL_CHILD_CHGATTR; + + switch( eUserCall ) + { + case SDRUSERCALL_MOVEONLY: + eChildUserType = SDRUSERCALL_CHILD_MOVEONLY; + break; + + case SDRUSERCALL_RESIZE: + eChildUserType = SDRUSERCALL_CHILD_RESIZE; + break; + + case SDRUSERCALL_CHGATTR: + eChildUserType = SDRUSERCALL_CHILD_CHGATTR; + break; + + case SDRUSERCALL_DELETE: + eChildUserType = SDRUSERCALL_CHILD_DELETE; + break; + + case SDRUSERCALL_COPY: + eChildUserType = SDRUSERCALL_CHILD_COPY; + break; + + case SDRUSERCALL_INSERTED: + eChildUserType = SDRUSERCALL_CHILD_INSERTED; + break; + + case SDRUSERCALL_REMOVED: + eChildUserType = SDRUSERCALL_CHILD_REMOVED; + break; + + default: break; + } + + pGroup->GetUserCall()->Changed( *this, eChildUserType, rBoundRect ); + } + + if( pGroup->GetObjList() && + pGroup->GetObjList()->GetListKind() == SDROBJLIST_GROUPOBJ && + pGroup != (SdrObjGroup*) pObjList->GetOwnerObj() ) + pGroup = (SdrObjGroup*) pObjList->GetOwnerObj(); + else + pGroup = NULL; + } + + // notify our UNO shape listeners + switch ( eUserCall ) + { + case SDRUSERCALL_RESIZE: + notifyShapePropertyChange( ::svx::eShapeSize ); + // fall through - RESIZE might also imply a change of the position + case SDRUSERCALL_MOVEONLY: + notifyShapePropertyChange( ::svx::eShapePosition ); + break; + default: + // not interested in + break; + } +} + +// ItemPool fuer dieses Objekt wechseln +void SdrObject::MigrateItemPool(SfxItemPool* pSrcPool, SfxItemPool* pDestPool, SdrModel* pNewModel) +{ + if(pSrcPool && pDestPool && (pSrcPool != pDestPool)) + { + GetProperties().MoveToItemPool(pSrcPool, pDestPool, pNewModel); + } +} + +sal_Bool SdrObject::IsTransparent( BOOL /*bCheckForAlphaChannel*/) const +{ + bool bRet = false; + + if( IsGroupObject() ) + { + SdrObjListIter aIter( *GetSubList(), IM_DEEPNOGROUPS ); + + for( SdrObject* pO = aIter.Next(); pO && !bRet; pO = aIter.Next() ) + { + const SfxItemSet& rAttr = pO->GetMergedItemSet(); + + if( ( ( (const XFillTransparenceItem&) rAttr.Get( XATTR_FILLTRANSPARENCE ) ).GetValue() || + ( (const XLineTransparenceItem&) rAttr.Get( XATTR_LINETRANSPARENCE ) ).GetValue() ) || + ( ( rAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE ) == SFX_ITEM_SET ) && + ( (const XFillFloatTransparenceItem&) rAttr.Get( XATTR_FILLFLOATTRANSPARENCE ) ).IsEnabled() ) ) + { + bRet = TRUE; + } + else if( pO->ISA( SdrGrafObj ) ) + { + SdrGrafObj* pGrafObj = (SdrGrafObj*) pO; + if( ( (const SdrGrafTransparenceItem&) rAttr.Get( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() || + ( pGrafObj->GetGraphicType() == GRAPHIC_BITMAP && pGrafObj->GetGraphic().GetBitmapEx().IsAlpha() ) ) + { + bRet = TRUE; + } + } + } + } + else + { + const SfxItemSet& rAttr = GetMergedItemSet(); + + if( ( ( (const XFillTransparenceItem&) rAttr.Get( XATTR_FILLTRANSPARENCE ) ).GetValue() || + ( (const XLineTransparenceItem&) rAttr.Get( XATTR_LINETRANSPARENCE ) ).GetValue() ) || + ( ( rAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE ) == SFX_ITEM_SET ) && + ( (const XFillFloatTransparenceItem&) rAttr.Get( XATTR_FILLFLOATTRANSPARENCE ) ).IsEnabled() ) ) + { + bRet = TRUE; + } + else if( ISA( SdrGrafObj ) ) + { + SdrGrafObj* pGrafObj = (SdrGrafObj*) this; + + // #i25616# + bRet = pGrafObj->IsObjectTransparent(); + } + } + + return bRet; +} + +void SdrObject::impl_setUnoShape( const uno::Reference< uno::XInterface >& _rxUnoShape ) +{ + maWeakUnoShape = _rxUnoShape; + mpSvxShape = SvxShape::getImplementation( _rxUnoShape ); +// OSL_ENSURE( mpSvxShape || !_rxUnoShape.is(), +// "SdrObject::setUnoShape: not sure it's a good idea to have an XShape which is not implemented by SvxShape ..." ); +} + +/** only for internal use! */ +SvxShape* SdrObject::getSvxShape() const +{ + DBG_TESTSOLARMUTEX(); + // retrieving the impl pointer and subsequently using it is not thread-safe, of course, so it needs to be + // guarded by the SolarMutex + +#if OSL_DEBUG_LEVE > 0 + uno::Reference< uno::XInterface > xShape( maWeakUnoShape ); + OSL_ENSURE( !( !xShapeGuard.is() && mpSvxShape ), + "SdrObject::getSvxShape: still having IMPL-Pointer to dead object!" ); +#endif + + return mpSvxShape; +} + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SdrObject::getUnoShape() +{ + // try weak reference first + uno::Reference< uno::XInterface > xShape( getWeakUnoShape() ); + if( !xShape.is() ) + { + OSL_ENSURE( mpSvxShape == NULL, "SdrObject::getUnoShape: XShape already dead, but still an IMPL pointer!" ); + if ( pPage ) + { + uno::Reference< uno::XInterface > xPage( pPage->getUnoPage() ); + if( xPage.is() ) + { + SvxDrawPage* pDrawPage = SvxDrawPage::getImplementation(xPage); + if( pDrawPage ) + { + // create one + xShape = pDrawPage->_CreateShape( this ); + impl_setUnoShape( xShape ); + } + } + } + else + { + mpSvxShape = SvxDrawPage::CreateShapeByTypeAndInventor( GetObjIdentifier(), GetObjInventor(), this, NULL ); + maWeakUnoShape = xShape = static_cast< ::cppu::OWeakObject* >( mpSvxShape ); + } + } + + return xShape; +} + +::svx::PropertyChangeNotifier& SdrObject::getShapePropertyChangeNotifier() +{ + DBG_TESTSOLARMUTEX(); + + SvxShape* pSvxShape = getSvxShape(); + ENSURE_OR_THROW( pSvxShape, "no SvxShape, yet!" ); + return pSvxShape->getShapePropertyChangeNotifier(); +} + +void SdrObject::notifyShapePropertyChange( const ::svx::ShapeProperty _eProperty ) const +{ + DBG_TESTSOLARMUTEX(); + + SvxShape* pSvxShape = const_cast< SdrObject* >( this )->getSvxShape(); + if ( pSvxShape ) + return pSvxShape->getShapePropertyChangeNotifier().notifyPropertyChange( _eProperty ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// transformation interface for StarOfficeAPI. This implements support for +// homogen 3x3 matrices containing the transformation of the SdrObject. At the +// moment it contains a shearX, rotation and translation, but for setting all linear +// transforms like Scale, ShearX, ShearY, Rotate and Translate are supported. +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon +// with the base geometry and returns TRUE. Otherwise it returns FALSE. +sal_Bool SdrObject::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const +{ + // any kind of SdrObject, just use SnapRect + Rectangle aRectangle(GetSnapRect()); + + // convert to transformation values + basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight()); + basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top()); + + // position maybe relative to anchorpos, convert + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // force MapUnit to 100th mm + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // postion + aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); + aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); + + // size + aScale.setX(ImplTwipsToMM(aScale.getX())); + aScale.setY(ImplTwipsToMM(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); + } + } + } + + // build matrix + rMatrix = basegfx::tools::createScaleTranslateB2DHomMatrix(aScale, aTranslate); + + return sal_False; +} + +// sets the base geometry of the object using infos contained in the homogen 3x3 matrix. +// If it's an SdrPathObj it will use the provided geometry information. The Polygon has +// to use (0,0) as upper left and will be scaled to the given size in the matrix. +void SdrObject::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) +{ + // break up matrix + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate, fShearX; + rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings + // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale.setX(fabs(aScale.getX())); + aScale.setY(fabs(aScale.getY())); + fRotate = fmod(fRotate + F_PI, F_2PI); + } + + // force metric to pool metric + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // position + aTranslate.setX(ImplMMToTwips(aTranslate.getX())); + aTranslate.setY(ImplMMToTwips(aTranslate.getY())); + + // size + aScale.setX(ImplMMToTwips(aScale.getX())); + aScale.setY(ImplMMToTwips(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); + } + } + } + + // if anchor is used, make position relative to it + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // build BaseRect + Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY())); + Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY()))); + + // set BaseRect + SetSnapRect(aBaseRect); +} + +// #116168# +// Give info if object is in destruction +sal_Bool SdrObject::IsInDestruction() const +{ + if(pModel) + return pModel->IsInDestruction(); + return sal_False; +} + +// return if fill is != XFILL_NONE +bool SdrObject::HasFillStyle() const +{ + return (((const XFillStyleItem&)GetObjectItem(XATTR_FILLSTYLE)).GetValue() != XFILL_NONE); +} + +bool SdrObject::HasLineStyle() const +{ + return (((const XLineStyleItem&)GetObjectItem(XATTR_LINESTYLE)).GetValue() != XLINE_NONE); +} + + +// #i52224# +// on import of OLE object from MS documents the BLIP size might be retrieved, +// the following four methods are used to control it; +// usually this data makes no sence after the import is finished, since the object +// might be resized + +Rectangle SdrObject::GetBLIPSizeRectangle() const +{ + return maBLIPSizeRectangle; +} + +void SdrObject::SetBLIPSizeRectangle( const Rectangle& aRect ) +{ + maBLIPSizeRectangle = aRect; +} + +void SdrObject::SetContextWritingMode( const sal_Int16 /*_nContextWritingMode*/ ) +{ + // this base class does not support different writing modes, so ignore the call +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@@@@ @@@@@@ @@@@@ @@@@ @@@@ @@@@@@ @@@@ @@@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@@@ @@@@@@ @@ @@ @@ @@ @@@@@ @@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@ @@@@@ @@@@ @@ @@ @@ @@@@ @@ @@@@ @@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObjFactory::SdrObjFactory(UINT32 nInvent, UINT16 nIdent, SdrPage* pNewPage, SdrModel* pNewModel) +{ + nInventor=nInvent; + nIdentifier=nIdent; + pNewObj=NULL; + pPage=pNewPage; + pModel=pNewModel; + pObj=NULL; + pNewData=NULL; +} + +SdrObjFactory::SdrObjFactory(UINT32 nInvent, UINT16 nIdent, SdrObject* pObj1) +{ + nInventor=nInvent; + nIdentifier=nIdent; + pNewObj=NULL; + pPage=NULL; + pModel=NULL; + pObj=pObj1; + pNewData=NULL; +} + +SdrObject* SdrObjFactory::MakeNewObject(UINT32 nInvent, UINT16 nIdent, SdrPage* pPage, SdrModel* pModel) +{ + if(pModel == NULL && pPage != NULL) + pModel = pPage->GetModel(); + SdrObject* pObj = NULL; + + if(nInvent == SdrInventor) + { + switch (nIdent) + { + case USHORT(OBJ_NONE ): pObj=new SdrObject; break; + case USHORT(OBJ_GRUP ): pObj=new SdrObjGroup; break; + case USHORT(OBJ_LINE ): pObj=new SdrPathObj(OBJ_LINE ); break; + case USHORT(OBJ_POLY ): pObj=new SdrPathObj(OBJ_POLY ); break; + case USHORT(OBJ_PLIN ): pObj=new SdrPathObj(OBJ_PLIN ); break; + case USHORT(OBJ_PATHLINE ): pObj=new SdrPathObj(OBJ_PATHLINE ); break; + case USHORT(OBJ_PATHFILL ): pObj=new SdrPathObj(OBJ_PATHFILL ); break; + case USHORT(OBJ_FREELINE ): pObj=new SdrPathObj(OBJ_FREELINE ); break; + case USHORT(OBJ_FREEFILL ): pObj=new SdrPathObj(OBJ_FREEFILL ); break; + case USHORT(OBJ_PATHPOLY ): pObj=new SdrPathObj(OBJ_POLY ); break; + case USHORT(OBJ_PATHPLIN ): pObj=new SdrPathObj(OBJ_PLIN ); break; + case USHORT(OBJ_EDGE ): pObj=new SdrEdgeObj; break; + case USHORT(OBJ_RECT ): pObj=new SdrRectObj; break; + case USHORT(OBJ_CIRC ): pObj=new SdrCircObj(OBJ_CIRC ); break; + case USHORT(OBJ_SECT ): pObj=new SdrCircObj(OBJ_SECT ); break; + case USHORT(OBJ_CARC ): pObj=new SdrCircObj(OBJ_CARC ); break; + case USHORT(OBJ_CCUT ): pObj=new SdrCircObj(OBJ_CCUT ); break; + case USHORT(OBJ_TEXT ): pObj=new SdrRectObj(OBJ_TEXT ); break; + case USHORT(OBJ_TEXTEXT ): pObj=new SdrRectObj(OBJ_TEXTEXT ); break; + case USHORT(OBJ_TITLETEXT ): pObj=new SdrRectObj(OBJ_TITLETEXT ); break; + case USHORT(OBJ_OUTLINETEXT): pObj=new SdrRectObj(OBJ_OUTLINETEXT); break; + case USHORT(OBJ_MEASURE ): pObj=new SdrMeasureObj; break; + case USHORT(OBJ_GRAF ): pObj=new SdrGrafObj; break; + case USHORT(OBJ_OLE2 ): pObj=new SdrOle2Obj; break; + case USHORT(OBJ_FRAME ): pObj=new SdrOle2Obj(TRUE); break; + case USHORT(OBJ_CAPTION ): pObj=new SdrCaptionObj; break; + case USHORT(OBJ_PAGE ): pObj=new SdrPageObj; break; + case USHORT(OBJ_UNO ): pObj=new SdrUnoObj(String()); break; + case USHORT(OBJ_CUSTOMSHAPE ): pObj=new SdrObjCustomShape(); break; + case USHORT(OBJ_MEDIA ): pObj=new SdrMediaObj(); break; + case USHORT(OBJ_TABLE ): pObj=new ::sdr::table::SdrTableObj(pModel); break; + } + } + + if(pObj == NULL) + { + SdrObjFactory* pFact=new SdrObjFactory(nInvent,nIdent,pPage,pModel); + SdrLinkList& rLL=ImpGetUserMakeObjHdl(); + unsigned nAnz=rLL.GetLinkCount(); + unsigned i=0; + while (i<nAnz && pObj==NULL) { + rLL.GetLink(i).Call((void*)pFact); + pObj=pFact->pNewObj; + i++; + } + delete pFact; + } + + if(pObj == NULL) + { + // Na wenn's denn keiner will ... + } + + if(pObj != NULL) + { + if(pPage != NULL) + pObj->SetPage(pPage); + else if(pModel != NULL) + pObj->SetModel(pModel); + } + + return pObj; +} + +SdrObjUserData* SdrObjFactory::MakeNewObjUserData(UINT32 nInvent, UINT16 nIdent, SdrObject* pObj1) +{ + SdrObjUserData* pData=NULL; + if (nInvent==SdrInventor) { + switch (nIdent) + { + case USHORT(SDRUSERDATA_OBJTEXTLINK) : pData=new ImpSdrObjTextLinkUserData((SdrTextObj*)pObj1); break; + } + } + if (pData==NULL) { + SdrObjFactory aFact(nInvent,nIdent,pObj1); + SdrLinkList& rLL=ImpGetUserMakeObjUserDataHdl(); + unsigned nAnz=rLL.GetLinkCount(); + unsigned i=0; + while (i<nAnz && pData==NULL) { + rLL.GetLink(i).Call((void*)&aFact); + pData=aFact.pNewData; + i++; + } + } + return pData; +} + +void SdrObjFactory::InsertMakeObjectHdl(const Link& rLink) +{ + SdrLinkList& rLL=ImpGetUserMakeObjHdl(); + rLL.InsertLink(rLink); +} + +void SdrObjFactory::RemoveMakeObjectHdl(const Link& rLink) +{ + SdrLinkList& rLL=ImpGetUserMakeObjHdl(); + rLL.RemoveLink(rLink); +} + +void SdrObjFactory::InsertMakeUserDataHdl(const Link& rLink) +{ + SdrLinkList& rLL=ImpGetUserMakeObjUserDataHdl(); + rLL.InsertLink(rLink); +} + +void SdrObjFactory::RemoveMakeUserDataHdl(const Link& rLink) +{ + SdrLinkList& rLL=ImpGetUserMakeObjUserDataHdl(); + rLL.RemoveLink(rLink); +} + +namespace svx +{ + ISdrObjectFilter::~ISdrObjectFilter() + { + } +} + +// eof diff --git a/svx/source/svdraw/svdocapt.cxx b/svx/source/svdraw/svdocapt.cxx new file mode 100644 index 000000000000..b92157823081 --- /dev/null +++ b/svx/source/svdraw/svdocapt.cxx @@ -0,0 +1,851 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <tools/bigint.hxx> +#include <svx/xlnwtit.hxx> +#include <svl/style.hxx> +#include <svx/svdocapt.hxx> +#include <svx/xpool.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdattrx.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdhdl.hxx> +#include <svx/svddrag.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdview.hxx> // fuer RectSnap +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname +#include <svx/svdogrp.hxx> +#include <svx/svdpage.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xfltrit.hxx> +#include <editeng/eeitem.hxx> +#include <svx/sdr/properties/captionproperties.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <svx/sdr/contact/viewcontactofsdrcaptionobj.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <svx/sdrhittesthelper.hxx> + +// #i32599# +inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } +inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +enum EscDir {LKS,RTS,OBN,UNT}; + +class ImpCaptParams +{ +public: + SdrCaptionType eType; + long nAngle; + long nGap; + long nEscRel; + long nEscAbs; + long nLineLen; + SdrCaptionEscDir eEscDir; + FASTBOOL bFitLineLen; + FASTBOOL bEscRel; + FASTBOOL bFixedAngle; + +public: + ImpCaptParams() + { + eType =SDRCAPT_TYPE3; + bFixedAngle=FALSE; + nAngle =4500; + nGap =0; + eEscDir =SDRCAPT_ESCHORIZONTAL; + bEscRel =TRUE; + nEscRel =5000; + nEscAbs =0; + nLineLen =0; + bFitLineLen=TRUE; + } + void CalcEscPos(const Point& rTail, const Rectangle& rRect, Point& rPt, EscDir& rDir) const; +}; + +void ImpCaptParams::CalcEscPos(const Point& rTailPt, const Rectangle& rRect, Point& rPt, EscDir& rDir) const +{ + Point aTl(rTailPt); // lokal kopieren wg. Performance + long nX,nY; + if (bEscRel) { + nX=rRect.Right()-rRect.Left(); + nX=BigMulDiv(nX,nEscRel,10000); + nY=rRect.Bottom()-rRect.Top(); + nY=BigMulDiv(nY,nEscRel,10000); + } else { + nX=nEscAbs; + nY=nEscAbs; + } + nX+=rRect.Left(); + nY+=rRect.Top(); + Point aBestPt; + EscDir eBestDir=LKS; + FASTBOOL bTryH=eEscDir==SDRCAPT_ESCBESTFIT; + if (!bTryH) { + if (eType!=SDRCAPT_TYPE1) { + bTryH=eEscDir==SDRCAPT_ESCHORIZONTAL; + } else { + bTryH=eEscDir==SDRCAPT_ESCVERTICAL; + } + } + FASTBOOL bTryV=eEscDir==SDRCAPT_ESCBESTFIT; + if (!bTryV) { + if (eType!=SDRCAPT_TYPE1) { + bTryV=eEscDir==SDRCAPT_ESCVERTICAL; + } else { + bTryV=eEscDir==SDRCAPT_ESCHORIZONTAL; + } + } + + if (bTryH) { + Point aLft(rRect.Left()-nGap,nY); + Point aRgt(rRect.Right()+nGap,nY); + FASTBOOL bLft=(aTl.X()-aLft.X()<aRgt.X()-aTl.X()); + if (bLft) { + eBestDir=LKS; + aBestPt=aLft; + } else { + eBestDir=RTS; + aBestPt=aRgt; + } + } + if (bTryV) { + Point aTop(nX,rRect.Top()-nGap); + Point aBtm(nX,rRect.Bottom()+nGap); + FASTBOOL bTop=(aTl.Y()-aTop.Y()<aBtm.Y()-aTl.Y()); + Point aBest2; + EscDir eBest2; + if (bTop) { + eBest2=OBN; + aBest2=aTop; + } else { + eBest2=UNT; + aBest2=aBtm; + } + FASTBOOL bTakeIt=eEscDir!=SDRCAPT_ESCBESTFIT; + if (!bTakeIt) { + BigInt aHorX(aBestPt.X()-aTl.X()); aHorX*=aHorX; + BigInt aHorY(aBestPt.Y()-aTl.Y()); aHorY*=aHorY; + BigInt aVerX(aBest2.X()-aTl.X()); aVerX*=aVerX; + BigInt aVerY(aBest2.Y()-aTl.Y()); aVerY*=aVerY; + if (eType!=SDRCAPT_TYPE1) { + bTakeIt=aVerX+aVerY<aHorX+aHorY; + } else { + bTakeIt=aVerX+aVerY>=aHorX+aHorY; + } + } + if (bTakeIt) { + aBestPt=aBest2; + eBestDir=eBest2; + } + } + rPt=aBestPt; + rDir=eBestDir; +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrCaptionObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::CaptionProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrCaptionObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrCaptionObj(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrCaptionObj,SdrRectObj); + +SdrCaptionObj::SdrCaptionObj(): + SdrRectObj(OBJ_TEXT), + aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien + mbSpecialTextBoxShadow(FALSE), + mbFixedTail(FALSE) +{ +} + +SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect): + SdrRectObj(OBJ_TEXT,rRect), + aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien + mbSpecialTextBoxShadow(FALSE), + mbFixedTail(FALSE) +{ +} + +SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect, const Point& rTail): + SdrRectObj(OBJ_TEXT,rRect), + aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien + mbSpecialTextBoxShadow(FALSE), + mbFixedTail(FALSE) +{ + aTailPoly[0]=maFixedTailPos=rTail; +} + +SdrCaptionObj::~SdrCaptionObj() +{ +} + +void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bRotateFreeAllowed=FALSE; + rInfo.bRotate90Allowed =FALSE; + rInfo.bMirrorFreeAllowed=FALSE; + rInfo.bMirror45Allowed =FALSE; + rInfo.bMirror90Allowed =FALSE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =FALSE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bCanConvToPath =TRUE; + rInfo.bCanConvToPoly =TRUE; + rInfo.bCanConvToPathLineToArea=FALSE; + rInfo.bCanConvToPolyLineToArea=FALSE; + rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +UINT16 SdrCaptionObj::GetObjIdentifier() const +{ + return UINT16(OBJ_CAPTION); +} + +void SdrCaptionObj::operator=(const SdrObject& rObj) +{ + SdrRectObj::operator=(rObj); + aTailPoly=((SdrCaptionObj&)rObj).aTailPoly; +} + +void SdrCaptionObj::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulCAPTION); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrCaptionObj::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralCAPTION); +} + +basegfx::B2DPolyPolygon SdrCaptionObj::TakeXorPoly() const +{ + basegfx::B2DPolyPolygon aPolyPoly(SdrRectObj::TakeXorPoly()); + aPolyPoly.append(aTailPoly.getB2DPolygon()); + + return aPolyPoly; +} + +sal_uInt32 SdrCaptionObj::GetHdlCount() const +{ + sal_uInt32 nAnz1(SdrRectObj::GetHdlCount()); + // sal_uInt32 nAnz2(aTailPoly.GetSize()); + // Derzeit ist nur das Draggen des Schwanzendes implementiert + return nAnz1 + 1L; +} + +SdrHdl* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum) const +{ + const sal_uInt32 nRectHdlAnz(SdrRectObj::GetHdlCount()); + + if(nHdlNum < nRectHdlAnz) + { + return SdrRectObj::GetHdl(nHdlNum); + } + else + { + sal_uInt32 nPntNum(nHdlNum); + nPntNum -= nRectHdlAnz; + + if(nPntNum < aTailPoly.GetSize()) + { + SdrHdl* pHdl = new SdrHdl(aTailPoly.GetPoint((sal_uInt16)nPntNum), HDL_POLY); + pHdl->SetPolyNum(1L); + pHdl->SetPointNum(nPntNum); + return pHdl; + } + else + { + return 0L; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrCaptionObj::hasSpecialDrag() const +{ + return true; +} + +bool SdrCaptionObj::beginSpecialDrag(SdrDragStat& rDrag) const +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + rDrag.SetEndDragChangesAttributes(true); + rDrag.SetEndDragChangesGeoAndAttributes(true); + + if(pHdl && 0 == pHdl->GetPolyNum()) + { + return SdrRectObj::beginSpecialDrag(rDrag); + } + else + { + rDrag.SetOrtho8Possible(true); + + if(!pHdl) + { + if (bMovProt) + return 0; + + rDrag.SetNoSnap(true); + rDrag.SetActionRect(aRect); + + Point aHit(rDrag.GetStart()); + + if(rDrag.GetPageView() && SdrObjectPrimitiveHit(*this, aHit, 0, *rDrag.GetPageView(), 0, false)) + { + return true; + } + } + else + { + if((1 == pHdl->GetPolyNum()) && (0 == pHdl->GetPointNum())) + return true; + } + } + + return false; +} + +bool SdrCaptionObj::applySpecialDrag(SdrDragStat& rDrag) +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + + if(pHdl && 0 == pHdl->GetPolyNum()) + { + const bool bRet(SdrRectObj::applySpecialDrag(rDrag)); + ImpRecalcTail(); + ActionChanged(); + + return bRet; + } + else + { + Point aDelt(rDrag.GetNow()-rDrag.GetStart()); + + if(!pHdl) + { + aRect.Move(aDelt.X(),aDelt.Y()); + } + else + { + aTailPoly[0] += aDelt; + } + + ImpRecalcTail(); + ActionChanged(); + + return true; + } +} + +String SdrCaptionObj::getSpecialDragComment(const SdrDragStat& rDrag) const +{ + const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj()); + + if(bCreateComment) + { + return String(); + } + else + { + const SdrHdl* pHdl = rDrag.GetHdl(); + + if(pHdl && 0 == pHdl->GetPolyNum()) + { + return SdrRectObj::getSpecialDragComment(rDrag); + } + else + { + XubString aStr; + + if(!pHdl) + { + ImpTakeDescriptionStr(STR_DragCaptFram, aStr); + } + else + { + ImpTakeDescriptionStr(STR_DragCaptTail, aStr); + } + + return aStr; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams& rPara) const +{ + const SfxItemSet& rSet = GetObjectItemSet(); + rPara.eType =((SdrCaptionTypeItem&) (rSet.Get(SDRATTR_CAPTIONTYPE ))).GetValue(); + rPara.bFixedAngle=((SdrCaptionFixedAngleItem&)(rSet.Get(SDRATTR_CAPTIONANGLE ))).GetValue(); + rPara.nAngle =((SdrCaptionAngleItem&) (rSet.Get(SDRATTR_CAPTIONFIXEDANGLE))).GetValue(); + rPara.nGap =((SdrCaptionGapItem&) (rSet.Get(SDRATTR_CAPTIONGAP ))).GetValue(); + rPara.eEscDir =((SdrCaptionEscDirItem&) (rSet.Get(SDRATTR_CAPTIONESCDIR ))).GetValue(); + rPara.bEscRel =((SdrCaptionEscIsRelItem&) (rSet.Get(SDRATTR_CAPTIONESCISREL ))).GetValue(); + rPara.nEscRel =((SdrCaptionEscRelItem&) (rSet.Get(SDRATTR_CAPTIONESCREL ))).GetValue(); + rPara.nEscAbs =((SdrCaptionEscAbsItem&) (rSet.Get(SDRATTR_CAPTIONESCABS ))).GetValue(); + rPara.nLineLen =((SdrCaptionLineLenItem&) (rSet.Get(SDRATTR_CAPTIONLINELEN ))).GetValue(); + rPara.bFitLineLen=((SdrCaptionFitLineLenItem&)(rSet.Get(SDRATTR_CAPTIONFITLINELEN))).GetValue(); +} + +void SdrCaptionObj::ImpRecalcTail() +{ + ImpCaptParams aPara; + ImpGetCaptParams(aPara); + ImpCalcTail(aPara,aTailPoly,aRect); + SetRectsDirty(); + SetXPolyDirty(); +} + +// #i35971# +// SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack. +// I really wonder why this had not triggered problems before. I am +// sure there are some places where SetTailPos() is called at least +// twice or SetSnapRect after it again just to work around this. +// Changed this method to not do that. +// Also found why this has been done: For interactive dragging of the +// tail end pos for SDRCAPT_TYPE1. This sure was the simplest method +// to achieve this, for the cost to make a whole group of const methods +// of this object implicitly chainging the object's position. +void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const +{ + Polygon aPol(2); + Point aTl(rPoly[0]); + + aPol[0] = aTl; + aPol[1] = aTl; + + EscDir eEscDir; + Point aEscPos; + + rPara.CalcEscPos(aTl, rRect, aEscPos, eEscDir); + aPol[1] = aEscPos; + + if(eEscDir==LKS || eEscDir==RTS) + { + aPol[0].X() = aEscPos.X(); + } + else + { + aPol[0].Y() = aEscPos.Y(); + } + + rPoly = aPol; +} + +void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const +{ // Gap/EscDir/EscPos/Angle + Polygon aPol(2); + Point aTl(rPoly[0]); + aPol[0]=aTl; + + EscDir eEscDir; + Point aEscPos; + rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir); + aPol[1]=aEscPos; + + if (!rPara.bFixedAngle) { + // fehlende Implementation + } + rPoly=aPol; +} + +void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const +{ // Gap/EscDir/EscPos/Angle/LineLen + Polygon aPol(3); + Point aTl(rPoly[0]); + aPol[0]=aTl; + + EscDir eEscDir; + Point aEscPos; + rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir); + aPol[1]=aEscPos; + aPol[2]=aEscPos; + + if (eEscDir==LKS || eEscDir==RTS) { + if (rPara.bFitLineLen) { + aPol[1].X()=(aTl.X()+aEscPos.X())/2; + } else { + if (eEscDir==LKS) aPol[1].X()-=rPara.nLineLen; + else aPol[1].X()+=rPara.nLineLen; + } + } else { + if (rPara.bFitLineLen) { + aPol[1].Y()=(aTl.Y()+aEscPos.Y())/2; + } else { + if (eEscDir==OBN) aPol[1].Y()-=rPara.nLineLen; + else aPol[1].Y()+=rPara.nLineLen; + } + } + if (!rPara.bFixedAngle) { + // fehlende Implementation + } + rPoly=aPol; +} + +void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const +{ + ImpCalcTail3(rPara,rPoly,rRect); +} + +void SdrCaptionObj::ImpCalcTail(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const +{ + switch (rPara.eType) { + case SDRCAPT_TYPE1: ImpCalcTail1(rPara,rPoly,rRect); break; + case SDRCAPT_TYPE2: ImpCalcTail2(rPara,rPoly,rRect); break; + case SDRCAPT_TYPE3: ImpCalcTail3(rPara,rPoly,rRect); break; + case SDRCAPT_TYPE4: ImpCalcTail4(rPara,rPoly,rRect); break; + } +} + +FASTBOOL SdrCaptionObj::BegCreate(SdrDragStat& rStat) +{ + if (aRect.IsEmpty()) return FALSE; // Create z.Zt. nur mit vorgegebenen Rect + + ImpCaptParams aPara; + ImpGetCaptParams(aPara); + aRect.SetPos(rStat.GetNow()); + aTailPoly[0]=rStat.GetStart(); + ImpCalcTail(aPara,aTailPoly,aRect); + rStat.SetActionRect(aRect); + return TRUE; +} + +FASTBOOL SdrCaptionObj::MovCreate(SdrDragStat& rStat) +{ + ImpCaptParams aPara; + ImpGetCaptParams(aPara); + aRect.SetPos(rStat.GetNow()); + ImpCalcTail(aPara,aTailPoly,aRect); + rStat.SetActionRect(aRect); + SetBoundRectDirty(); + bSnapRectDirty=TRUE; + return TRUE; +} + +FASTBOOL SdrCaptionObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + ImpCaptParams aPara; + ImpGetCaptParams(aPara); + aRect.SetPos(rStat.GetNow()); + ImpCalcTail(aPara,aTailPoly,aRect); + SetRectsDirty(); + return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); +} + +FASTBOOL SdrCaptionObj::BckCreate(SdrDragStat& /*rStat*/) +{ + return FALSE; +} + +void SdrCaptionObj::BrkCreate(SdrDragStat& /*rStat*/) +{ +} + +basegfx::B2DPolyPolygon SdrCaptionObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const +{ + basegfx::B2DPolyPolygon aRetval; + const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); + aRetval.append(basegfx::tools::createPolygonFromRect(aRange)); + aRetval.append(aTailPoly.getB2DPolygon()); + return aRetval; +} + +Pointer SdrCaptionObj::GetCreatePointer() const +{ + return Pointer(POINTER_DRAW_CAPTION); +} + +void SdrCaptionObj::NbcMove(const Size& rSiz) +{ + SdrRectObj::NbcMove(rSiz); + MovePoly(aTailPoly,rSiz); + if(mbFixedTail) + SetTailPos(GetFixedTailPos()); +} + +void SdrCaptionObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + SdrRectObj::NbcResize(rRef,xFact,yFact); + ResizePoly(aTailPoly,rRef,xFact,yFact); + ImpRecalcTail(); + if(mbFixedTail) + SetTailPos(GetFixedTailPos()); +} + +void SdrCaptionObj::NbcSetRelativePos(const Point& rPnt) +{ + Point aRelPos0(aTailPoly.GetPoint(0)-aAnchor); + Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y()); + NbcMove(aSiz); // Der ruft auch das SetRectsDirty() +} + +Point SdrCaptionObj::GetRelativePos() const +{ + return aTailPoly.GetPoint(0)-aAnchor; +} + +void SdrCaptionObj::NbcSetAnchorPos(const Point& rPnt) +{ + SdrRectObj::NbcSetAnchorPos(rPnt); + // !!!!! fehlende Impl. +} + +const Point& SdrCaptionObj::GetAnchorPos() const +{ + // !!!!! fehlende Impl. + return SdrRectObj::GetAnchorPos(); +} + +void SdrCaptionObj::RecalcSnapRect() +{ + SdrRectObj::RecalcSnapRect(); + // #i32599# + // maSnapRect.Union(aTailPoly.GetBoundRect()); + // !!!!! fehlende Impl. +} + +const Rectangle& SdrCaptionObj::GetSnapRect() const +{ + return SdrRectObj::GetSnapRect(); +} + +void SdrCaptionObj::NbcSetSnapRect(const Rectangle& rRect) +{ + // #i32599# + // Move back to see the rectangle of the underlying SdrRectObj + // as the SnapRect, without the TailPos. That simplifies SnapRect + // handling again, if not allows it at all... + SdrRectObj::NbcSetSnapRect(rRect); +} + +const Rectangle& SdrCaptionObj::GetLogicRect() const +{ + return aRect; +} + +void SdrCaptionObj::NbcSetLogicRect(const Rectangle& rRect) +{ + SdrRectObj::NbcSetLogicRect(rRect); + ImpRecalcTail(); +} + +const Point& SdrCaptionObj::GetTailPos() const +{ + return aTailPoly[0]; +} + +void SdrCaptionObj::SetTailPos(const Point& rPos) +{ + if (aTailPoly.GetSize()==0 || aTailPoly[0]!=rPos) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetTailPos(rPos); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrCaptionObj::NbcSetTailPos(const Point& rPos) +{ + aTailPoly[0]=rPos; + ImpRecalcTail(); +} + +sal_uInt32 SdrCaptionObj::GetSnapPointCount() const +{ + // !!!!! fehlende Impl. + return 0L; +} + +Point SdrCaptionObj::GetSnapPoint(sal_uInt32 /*i*/) const +{ + // !!!!! fehlende Impl. + return Point(0,0); +} + +void SdrCaptionObj::SetModel(SdrModel* pNewModel) +{ + SdrRectObj::SetModel(pNewModel); + ImpRecalcTail(); +} + +void SdrCaptionObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + SdrRectObj::Notify(rBC,rHint); + ImpRecalcTail(); +} + +SdrObjGeoData* SdrCaptionObj::NewGeoData() const +{ + return new SdrCaptObjGeoData; +} + +void SdrCaptionObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrRectObj::SaveGeoData(rGeo); + SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo; + rCGeo.aTailPoly=aTailPoly; +} + +void SdrCaptionObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrRectObj::RestGeoData(rGeo); + SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo; + aTailPoly=rCGeo.aTailPoly; +} + +SdrObject* SdrCaptionObj::DoConvertToPolyObj(BOOL bBezier) const +{ // #42334# - Convert implementiert + SdrObject* pRect=SdrRectObj::DoConvertToPolyObj(bBezier); + SdrObject* pTail = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly.getB2DPolygon()), sal_False, bBezier); + SdrObject* pRet=(pTail!=NULL) ? pTail : pRect; + if (pTail!=NULL && pRect!=NULL) { + FASTBOOL bInsRect=TRUE; + FASTBOOL bInsTail=TRUE; + SdrObjList* pOL=pTail->GetSubList(); + if (pOL!=NULL) { pRet=pRect; bInsTail=FALSE; } + if (pOL==NULL) pOL=pRect->GetSubList(); + if (pOL!=NULL) { pRet=pRect; bInsRect=FALSE; } + if (pOL==NULL) { + SdrObjGroup* pGrp=new SdrObjGroup; + pOL=pGrp->GetSubList(); + pRet=pGrp; + } + if (bInsRect) pOL->NbcInsertObject(pRect); + if (bInsTail) pOL->NbcInsertObject(pTail,0); + } + return pRet; +} + +// #i32599# +// Add own implementation for TRSetBaseGeometry to handle TailPos over changes. +void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) +{ + // break up matrix + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate, fShearX; + rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings + // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale.setX(fabs(aScale.getX())); + aScale.setY(fabs(aScale.getY())); + fRotate = fmod(fRotate + F_PI, F_2PI); + } + + // force metric to pool metric + SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // position + aTranslate.setX(ImplMMToTwips(aTranslate.getX())); + aTranslate.setY(ImplMMToTwips(aTranslate.getY())); + + // size + aScale.setX(ImplMMToTwips(aScale.getX())); + aScale.setY(ImplMMToTwips(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); + } + } + } + + // if anchor is used, make position relative to it + if( pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // build BaseRect + Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY())); + Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY()))); + + // set BaseRect, but rescue TailPos over this call + const Point aTailPoint = GetTailPos(); + SetSnapRect(aBaseRect); + SetTailPos(aTailPoint); + ImpRecalcTail(); +} + +// geometry access +basegfx::B2DPolygon SdrCaptionObj::getTailPolygon() const +{ + return aTailPoly.getB2DPolygon(); +} + +// eof diff --git a/svx/source/svdraw/svdocirc.cxx b/svx/source/svdraw/svdocirc.cxx new file mode 100644 index 000000000000..4c600cba821f --- /dev/null +++ b/svx/source/svdraw/svdocirc.cxx @@ -0,0 +1,1171 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svl/style.hxx> +#include <tools/bigint.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/svdocirc.hxx> +#include <math.h> +#include <svx/xpool.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdattrx.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svddrag.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdopath.hxx> // fuer die Objektkonvertierung +#include <svx/svdview.hxx> // Zum Draggen (Ortho) +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname +#include <editeng/eeitem.hxx> +#include "svdoimp.hxx" +#include <svx/sdr/properties/circleproperties.hxx> +#include <svx/sdr/contact/viewcontactofsdrcircobj.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +Point GetWinkPnt(const Rectangle& rR, long nWink) +{ + Point aCenter(rR.Center()); + long nWdt=rR.Right()-rR.Left(); + long nHgt=rR.Bottom()-rR.Top(); + long nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2; + double a; + a=nWink*nPi180; + Point aRetval(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad)); + if (nWdt==0) aRetval.X()=0; + if (nHgt==0) aRetval.Y()=0; + if (nWdt!=nHgt) { + if (nWdt>nHgt) { + if (nWdt!=0) { + // eventuelle Ueberlaeufe bei sehr grossen Objekten abfangen (Bug 23384) + if (Abs(nHgt)>32767 || Abs(aRetval.Y())>32767) { + aRetval.Y()=BigMulDiv(aRetval.Y(),nHgt,nWdt); + } else { + aRetval.Y()=aRetval.Y()*nHgt/nWdt; + } + } + } else { + if (nHgt!=0) { + // eventuelle Ueberlaeufe bei sehr grossen Objekten abfangen (Bug 23384) + if (Abs(nWdt)>32767 || Abs(aRetval.X())>32767) { + aRetval.X()=BigMulDiv(aRetval.X(),nWdt,nHgt); + } else { + aRetval.X()=aRetval.X()*nWdt/nHgt; + } + } + } + } + aRetval+=aCenter; + return aRetval; +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrCircObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::CircleProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrCircObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrCircObj(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrCircObj,SdrRectObj); + +SdrCircObj::SdrCircObj(SdrObjKind eNewKind) +{ + nStartWink=0; + nEndWink=36000; + meCircleKind=eNewKind; + bClosedObj=eNewKind!=OBJ_CARC; +} + +SdrCircObj::SdrCircObj(SdrObjKind eNewKind, const Rectangle& rRect): + SdrRectObj(rRect) +{ + nStartWink=0; + nEndWink=36000; + meCircleKind=eNewKind; + bClosedObj=eNewKind!=OBJ_CARC; +} + +SdrCircObj::SdrCircObj(SdrObjKind eNewKind, const Rectangle& rRect, long nNewStartWink, long nNewEndWink): + SdrRectObj(rRect) +{ + long nWinkDif=nNewEndWink-nNewStartWink; + nStartWink=NormAngle360(nNewStartWink); + nEndWink=NormAngle360(nNewEndWink); + if (nWinkDif==36000) nEndWink+=nWinkDif; // Vollkreis + meCircleKind=eNewKind; + bClosedObj=eNewKind!=OBJ_CARC; +} + +SdrCircObj::~SdrCircObj() +{ +} + +void SdrCircObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + FASTBOOL bCanConv=!HasText() || ImpCanConvTextToCurve(); + rInfo.bEdgeRadiusAllowed = FALSE; + rInfo.bCanConvToPath=bCanConv; + rInfo.bCanConvToPoly=bCanConv; + rInfo.bCanConvToContour = !IsFontwork() && (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +UINT16 SdrCircObj::GetObjIdentifier() const +{ + return UINT16(meCircleKind); +} + +FASTBOOL SdrCircObj::PaintNeedsXPolyCirc() const +{ + // XPoly ist notwendig fuer alle gedrehten Ellipsenobjekte, + // fuer alle Kreis- und Ellipsenabschnitte + // und wenn nicht WIN dann (erstmal) auch fuer Kreis-/Ellipsenausschnitte + // und Kreis-/Ellipsenboegen (wg. Genauigkeit) + FASTBOOL bNeed=aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || meCircleKind==OBJ_CCUT; +#ifndef WIN + // Wenn nicht Win, dann fuer alle ausser Vollkreis (erstmal!!!) + if (meCircleKind!=OBJ_CIRC) bNeed=TRUE; +#endif + + const SfxItemSet& rSet = GetObjectItemSet(); + if(!bNeed) + { + // XPoly ist notwendig fuer alles was nicht LineSolid oder LineNone ist + XLineStyle eLine = ((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue(); + bNeed = eLine != XLINE_NONE && eLine != XLINE_SOLID; + + // XPoly ist notwendig fuer dicke Linien + if(!bNeed && eLine != XLINE_NONE) + bNeed = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue() != 0; + + // XPoly ist notwendig fuer Kreisboegen mit Linienenden + if(!bNeed && meCircleKind == OBJ_CARC) + { + // Linienanfang ist da, wenn StartPolygon und StartWidth!=0 + bNeed=((XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetLineStartValue().count() != 0L && + ((XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue() != 0; + + if(!bNeed) + { + // Linienende ist da, wenn EndPolygon und EndWidth!=0 + bNeed = ((XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetLineEndValue().count() != 0L && + ((XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue() != 0; + } + } + } + + // XPoly ist notwendig, wenn Fill !=None und !=Solid + if(!bNeed && meCircleKind != OBJ_CARC) + { + XFillStyle eFill=((XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue(); + bNeed = eFill != XFILL_NONE && eFill != XFILL_SOLID; + } + + if(!bNeed && meCircleKind != OBJ_CIRC && nStartWink == nEndWink) + bNeed=TRUE; // Weil sonst Vollkreis gemalt wird + + return bNeed; +} + +basegfx::B2DPolygon SdrCircObj::ImpCalcXPolyCirc(const SdrObjKind eCicrleKind, const Rectangle& rRect1, long nStart, long nEnd) const +{ + const basegfx::B2DRange aRange(rRect1.Left(), rRect1.Top(), rRect1.Right(), rRect1.Bottom()); + basegfx::B2DPolygon aCircPolygon; + + if(OBJ_CIRC == eCicrleKind) + { + // create full circle. Do not use createPolygonFromEllipse; it's necessary + // to get the start point to the bottom of the circle to keep compatible to + // old geometry creation + aCircPolygon = basegfx::tools::createPolygonFromUnitCircle(1); + + // needs own scaling and translation from unit circle to target size (same as + // would be in createPolygonFromEllipse) + const basegfx::B2DPoint aCenter(aRange.getCenter()); + const basegfx::B2DHomMatrix aMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix( + aRange.getWidth() / 2.0, aRange.getHeight() / 2.0, + aCenter.getX(), aCenter.getY())); + aCircPolygon.transform(aMatrix); + } + else + { + // mirror start, end for geometry creation since model coordinate system is mirrored in Y + // #i111715# increase numerical correctness by first dividing and not using F_PI1800 + const double fStart((((36000 - nEnd) % 36000) / 18000.0) * F_PI); + const double fEnd((((36000 - nStart) % 36000) / 18000.0) * F_PI); + + // create circle segment. This is not closed by default + aCircPolygon = basegfx::tools::createPolygonFromEllipseSegment( + aRange.getCenter(), aRange.getWidth() / 2.0, aRange.getHeight() / 2.0, + fStart, fEnd); + + // check closing states + const bool bCloseSegment(OBJ_CARC != eCicrleKind); + const bool bCloseUsingCenter(OBJ_SECT == eCicrleKind); + + if(bCloseSegment) + { + if(bCloseUsingCenter) + { + // add center point at start (for historical reasons) + basegfx::B2DPolygon aSector; + aSector.append(aRange.getCenter()); + aSector.append(aCircPolygon); + aCircPolygon = aSector; + } + + // close + aCircPolygon.setClosed(true); + } + } + + // #i76950# + if(aGeo.nShearWink || aGeo.nDrehWink) + { + // translate top left to (0,0) + const basegfx::B2DPoint aTopLeft(aRange.getMinimum()); + basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix( + -aTopLeft.getX(), -aTopLeft.getY())); + + // shear, rotate and back to top left (if needed) + aMatrix = basegfx::tools::createShearXRotateTranslateB2DHomMatrix( + aGeo.nShearWink ? tan((36000 - aGeo.nShearWink) * F_PI18000) : 0.0, + aGeo.nDrehWink ? (36000 - aGeo.nDrehWink) * F_PI18000 : 0.0, + aTopLeft) * aMatrix; + + // apply transformation + aCircPolygon.transform(aMatrix); + } + + return aCircPolygon; +} + +void SdrCircObj::RecalcXPoly() +{ + const basegfx::B2DPolygon aPolyCirc(ImpCalcXPolyCirc(meCircleKind, aRect, nStartWink, nEndWink)); + mpXPoly = new XPolygon(aPolyCirc); +} + +void SdrCircObj::TakeObjNameSingul(XubString& rName) const +{ + USHORT nID=STR_ObjNameSingulCIRC; + if (aRect.GetWidth()==aRect.GetHeight() && aGeo.nShearWink==0) { + switch (meCircleKind) { + case OBJ_CIRC: nID=STR_ObjNameSingulCIRC; break; + case OBJ_SECT: nID=STR_ObjNameSingulSECT; break; + case OBJ_CARC: nID=STR_ObjNameSingulCARC; break; + case OBJ_CCUT: nID=STR_ObjNameSingulCCUT; break; + default: break; + } + } else { + switch (meCircleKind) { + case OBJ_CIRC: nID=STR_ObjNameSingulCIRCE; break; + case OBJ_SECT: nID=STR_ObjNameSingulSECTE; break; + case OBJ_CARC: nID=STR_ObjNameSingulCARCE; break; + case OBJ_CCUT: nID=STR_ObjNameSingulCCUTE; break; + default: break; + } + } + rName=ImpGetResStr(nID); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrCircObj::TakeObjNamePlural(XubString& rName) const +{ + USHORT nID=STR_ObjNamePluralCIRC; + if (aRect.GetWidth()==aRect.GetHeight() && aGeo.nShearWink==0) { + switch (meCircleKind) { + case OBJ_CIRC: nID=STR_ObjNamePluralCIRC; break; + case OBJ_SECT: nID=STR_ObjNamePluralSECT; break; + case OBJ_CARC: nID=STR_ObjNamePluralCARC; break; + case OBJ_CCUT: nID=STR_ObjNamePluralCCUT; break; + default: break; + } + } else { + switch (meCircleKind) { + case OBJ_CIRC: nID=STR_ObjNamePluralCIRCE; break; + case OBJ_SECT: nID=STR_ObjNamePluralSECTE; break; + case OBJ_CARC: nID=STR_ObjNamePluralCARCE; break; + case OBJ_CCUT: nID=STR_ObjNamePluralCCUTE; break; + default: break; + } + } + rName=ImpGetResStr(nID); +} + +void SdrCircObj::operator=(const SdrObject& rObj) +{ + SdrRectObj::operator=(rObj); + + nStartWink = ((SdrCircObj&)rObj).nStartWink; + nEndWink = ((SdrCircObj&)rObj).nEndWink; +} + +basegfx::B2DPolyPolygon SdrCircObj::TakeXorPoly() const +{ + const basegfx::B2DPolygon aCircPolygon(ImpCalcXPolyCirc(meCircleKind, aRect, nStartWink, nEndWink)); + return basegfx::B2DPolyPolygon(aCircPolygon); +} + +struct ImpCircUser : public SdrDragStatUserData +{ + Rectangle aR; + Point aCenter; + Point aRadius; + Point aP1; + Point aP2; + long nMaxRad; + long nHgt; + long nWdt; + long nStart; + long nEnd; + long nWink; + FASTBOOL bRight; // noch nicht implementiert + +public: + ImpCircUser() + : nMaxRad(0), + nHgt(0), + nWdt(0), + nStart(0), + nEnd(0), + bRight(FALSE) + {} + void SetCreateParams(SdrDragStat& rStat); +}; + +sal_uInt32 SdrCircObj::GetHdlCount() const +{ + if(OBJ_CIRC != meCircleKind) + { + return 10L; + } + else + { + return 8L; + } +} + +SdrHdl* SdrCircObj::GetHdl(sal_uInt32 nHdlNum) const +{ + if (meCircleKind==OBJ_CIRC) + { + nHdlNum += 2L; + } + + SdrHdl* pH = NULL; + Point aPnt; + SdrHdlKind eLocalKind(HDL_MOVE); + sal_uInt32 nPNum(0); + + switch (nHdlNum) + { + case 0: + aPnt = GetWinkPnt(aRect,nStartWink); + eLocalKind = HDL_CIRC; + nPNum = 1; + break; + case 1: + aPnt = GetWinkPnt(aRect,nEndWink); + eLocalKind = HDL_CIRC; + nPNum = 2L; + break; + case 2: + aPnt = aRect.TopLeft(); + eLocalKind = HDL_UPLFT; + break; + case 3: + aPnt = aRect.TopCenter(); + eLocalKind = HDL_UPPER; + break; + case 4: + aPnt = aRect.TopRight(); + eLocalKind = HDL_UPRGT; + break; + case 5: + aPnt = aRect.LeftCenter(); + eLocalKind = HDL_LEFT; + break; + case 6: + aPnt = aRect.RightCenter(); + eLocalKind = HDL_RIGHT; + break; + case 7: + aPnt = aRect.BottomLeft(); + eLocalKind = HDL_LWLFT; + break; + case 8: + aPnt = aRect.BottomCenter(); + eLocalKind = HDL_LOWER; + break; + case 9: + aPnt = aRect.BottomRight(); + eLocalKind = HDL_LWRGT; + break; + } + + if (aGeo.nShearWink) + { + ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan); + } + + if (aGeo.nDrehWink) + { + RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + } + + if (eLocalKind != HDL_MOVE) + { + pH = new SdrHdl(aPnt,eLocalKind); + pH->SetPointNum(nPNum); + pH->SetObj((SdrObject*)this); + pH->SetDrehWink(aGeo.nDrehWink); + } + + return pH; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrCircObj::hasSpecialDrag() const +{ + return true; +} + +bool SdrCircObj::beginSpecialDrag(SdrDragStat& rDrag) const +{ + const bool bWink(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); + + if(bWink) + { + if(1 == rDrag.GetHdl()->GetPointNum() || 2 == rDrag.GetHdl()->GetPointNum()) + { + rDrag.SetNoSnap(true); + } + + return true; + } + + return SdrTextObj::beginSpecialDrag(rDrag); +} + +bool SdrCircObj::applySpecialDrag(SdrDragStat& rDrag) +{ + const bool bWink(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); + + if(bWink) + { + Point aPt(rDrag.GetNow()); + + if (aGeo.nDrehWink!=0) + RotatePoint(aPt,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); + + if (aGeo.nShearWink!=0) + ShearPoint(aPt,aRect.TopLeft(),-aGeo.nTan); + + aPt-=aRect.Center(); + + long nWdt=aRect.Right()-aRect.Left(); + long nHgt=aRect.Bottom()-aRect.Top(); + + if(nWdt>=nHgt) + { + aPt.Y()=BigMulDiv(aPt.Y(),nWdt,nHgt); + } + else + { + aPt.X()=BigMulDiv(aPt.X(),nHgt,nWdt); + } + + long nWink=NormAngle360(GetAngle(aPt)); + + if (rDrag.GetView() && rDrag.GetView()->IsAngleSnapEnabled()) + { + long nSA=rDrag.GetView()->GetSnapAngle(); + + if (nSA!=0) + { + nWink+=nSA/2; + nWink/=nSA; + nWink*=nSA; + nWink=NormAngle360(nWink); + } + } + + if(1 == rDrag.GetHdl()->GetPointNum()) + { + nStartWink = nWink; + } + else if(2 == rDrag.GetHdl()->GetPointNum()) + { + nEndWink = nWink; + } + + SetRectsDirty(); + SetXPolyDirty(); + ImpSetCircInfoToAttr(); + SetChanged(); + + return true; + } + else + { + return SdrTextObj::applySpecialDrag(rDrag); + } +} + +String SdrCircObj::getSpecialDragComment(const SdrDragStat& rDrag) const +{ + const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj()); + + if(bCreateComment) + { + XubString aStr; + ImpTakeDescriptionStr(STR_ViewCreateObj, aStr); + const sal_uInt32 nPntAnz(rDrag.GetPointAnz()); + + if(OBJ_CIRC != meCircleKind && nPntAnz > 2) + { + ImpCircUser* pU = (ImpCircUser*)rDrag.GetUser(); + sal_Int32 nWink; + + aStr.AppendAscii(" ("); + + if(3 == nPntAnz) + { + nWink = pU->nStart; + } + else + { + nWink = pU->nEnd; + } + + aStr += GetWinkStr(nWink,FALSE); + aStr += sal_Unicode(')'); + } + + return aStr; + } + else + { + const bool bWink(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); + + if(bWink) + { + XubString aStr; + const sal_Int32 nWink(1 == rDrag.GetHdl()->GetPointNum() ? nStartWink : nEndWink); + + ImpTakeDescriptionStr(STR_DragCircAngle, aStr); + aStr.AppendAscii(" ("); + aStr += GetWinkStr(nWink,FALSE); + aStr += sal_Unicode(')'); + + return aStr; + } + else + { + return SdrTextObj::getSpecialDragComment(rDrag); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ImpCircUser::SetCreateParams(SdrDragStat& rStat) +{ + rStat.TakeCreateRect(aR); + aR.Justify(); + aCenter=aR.Center(); + nWdt=aR.Right()-aR.Left(); + nHgt=aR.Bottom()-aR.Top(); + nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2; + nStart=0; + nEnd=36000; + if (rStat.GetPointAnz()>2) { + Point aP(rStat.GetPoint(2)-aCenter); + if (nWdt==0) aP.X()=0; + if (nHgt==0) aP.Y()=0; + if (nWdt>=nHgt) { + if (nHgt!=0) aP.Y()=aP.Y()*nWdt/nHgt; + } else { + if (nWdt!=0) aP.X()=aP.X()*nHgt/nWdt; + } + nStart=NormAngle360(GetAngle(aP)); + if (rStat.GetView()!=NULL && rStat.GetView()->IsAngleSnapEnabled()) { + long nSA=rStat.GetView()->GetSnapAngle(); + if (nSA!=0) { // Winkelfang + nStart+=nSA/2; + nStart/=nSA; + nStart*=nSA; + nStart=NormAngle360(nStart); + } + } + aP1 = GetWinkPnt(aR,nStart); + nEnd=nStart; + aP2=aP1; + } else aP1=aCenter; + if (rStat.GetPointAnz()>3) { + Point aP(rStat.GetPoint(3)-aCenter); + if (nWdt>=nHgt) { + aP.Y()=BigMulDiv(aP.Y(),nWdt,nHgt); + } else { + aP.X()=BigMulDiv(aP.X(),nHgt,nWdt); + } + nEnd=NormAngle360(GetAngle(aP)); + if (rStat.GetView()!=NULL && rStat.GetView()->IsAngleSnapEnabled()) { + long nSA=rStat.GetView()->GetSnapAngle(); + if (nSA!=0) { // Winkelfang + nEnd+=nSA/2; + nEnd/=nSA; + nEnd*=nSA; + nEnd=NormAngle360(nEnd); + } + } + aP2 = GetWinkPnt(aR,nEnd); + } else aP2=aCenter; +} + +void SdrCircObj::ImpSetCreateParams(SdrDragStat& rStat) const +{ + ImpCircUser* pU=(ImpCircUser*)rStat.GetUser(); + if (pU==NULL) { + pU=new ImpCircUser; + rStat.SetUser(pU); + } + pU->SetCreateParams(rStat); +} + +FASTBOOL SdrCircObj::BegCreate(SdrDragStat& rStat) +{ + rStat.SetOrtho4Possible(); + Rectangle aRect1(rStat.GetStart(), rStat.GetNow()); + aRect1.Justify(); + rStat.SetActionRect(aRect1); + aRect = aRect1; + ImpSetCreateParams(rStat); + return TRUE; +} + +FASTBOOL SdrCircObj::MovCreate(SdrDragStat& rStat) +{ + ImpSetCreateParams(rStat); + ImpCircUser* pU=(ImpCircUser*)rStat.GetUser(); + rStat.SetActionRect(pU->aR); + aRect=pU->aR; // fuer ObjName + ImpJustifyRect(aRect); + nStartWink=pU->nStart; + nEndWink=pU->nEnd; + SetBoundRectDirty(); + bSnapRectDirty=TRUE; + SetXPolyDirty(); + + // #i103058# push current angle settings to ItemSet to + // allow FullDrag visualisation + if(rStat.GetPointAnz() >= 4) + { + ImpSetCircInfoToAttr(); + } + + return TRUE; +} + +FASTBOOL SdrCircObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + ImpSetCreateParams(rStat); + ImpCircUser* pU=(ImpCircUser*)rStat.GetUser(); + FASTBOOL bRet=FALSE; + if (eCmd==SDRCREATE_FORCEEND && rStat.GetPointAnz()<4) meCircleKind=OBJ_CIRC; + if (meCircleKind==OBJ_CIRC) { + bRet=rStat.GetPointAnz()>=2; + if (bRet) { + aRect=pU->aR; + ImpJustifyRect(aRect); + } + } else { + rStat.SetNoSnap(rStat.GetPointAnz()>=2); + rStat.SetOrtho4Possible(rStat.GetPointAnz()<2); + bRet=rStat.GetPointAnz()>=4; + if (bRet) { + aRect=pU->aR; + ImpJustifyRect(aRect); + nStartWink=pU->nStart; + nEndWink=pU->nEnd; + } + } + bClosedObj=meCircleKind!=OBJ_CARC; + SetRectsDirty(); + SetXPolyDirty(); + ImpSetCircInfoToAttr(); + if (bRet) { + delete pU; + rStat.SetUser(NULL); + } + return bRet; +} + +void SdrCircObj::BrkCreate(SdrDragStat& rStat) +{ + ImpCircUser* pU=(ImpCircUser*)rStat.GetUser(); + delete pU; + rStat.SetUser(NULL); +} + +FASTBOOL SdrCircObj::BckCreate(SdrDragStat& rStat) +{ + rStat.SetNoSnap(rStat.GetPointAnz()>=3); + rStat.SetOrtho4Possible(rStat.GetPointAnz()<3); + return meCircleKind!=OBJ_CIRC; +} + +basegfx::B2DPolyPolygon SdrCircObj::TakeCreatePoly(const SdrDragStat& rDrag) const +{ + ImpCircUser* pU = (ImpCircUser*)rDrag.GetUser(); + + if(rDrag.GetPointAnz() < 4L) + { + // force to OBJ_CIRC to get full visualisation + basegfx::B2DPolyPolygon aRetval(ImpCalcXPolyCirc(OBJ_CIRC, pU->aR, pU->nStart, pU->nEnd)); + + if(3L == rDrag.GetPointAnz()) + { + // add edge to first point on ellipse + basegfx::B2DPolygon aNew; + + aNew.append(basegfx::B2DPoint(pU->aCenter.X(), pU->aCenter.Y())); + aNew.append(basegfx::B2DPoint(pU->aP1.X(), pU->aP1.Y())); + aRetval.append(aNew); + } + + return aRetval; + } + else + { + return basegfx::B2DPolyPolygon(ImpCalcXPolyCirc(meCircleKind, pU->aR, pU->nStart, pU->nEnd)); + } +} + +Pointer SdrCircObj::GetCreatePointer() const +{ + switch (meCircleKind) { + case OBJ_CIRC: return Pointer(POINTER_DRAW_ELLIPSE); + case OBJ_SECT: return Pointer(POINTER_DRAW_PIE); + case OBJ_CARC: return Pointer(POINTER_DRAW_ARC); + case OBJ_CCUT: return Pointer(POINTER_DRAW_CIRCLECUT); + default: break; + } // switch + return Pointer(POINTER_CROSS); +} + +void SdrCircObj::NbcMove(const Size& aSiz) +{ + MoveRect(aRect,aSiz); + MoveRect(aOutRect,aSiz); + MoveRect(maSnapRect,aSiz); + SetXPolyDirty(); + SetRectsDirty(sal_True); +} + +void SdrCircObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + long nWink0=aGeo.nDrehWink; + FASTBOOL bNoShearRota=(aGeo.nDrehWink==0 && aGeo.nShearWink==0); + SdrTextObj::NbcResize(rRef,xFact,yFact); + bNoShearRota|=(aGeo.nDrehWink==0 && aGeo.nShearWink==0); + if (meCircleKind!=OBJ_CIRC) { + FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0); + FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0); + if (bXMirr || bYMirr) { + // bei bXMirr!=bYMirr muessten eigentlich noch die beiden + // Linienende vertauscht werden. Das ist jedoch mal wieder + // schlecht (wg. zwangslaeufiger harter Formatierung). + // Alternativ koennte ein bMirrored-Flag eingefuehrt werden + // (Vielleicht ja mal grundsaetzlich, auch fuer gepiegelten Text, ...). + long nS0=nStartWink; + long nE0=nEndWink; + if (bNoShearRota) { + // Das RectObj spiegelt bei VMirror bereits durch durch 180deg Drehung. + if (! (bXMirr && bYMirr)) { + long nTmp=nS0; + nS0=18000-nE0; + nE0=18000-nTmp; + } + } else { // Spiegeln fuer verzerrte Ellipsen + if (bXMirr!=bYMirr) { + nS0+=nWink0; + nE0+=nWink0; + if (bXMirr) { + long nTmp=nS0; + nS0=18000-nE0; + nE0=18000-nTmp; + } + if (bYMirr) { + long nTmp=nS0; + nS0=-nE0; + nE0=-nTmp; + } + nS0-=aGeo.nDrehWink; + nE0-=aGeo.nDrehWink; + } + } + long nWinkDif=nE0-nS0; + nStartWink=NormAngle360(nS0); + nEndWink =NormAngle360(nE0); + if (nWinkDif==36000) nEndWink+=nWinkDif; // Vollkreis + } + } + SetXPolyDirty(); + ImpSetCircInfoToAttr(); +} + +void SdrCircObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + SdrTextObj::NbcShear(rRef,nWink,tn,bVShear); + SetXPolyDirty(); + ImpSetCircInfoToAttr(); +} + +void SdrCircObj::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + //long nWink0=aGeo.nDrehWink; + FASTBOOL bFreeMirr=meCircleKind!=OBJ_CIRC; + Point aTmpPt1; + Point aTmpPt2; + if (bFreeMirr) { // bei freier Spiegelachse einige Vorbereitungen Treffen + Point aCenter(aRect.Center()); + long nWdt=aRect.GetWidth()-1; + long nHgt=aRect.GetHeight()-1; + long nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2; + double a; + // Startpunkt + a=nStartWink*nPi180; + aTmpPt1=Point(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad)); + if (nWdt==0) aTmpPt1.X()=0; + if (nHgt==0) aTmpPt1.Y()=0; + aTmpPt1+=aCenter; + // Endpunkt + a=nEndWink*nPi180; + aTmpPt2=Point(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad)); + if (nWdt==0) aTmpPt2.X()=0; + if (nHgt==0) aTmpPt2.Y()=0; + aTmpPt2+=aCenter; + if (aGeo.nDrehWink!=0) { + RotatePoint(aTmpPt1,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + RotatePoint(aTmpPt2,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + } + if (aGeo.nShearWink!=0) { + ShearPoint(aTmpPt1,aRect.TopLeft(),aGeo.nTan); + ShearPoint(aTmpPt2,aRect.TopLeft(),aGeo.nTan); + } + } + SdrTextObj::NbcMirror(rRef1,rRef2); + if (meCircleKind!=OBJ_CIRC) { // Anpassung von Start- und Endwinkel + MirrorPoint(aTmpPt1,rRef1,rRef2); + MirrorPoint(aTmpPt2,rRef1,rRef2); + // Unrotate: + if (aGeo.nDrehWink!=0) { + RotatePoint(aTmpPt1,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin fuer Umkehrung + RotatePoint(aTmpPt2,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin fuer Umkehrung + } + // Unshear: + if (aGeo.nShearWink!=0) { + ShearPoint(aTmpPt1,aRect.TopLeft(),-aGeo.nTan); // -tan fuer Umkehrung + ShearPoint(aTmpPt2,aRect.TopLeft(),-aGeo.nTan); // -tan fuer Umkehrung + } + Point aCenter(aRect.Center()); + aTmpPt1-=aCenter; + aTmpPt2-=aCenter; + // Weil gespiegelt sind die Winkel nun auch noch vertauscht + nStartWink=GetAngle(aTmpPt2); + nEndWink =GetAngle(aTmpPt1); + long nWinkDif=nEndWink-nStartWink; + nStartWink=NormAngle360(nStartWink); + nEndWink =NormAngle360(nEndWink); + if (nWinkDif==36000) nEndWink+=nWinkDif; // Vollkreis + } + SetXPolyDirty(); + ImpSetCircInfoToAttr(); +} + +SdrObjGeoData* SdrCircObj::NewGeoData() const +{ + return new SdrCircObjGeoData; +} + +void SdrCircObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrRectObj::SaveGeoData(rGeo); + SdrCircObjGeoData& rCGeo=(SdrCircObjGeoData&)rGeo; + rCGeo.nStartWink=nStartWink; + rCGeo.nEndWink =nEndWink; +} + +void SdrCircObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrRectObj::RestGeoData(rGeo); + SdrCircObjGeoData& rCGeo=(SdrCircObjGeoData&)rGeo; + nStartWink=rCGeo.nStartWink; + nEndWink =rCGeo.nEndWink; + SetXPolyDirty(); + ImpSetCircInfoToAttr(); +} + +void Union(Rectangle& rR, const Point& rP) +{ + if (rP.X()<rR.Left ()) rR.Left ()=rP.X(); + if (rP.X()>rR.Right ()) rR.Right ()=rP.X(); + if (rP.Y()<rR.Top ()) rR.Top ()=rP.Y(); + if (rP.Y()>rR.Bottom()) rR.Bottom()=rP.Y(); +} + +void SdrCircObj::TakeUnrotatedSnapRect(Rectangle& rRect) const +{ + rRect=aRect; + if (meCircleKind!=OBJ_CIRC) { + const Point aPntStart(GetWinkPnt(aRect,nStartWink)); + const Point aPntEnd(GetWinkPnt(aRect,nEndWink)); + long a=nStartWink; + long e=nEndWink; + rRect.Left ()=aRect.Right(); + rRect.Right ()=aRect.Left(); + rRect.Top ()=aRect.Bottom(); + rRect.Bottom()=aRect.Top(); + Union(rRect,aPntStart); + Union(rRect,aPntEnd); + if ((a<=18000 && e>=18000) || (a>e && (a<=18000 || e>=18000))) { + Union(rRect,aRect.LeftCenter()); + } + if ((a<=27000 && e>=27000) || (a>e && (a<=27000 || e>=27000))) { + Union(rRect,aRect.BottomCenter()); + } + if (a>e) { + Union(rRect,aRect.RightCenter()); + } + if ((a<=9000 && e>=9000) || (a>e && (a<=9000 || e>=9000))) { + Union(rRect,aRect.TopCenter()); + } + if (meCircleKind==OBJ_SECT) { + Union(rRect,aRect.Center()); + } + if (aGeo.nDrehWink!=0) { + Point aDst(rRect.TopLeft()); + aDst-=aRect.TopLeft(); + Point aDst0(aDst); + RotatePoint(aDst,Point(),aGeo.nSin,aGeo.nCos); + aDst-=aDst0; + rRect.Move(aDst.X(),aDst.Y()); + } + } + if (aGeo.nShearWink!=0) { + long nDst=Round((rRect.Bottom()-rRect.Top())*aGeo.nTan); + if (aGeo.nShearWink>0) { + Point aRef(rRect.TopLeft()); + rRect.Left()-=nDst; + Point aTmpPt(rRect.TopLeft()); + RotatePoint(aTmpPt,aRef,aGeo.nSin,aGeo.nCos); + aTmpPt-=rRect.TopLeft(); + rRect.Move(aTmpPt.X(),aTmpPt.Y()); + } else { + rRect.Right()-=nDst; + } + } +} + +void SdrCircObj::RecalcSnapRect() +{ + if (PaintNeedsXPolyCirc()) { + maSnapRect=GetXPoly().GetBoundRect(); + } else { + TakeUnrotatedSnapRect(maSnapRect); + } +} + +void SdrCircObj::NbcSetSnapRect(const Rectangle& rRect) +{ + if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || meCircleKind!=OBJ_CIRC) { + Rectangle aSR0(GetSnapRect()); + long nWdt0=aSR0.Right()-aSR0.Left(); + long nHgt0=aSR0.Bottom()-aSR0.Top(); + long nWdt1=rRect.Right()-rRect.Left(); + long nHgt1=rRect.Bottom()-rRect.Top(); + NbcResize(maSnapRect.TopLeft(),Fraction(nWdt1,nWdt0),Fraction(nHgt1,nHgt0)); + NbcMove(Size(rRect.Left()-aSR0.Left(),rRect.Top()-aSR0.Top())); + } else { + aRect=rRect; + ImpJustifyRect(aRect); + } + SetRectsDirty(); + SetXPolyDirty(); + ImpSetCircInfoToAttr(); +} + +sal_uInt32 SdrCircObj::GetSnapPointCount() const +{ + if (meCircleKind==OBJ_CIRC) { + return 1L; + } else { + return 3L; + } +} + +Point SdrCircObj::GetSnapPoint(sal_uInt32 i) const +{ + switch (i) { + case 1 : return GetWinkPnt(aRect,nStartWink); + case 2 : return GetWinkPnt(aRect,nEndWink); + default: return aRect.Center(); + } +} + +void __EXPORT SdrCircObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + SetXPolyDirty(); + SdrRectObj::Notify(rBC,rHint); + ImpSetAttrToCircInfo(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrCircObj::ImpSetAttrToCircInfo() +{ + const SfxItemSet& rSet = GetObjectItemSet(); + SdrCircKind eNewKindA = ((SdrCircKindItem&)rSet.Get(SDRATTR_CIRCKIND)).GetValue(); + SdrObjKind eNewKind = meCircleKind; + + if(eNewKindA == SDRCIRC_FULL) + eNewKind = OBJ_CIRC; + else if(eNewKindA == SDRCIRC_SECT) + eNewKind = OBJ_SECT; + else if(eNewKindA == SDRCIRC_ARC) + eNewKind = OBJ_CARC; + else if(eNewKindA == SDRCIRC_CUT) + eNewKind = OBJ_CCUT; + + sal_Int32 nNewStart = ((SdrCircStartAngleItem&)rSet.Get(SDRATTR_CIRCSTARTANGLE)).GetValue(); + sal_Int32 nNewEnd = ((SdrCircEndAngleItem&)rSet.Get(SDRATTR_CIRCENDANGLE)).GetValue(); + + BOOL bKindChg = meCircleKind != eNewKind; + BOOL bWinkChg = nNewStart != nStartWink || nNewEnd != nEndWink; + + if(bKindChg || bWinkChg) + { + meCircleKind = eNewKind; + nStartWink = nNewStart; + nEndWink = nNewEnd; + + if(bKindChg || (meCircleKind != OBJ_CIRC && bWinkChg)) + { + SetXPolyDirty(); + SetRectsDirty(); + } + } +} + +void SdrCircObj::ImpSetCircInfoToAttr() +{ + SdrCircKind eNewKindA = SDRCIRC_FULL; + const SfxItemSet& rSet = GetObjectItemSet(); + + if(meCircleKind == OBJ_SECT) + eNewKindA = SDRCIRC_SECT; + else if(meCircleKind == OBJ_CARC) + eNewKindA = SDRCIRC_ARC; + else if(meCircleKind == OBJ_CCUT) + eNewKindA = SDRCIRC_CUT; + + SdrCircKind eOldKindA = ((SdrCircKindItem&)rSet.Get(SDRATTR_CIRCKIND)).GetValue(); + sal_Int32 nOldStartWink = ((SdrCircStartAngleItem&)rSet.Get(SDRATTR_CIRCSTARTANGLE)).GetValue(); + sal_Int32 nOldEndWink = ((SdrCircEndAngleItem&)rSet.Get(SDRATTR_CIRCENDANGLE)).GetValue(); + + if(eNewKindA != eOldKindA || nStartWink != nOldStartWink || nEndWink != nOldEndWink) + { + // #81921# since SetItem() implicitly calls ImpSetAttrToCircInfo() + // setting the item directly is necessary here. + if(eNewKindA != eOldKindA) + { + GetProperties().SetObjectItemDirect(SdrCircKindItem(eNewKindA)); + } + + if(nStartWink != nOldStartWink) + { + GetProperties().SetObjectItemDirect(SdrCircStartAngleItem(nStartWink)); + } + + if(nEndWink != nOldEndWink) + { + GetProperties().SetObjectItemDirect(SdrCircEndAngleItem(nEndWink)); + } + + SetXPolyDirty(); + ImpSetAttrToCircInfo(); + } +} + +SdrObject* SdrCircObj::DoConvertToPolyObj(BOOL bBezier) const +{ + const sal_Bool bFill(OBJ_CARC == meCircleKind ? sal_False : sal_True); + const basegfx::B2DPolygon aCircPolygon(ImpCalcXPolyCirc(meCircleKind, aRect, nStartWink, nEndWink)); + SdrObject* pRet = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aCircPolygon), bFill, bBezier); + pRet = ImpConvertAddText(pRet, bBezier); + + return pRet; +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdoedge.cxx b/svx/source/svdraw/svdoedge.cxx new file mode 100644 index 000000000000..3d254aeb39c4 --- /dev/null +++ b/svx/source/svdraw/svdoedge.cxx @@ -0,0 +1,2497 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdoedge.hxx> +#include <svx/xpool.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdattrx.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdview.hxx> +#include <svx/svddrag.hxx> +#include <svx/svddrgv.hxx> +#include "svddrgm1.hxx" +#include <svx/svdhdl.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname +#include <svl/style.hxx> +#include <svl/smplhint.hxx> +#include <editeng/eeitem.hxx> +#include "svdoimp.hxx" +#include <svx/sdr/properties/connectorproperties.hxx> +#include <svx/sdr/contact/viewcontactofsdredgeobj.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <svx/sdrhittesthelper.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObjConnection::~SdrObjConnection() +{ +} + +void SdrObjConnection::ResetVars() +{ + pObj=NULL; + nConId=0; + nXDist=0; + nYDist=0; + bBestConn=TRUE; + bBestVertex=TRUE; + bXDistOvr=FALSE; + bYDistOvr=FALSE; + bAutoVertex=FALSE; + bAutoCorner=FALSE; +} + +FASTBOOL SdrObjConnection::TakeGluePoint(SdrGluePoint& rGP, FASTBOOL bSetAbsPos) const +{ + FASTBOOL bRet=FALSE; + if (pObj!=NULL) { // Ein Obj muss schon angedockt sein! + if (bAutoVertex) { + rGP=pObj->GetVertexGluePoint(nConId); + bRet=TRUE; + } else if (bAutoCorner) { + rGP=pObj->GetCornerGluePoint(nConId); + bRet=TRUE; + } else { + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + if (pGPL!=NULL) { + USHORT nNum=pGPL->FindGluePoint(nConId); + if (nNum!=SDRGLUEPOINT_NOTFOUND) { + rGP=(*pGPL)[nNum]; + bRet=TRUE; + } + } + } + } + if (bRet && bSetAbsPos) { + Point aPt(rGP.GetAbsolutePos(*pObj)); + aPt+=aObjOfs; + rGP.SetPos(aPt); + } + return bRet; +} + +Point& SdrEdgeInfoRec::ImpGetLineVersatzPoint(SdrEdgeLineCode eLineCode) +{ + switch (eLineCode) { + case OBJ1LINE2 : return aObj1Line2; + case OBJ1LINE3 : return aObj1Line3; + case OBJ2LINE2 : return aObj2Line2; + case OBJ2LINE3 : return aObj2Line3; + case MIDDLELINE: return aMiddleLine; + } // switch + return aMiddleLine; +} + +USHORT SdrEdgeInfoRec::ImpGetPolyIdx(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const +{ + switch (eLineCode) { + case OBJ1LINE2 : return 1; + case OBJ1LINE3 : return 2; + case OBJ2LINE2 : return rXP.GetPointCount()-3; + case OBJ2LINE3 : return rXP.GetPointCount()-4; + case MIDDLELINE: return nMiddleLine; + } // switch + return 0; +} + +FASTBOOL SdrEdgeInfoRec::ImpIsHorzLine(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const +{ + USHORT nIdx=ImpGetPolyIdx(eLineCode,rXP); + FASTBOOL bHorz=nAngle1==0 || nAngle1==18000; + if (eLineCode==OBJ2LINE2 || eLineCode==OBJ2LINE3) { + nIdx=rXP.GetPointCount()-nIdx; // #36314# + bHorz=nAngle2==0 || nAngle2==18000; // #52000# + } + if ((nIdx & 1)==1) bHorz=!bHorz; + return bHorz; +} + +void SdrEdgeInfoRec::ImpSetLineVersatz(SdrEdgeLineCode eLineCode, const XPolygon& rXP, long nVal) +{ + Point& rPt=ImpGetLineVersatzPoint(eLineCode); + if (ImpIsHorzLine(eLineCode,rXP)) rPt.Y()=nVal; + else rPt.X()=nVal; +} + +long SdrEdgeInfoRec::ImpGetLineVersatz(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const +{ + const Point& rPt=ImpGetLineVersatzPoint(eLineCode); + if (ImpIsHorzLine(eLineCode,rXP)) return rPt.Y(); + else return rPt.X(); +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrEdgeObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::ConnectorProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrEdgeObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrEdgeObj(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrEdgeObj,SdrTextObj); + +SdrEdgeObj::SdrEdgeObj() +: SdrTextObj(), + nNotifyingCount(0), + bEdgeTrackDirty(sal_False), + bEdgeTrackUserDefined(sal_False), + // #109007# Default is to allow default connects + mbSuppressDefaultConnect(sal_False), + // #110649# + mbBoundRectCalculationRunning(sal_False) +{ + bClosedObj=FALSE; + bIsEdge=TRUE; + pEdgeTrack=new XPolygon; + +} + +SdrEdgeObj::~SdrEdgeObj() +{ + DisconnectFromNode(TRUE); + DisconnectFromNode(FALSE); + delete pEdgeTrack; +} + +void SdrEdgeObj::ImpSetAttrToEdgeInfo() +{ + const SfxItemSet& rSet = GetObjectItemSet(); + SdrEdgeKind eKind = ((SdrEdgeKindItem&)(rSet.Get(SDRATTR_EDGEKIND))).GetValue(); + sal_Int32 nVal1 = ((SdrEdgeLine1DeltaItem&)rSet.Get(SDRATTR_EDGELINE1DELTA)).GetValue(); + sal_Int32 nVal2 = ((SdrEdgeLine2DeltaItem&)rSet.Get(SDRATTR_EDGELINE2DELTA)).GetValue(); + sal_Int32 nVal3 = ((SdrEdgeLine3DeltaItem&)rSet.Get(SDRATTR_EDGELINE3DELTA)).GetValue(); + + if(eKind == SDREDGE_ORTHOLINES || eKind == SDREDGE_BEZIER) + { + sal_Int32 nVals[3] = { nVal1, nVal2, nVal3 }; + sal_uInt16 n = 0; + + if(aEdgeInfo.nObj1Lines >= 2 && n < 3) + { + aEdgeInfo.ImpSetLineVersatz(OBJ1LINE2, *pEdgeTrack, nVals[n]); + n++; + } + + if(aEdgeInfo.nObj1Lines >= 3 && n < 3) + { + aEdgeInfo.ImpSetLineVersatz(OBJ1LINE3, *pEdgeTrack, nVals[n]); + n++; + } + + if(aEdgeInfo.nMiddleLine != 0xFFFF && n < 3) + { + aEdgeInfo.ImpSetLineVersatz(MIDDLELINE, *pEdgeTrack, nVals[n]); + n++; + } + + if(aEdgeInfo.nObj2Lines >= 3 && n < 3) + { + aEdgeInfo.ImpSetLineVersatz(OBJ2LINE3, *pEdgeTrack, nVals[n]); + n++; + } + + if(aEdgeInfo.nObj2Lines >= 2 && n < 3) + { + aEdgeInfo.ImpSetLineVersatz(OBJ2LINE2, *pEdgeTrack, nVals[n]); + n++; + } + } + else if(eKind == SDREDGE_THREELINES) + { + BOOL bHor1 = aEdgeInfo.nAngle1 == 0 || aEdgeInfo.nAngle1 == 18000; + BOOL bHor2 = aEdgeInfo.nAngle2 == 0 || aEdgeInfo.nAngle2 == 18000; + + if(bHor1) + { + aEdgeInfo.aObj1Line2.X() = nVal1; + } + else + { + aEdgeInfo.aObj1Line2.Y() = nVal1; + } + + if(bHor2) + { + aEdgeInfo.aObj2Line2.X() = nVal2; + } + else + { + aEdgeInfo.aObj2Line2.Y() = nVal2; + } + } + + // #84649# + ImpDirtyEdgeTrack(); +} + +void SdrEdgeObj::ImpSetEdgeInfoToAttr() +{ + const SfxItemSet& rSet = GetObjectItemSet(); + SdrEdgeKind eKind = ((SdrEdgeKindItem&)(rSet.Get(SDRATTR_EDGEKIND))).GetValue(); + sal_Int32 nValAnz = ((SdrEdgeLineDeltaAnzItem&)rSet.Get(SDRATTR_EDGELINEDELTAANZ)).GetValue(); + sal_Int32 nVal1 = ((SdrEdgeLine1DeltaItem&)rSet.Get(SDRATTR_EDGELINE1DELTA)).GetValue(); + sal_Int32 nVal2 = ((SdrEdgeLine2DeltaItem&)rSet.Get(SDRATTR_EDGELINE2DELTA)).GetValue(); + sal_Int32 nVal3 = ((SdrEdgeLine3DeltaItem&)rSet.Get(SDRATTR_EDGELINE3DELTA)).GetValue(); + sal_Int32 nVals[3] = { nVal1, nVal2, nVal3 }; + sal_uInt16 n = 0; + + if(eKind == SDREDGE_ORTHOLINES || eKind == SDREDGE_BEZIER) + { + if(aEdgeInfo.nObj1Lines >= 2 && n < 3) + { + nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ1LINE2, *pEdgeTrack); + n++; + } + + if(aEdgeInfo.nObj1Lines >= 3 && n < 3) + { + nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ1LINE3, *pEdgeTrack); + n++; + } + + if(aEdgeInfo.nMiddleLine != 0xFFFF && n < 3) + { + nVals[n] = aEdgeInfo.ImpGetLineVersatz(MIDDLELINE, *pEdgeTrack); + n++; + } + + if(aEdgeInfo.nObj2Lines >= 3 && n < 3) + { + nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ2LINE3, *pEdgeTrack); + n++; + } + + if(aEdgeInfo.nObj2Lines >= 2 && n < 3) + { + nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ2LINE2, *pEdgeTrack); + n++; + } + } + else if(eKind == SDREDGE_THREELINES) + { + BOOL bHor1 = aEdgeInfo.nAngle1 == 0 || aEdgeInfo.nAngle1 == 18000; + BOOL bHor2 = aEdgeInfo.nAngle2 == 0 || aEdgeInfo.nAngle2 == 18000; + + n = 2; + nVals[0] = bHor1 ? aEdgeInfo.aObj1Line2.X() : aEdgeInfo.aObj1Line2.Y(); + nVals[1] = bHor2 ? aEdgeInfo.aObj2Line2.X() : aEdgeInfo.aObj2Line2.Y(); + } + + if(n != nValAnz || nVals[0] != nVal1 || nVals[1] != nVal2 || nVals[2] != nVal3) + { + // #75371# Here no more notifying is necessary, just local changes are OK. + if(n != nValAnz) + { + GetProperties().SetObjectItemDirect(SdrEdgeLineDeltaAnzItem(n)); + } + + if(nVals[0] != nVal1) + { + GetProperties().SetObjectItemDirect(SdrEdgeLine1DeltaItem(nVals[0])); + } + + if(nVals[1] != nVal2) + { + GetProperties().SetObjectItemDirect(SdrEdgeLine2DeltaItem(nVals[1])); + } + + if(nVals[2] != nVal3) + { + GetProperties().SetObjectItemDirect(SdrEdgeLine3DeltaItem(nVals[2])); + } + + if(n < 3) + { + GetProperties().ClearObjectItemDirect(SDRATTR_EDGELINE3DELTA); + } + + if(n < 2) + { + GetProperties().ClearObjectItemDirect(SDRATTR_EDGELINE2DELTA); + } + + if(n < 1) + { + GetProperties().ClearObjectItemDirect(SDRATTR_EDGELINE1DELTA); + } + } +} + +void SdrEdgeObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bRotateFreeAllowed=FALSE; + rInfo.bRotate90Allowed =FALSE; + rInfo.bMirrorFreeAllowed=FALSE; + rInfo.bMirror45Allowed =FALSE; + rInfo.bMirror90Allowed =FALSE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =FALSE; + rInfo.bEdgeRadiusAllowed=FALSE; + FASTBOOL bCanConv=!HasText() || ImpCanConvTextToCurve(); + rInfo.bCanConvToPath=bCanConv; + rInfo.bCanConvToPoly=bCanConv; + rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +UINT16 SdrEdgeObj::GetObjIdentifier() const +{ + return UINT16(OBJ_EDGE); +} + +const Rectangle& SdrEdgeObj::GetCurrentBoundRect() const +{ + if(bEdgeTrackDirty) + { + ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack(); + } + + return SdrTextObj::GetCurrentBoundRect(); +} + +const Rectangle& SdrEdgeObj::GetSnapRect() const +{ + if(bEdgeTrackDirty) + { + ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack(); + } + + return SdrTextObj::GetSnapRect(); +} + +void SdrEdgeObj::RecalcSnapRect() +{ + maSnapRect=pEdgeTrack->GetBoundRect(); +} + +void SdrEdgeObj::TakeUnrotatedSnapRect(Rectangle& rRect) const +{ + rRect=GetSnapRect(); +} + +FASTBOOL SdrEdgeObj::IsNode() const +{ + return TRUE; +} + +SdrGluePoint SdrEdgeObj::GetVertexGluePoint(USHORT nNum) const +{ + Point aPt; + USHORT nPntAnz=pEdgeTrack->GetPointCount(); + if (nPntAnz>0) + { + Point aOfs = GetSnapRect().Center(); + if (nNum==2 && GetConnectedNode(TRUE)==NULL) aPt=(*pEdgeTrack)[0]; + else if (nNum==3 && GetConnectedNode(FALSE)==NULL) aPt=(*pEdgeTrack)[nPntAnz-1]; + else { + if ((nPntAnz & 1) ==1) { + aPt=(*pEdgeTrack)[nPntAnz/2]; + } else { + Point aPt1((*pEdgeTrack)[nPntAnz/2-1]); + Point aPt2((*pEdgeTrack)[nPntAnz/2]); + aPt1+=aPt2; + aPt1.X()/=2; + aPt1.Y()/=2; + aPt=aPt1; + } + } + aPt-=aOfs; + } + SdrGluePoint aGP(aPt); + aGP.SetPercent(FALSE); + return aGP; +} + +SdrGluePoint SdrEdgeObj::GetCornerGluePoint(USHORT nNum) const +{ + return GetVertexGluePoint(nNum); +} + +const SdrGluePointList* SdrEdgeObj::GetGluePointList() const +{ + return NULL; // Keine benutzerdefinierten Klebepunkte fuer Verbinder #31671# +} + +SdrGluePointList* SdrEdgeObj::ForceGluePointList() +{ + return NULL; // Keine benutzerdefinierten Klebepunkte fuer Verbinder #31671# +} + +FASTBOOL SdrEdgeObj::IsEdge() const +{ + return TRUE; +} + +void SdrEdgeObj::ConnectToNode(FASTBOOL bTail1, SdrObject* pObj) +{ + SdrObjConnection& rCon=GetConnection(bTail1); + DisconnectFromNode(bTail1); + if (pObj!=NULL) { + pObj->AddListener(*this); + rCon.pObj=pObj; + ImpDirtyEdgeTrack(); + } +} + +void SdrEdgeObj::DisconnectFromNode(FASTBOOL bTail1) +{ + SdrObjConnection& rCon=GetConnection(bTail1); + if (rCon.pObj!=NULL) { + rCon.pObj->RemoveListener(*this); + rCon.pObj=NULL; + } +} + +SdrObject* SdrEdgeObj::GetConnectedNode(FASTBOOL bTail1) const +{ + SdrObject* pObj=GetConnection(bTail1).pObj; + if (pObj!=NULL && (pObj->GetPage()!=pPage || !pObj->IsInserted())) pObj=NULL; + return pObj; +} + +FASTBOOL SdrEdgeObj::CheckNodeConnection(FASTBOOL bTail1) const +{ + FASTBOOL bRet=FALSE; + const SdrObjConnection& rCon=GetConnection(bTail1); + USHORT nPtAnz=pEdgeTrack->GetPointCount(); + if (rCon.pObj!=NULL && rCon.pObj->GetPage()==pPage && nPtAnz!=0) { + const SdrGluePointList* pGPL=rCon.pObj->GetGluePointList(); + USHORT nConAnz=pGPL==NULL ? 0 : pGPL->GetCount(); + USHORT nGesAnz=nConAnz+8; + Point aTail(bTail1 ? (*pEdgeTrack)[0] : (*pEdgeTrack)[USHORT(nPtAnz-1)]); + for (USHORT i=0; i<nGesAnz && !bRet; i++) { + if (i<nConAnz) { // UserDefined + bRet=aTail==(*pGPL)[i].GetAbsolutePos(*rCon.pObj); + } else if (i<nConAnz+4) { // Vertex + SdrGluePoint aPt(rCon.pObj->GetVertexGluePoint(i-nConAnz)); + bRet=aTail==aPt.GetAbsolutePos(*rCon.pObj); + } else { // Corner + SdrGluePoint aPt(rCon.pObj->GetCornerGluePoint(i-nConAnz-4)); + bRet=aTail==aPt.GetAbsolutePos(*rCon.pObj); + } + } + } + return bRet; +} + +void SdrEdgeObj::ImpSetTailPoint(FASTBOOL bTail1, const Point& rPt) +{ + USHORT nPtAnz=pEdgeTrack->GetPointCount(); + if (nPtAnz==0) { + (*pEdgeTrack)[0]=rPt; + (*pEdgeTrack)[1]=rPt; + } else if (nPtAnz==1) { + if (!bTail1) (*pEdgeTrack)[1]=rPt; + else { (*pEdgeTrack)[1]=(*pEdgeTrack)[0]; (*pEdgeTrack)[0]=rPt; } + } else { + if (!bTail1) (*pEdgeTrack)[USHORT(nPtAnz-1)]=rPt; + else (*pEdgeTrack)[0]=rPt; + } + ImpRecalcEdgeTrack(); + SetRectsDirty(); +} + +void SdrEdgeObj::ImpDirtyEdgeTrack() +{ + if ( !bEdgeTrackUserDefined || !(GetModel() && GetModel()->isLocked()) ) + bEdgeTrackDirty = sal_True; +} + +void SdrEdgeObj::ImpUndirtyEdgeTrack() +{ + if (bEdgeTrackDirty && (GetModel() && GetModel()->isLocked()) ) { + ImpRecalcEdgeTrack(); + } +} + +void SdrEdgeObj::ImpRecalcEdgeTrack() +{ + if ( bEdgeTrackUserDefined && (GetModel() && GetModel()->isLocked()) ) + return; + + // #110649# + if(IsBoundRectCalculationRunning()) + { + // this object is involved into another ImpRecalcEdgeTrack() call + // from another SdrEdgeObj. Do not calculate again to avoid loop. + // Also, do not change bEdgeTrackDirty so that it gets recalculated + // later at the first non-looping call. + } + // #i43068# + else if(GetModel() && GetModel()->isLocked()) + { + // avoid re-layout during imports/API call sequences + // #i45294# but calc EdgeTrack and secure properties there + ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_True; + *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo); + ImpSetAttrToEdgeInfo(); + bEdgeTrackDirty=sal_False; + ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_False; + } + else + { + // To not run in a depth loop, use a coloring algorythm on + // SdrEdgeObj BoundRect calculations + ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_True; + + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + SetRectsDirty(); + // #110094#-14 if (!bEdgeTrackDirty) SendRepaintBroadcast(); + *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo); + ImpSetEdgeInfoToAttr(); // Die Werte aus aEdgeInfo in den Pool kopieren + bEdgeTrackDirty=sal_False; + + // Only redraw here, no object change + ActionChanged(); + // BroadcastObjectChange(); + + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + + // #110649# + ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_False; + } +} + +USHORT SdrEdgeObj::ImpCalcEscAngle(SdrObject* pObj, const Point& rPt) const +{ + if (pObj==NULL) return SDRESC_ALL; + Rectangle aR(pObj->GetSnapRect()); + long dxl=rPt.X()-aR.Left(); + long dyo=rPt.Y()-aR.Top(); + long dxr=aR.Right()-rPt.X(); + long dyu=aR.Bottom()-rPt.Y(); + FASTBOOL bxMitt=Abs(dxl-dxr)<2; + FASTBOOL byMitt=Abs(dyo-dyu)<2; + long dx=Min(dxl,dxr); + long dy=Min(dyo,dyu); + FASTBOOL bDiag=Abs(dx-dy)<2; + if (bxMitt && byMitt) return SDRESC_ALL; // In der Mitte + if (bDiag) { // diagonal + USHORT nRet=0; + if (byMitt) nRet|=SDRESC_VERT; + if (bxMitt) nRet|=SDRESC_HORZ; + if (dxl<dxr) { // Links + if (dyo<dyu) nRet|=SDRESC_LEFT | SDRESC_TOP; + else nRet|=SDRESC_LEFT | SDRESC_BOTTOM; + } else { // Rechts + if (dyo<dyu) nRet|=SDRESC_RIGHT | SDRESC_TOP; + else nRet|=SDRESC_RIGHT | SDRESC_BOTTOM; + } + return nRet; + } + if (dx<dy) { // waagerecht + if (bxMitt) return SDRESC_HORZ; + if (dxl<dxr) return SDRESC_LEFT; + else return SDRESC_RIGHT; + } else { // senkrecht + if (byMitt) return SDRESC_VERT; + if (dyo<dyu) return SDRESC_TOP; + else return SDRESC_BOTTOM; + } +} + +FASTBOOL SdrEdgeObj::ImpStripPolyPoints(XPolygon& /*rXP*/) const +{ + // fehlende Implementation !!! + return FALSE; +} + +XPolygon SdrEdgeObj::ImpCalcObjToCenter(const Point& rStPt, long nEscAngle, const Rectangle& rRect, const Point& rMeeting) const +{ + XPolygon aXP; + aXP.Insert(XPOLY_APPEND,rStPt,XPOLY_NORMAL); + FASTBOOL bRts=nEscAngle==0; + FASTBOOL bObn=nEscAngle==9000; + FASTBOOL bLks=nEscAngle==18000; + FASTBOOL bUnt=nEscAngle==27000; + + Point aP1(rStPt); // erstmal den Pflichtabstand + if (bLks) aP1.X()=rRect.Left(); + if (bRts) aP1.X()=rRect.Right(); + if (bObn) aP1.Y()=rRect.Top(); + if (bUnt) aP1.Y()=rRect.Bottom(); + + FASTBOOL bFinish=FALSE; + if (!bFinish) { + Point aP2(aP1); // Und nun den Pflichtabstand ggf. bis auf Meetinghoehe erweitern + if (bLks && rMeeting.X()<=aP2.X()) aP2.X()=rMeeting.X(); + if (bRts && rMeeting.X()>=aP2.X()) aP2.X()=rMeeting.X(); + if (bObn && rMeeting.Y()<=aP2.Y()) aP2.Y()=rMeeting.Y(); + if (bUnt && rMeeting.Y()>=aP2.Y()) aP2.Y()=rMeeting.Y(); + aXP.Insert(XPOLY_APPEND,aP2,XPOLY_NORMAL); + + Point aP3(aP2); + if ((bLks && rMeeting.X()>aP2.X()) || (bRts && rMeeting.X()<aP2.X())) { // Aussenrum + if (rMeeting.Y()<aP2.Y()) { + aP3.Y()=rRect.Top(); + if (rMeeting.Y()<aP3.Y()) aP3.Y()=rMeeting.Y(); + } else { + aP3.Y()=rRect.Bottom(); + if (rMeeting.Y()>aP3.Y()) aP3.Y()=rMeeting.Y(); + } + aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL); + if (aP3.Y()!=rMeeting.Y()) { + aP3.X()=rMeeting.X(); + aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL); + } + } + if ((bObn && rMeeting.Y()>aP2.Y()) || (bUnt && rMeeting.Y()<aP2.Y())) { // Aussenrum + if (rMeeting.X()<aP2.X()) { + aP3.X()=rRect.Left(); + if (rMeeting.X()<aP3.X()) aP3.X()=rMeeting.X(); + } else { + aP3.X()=rRect.Right(); + if (rMeeting.X()>aP3.X()) aP3.X()=rMeeting.X(); + } + aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL); + if (aP3.X()!=rMeeting.X()) { + aP3.Y()=rMeeting.Y(); + aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL); + } + } + } +#ifdef DBG_UTIL + if (aXP.GetPointCount()>4) { + DBG_ERROR("SdrEdgeObj::ImpCalcObjToCenter(): Polygon hat mehr als 4 Punkte!"); + } +#endif + return aXP; +} + +XPolygon SdrEdgeObj::ImpCalcEdgeTrack(const XPolygon& rTrack0, SdrObjConnection& rCon1, SdrObjConnection& rCon2, SdrEdgeInfoRec* pInfo) const +{ + Point aPt1,aPt2; + SdrGluePoint aGP1,aGP2; + USHORT nEsc1=SDRESC_ALL,nEsc2=SDRESC_ALL; + Rectangle aBoundRect1; + Rectangle aBoundRect2; + Rectangle aBewareRect1; + Rectangle aBewareRect2; + // Erstmal die alten Endpunkte wiederholen + if (rTrack0.GetPointCount()!=0) { + aPt1=rTrack0[0]; + USHORT nSiz=rTrack0.GetPointCount(); + nSiz--; + aPt2=rTrack0[nSiz]; + } else { + if (!aOutRect.IsEmpty()) { + aPt1=aOutRect.TopLeft(); + aPt2=aOutRect.BottomRight(); + } + } + FASTBOOL bCon1=rCon1.pObj!=NULL && rCon1.pObj->GetPage()==pPage && rCon1.pObj->IsInserted(); + FASTBOOL bCon2=rCon2.pObj!=NULL && rCon2.pObj->GetPage()==pPage && rCon2.pObj->IsInserted(); + const SfxItemSet& rSet = GetObjectItemSet(); + + if (bCon1) { + if (rCon1.pObj==(SdrObject*)this) + { + // sicherheitshalber Abfragen #44515# + aBoundRect1=aOutRect; + } + else + { + aBoundRect1 = rCon1.pObj->GetCurrentBoundRect(); + } + aBoundRect1.Move(rCon1.aObjOfs.X(),rCon1.aObjOfs.Y()); + aBewareRect1=aBoundRect1; + + sal_Int32 nH = ((SdrEdgeNode1HorzDistItem&)rSet.Get(SDRATTR_EDGENODE1HORZDIST)).GetValue(); + sal_Int32 nV = ((SdrEdgeNode1VertDistItem&)rSet.Get(SDRATTR_EDGENODE1VERTDIST)).GetValue(); + + aBewareRect1.Left()-=nH; + aBewareRect1.Right()+=nH; + aBewareRect1.Top()-=nV; + aBewareRect1.Bottom()+=nV; + } else { + aBoundRect1=Rectangle(aPt1,aPt1); + aBoundRect1.Move(rCon1.aObjOfs.X(),rCon1.aObjOfs.Y()); + aBewareRect1=aBoundRect1; + } + if (bCon2) { + if (rCon2.pObj==(SdrObject*)this) { // sicherheitshalber Abfragen #44515# + aBoundRect2=aOutRect; + } + else + { + aBoundRect2 = rCon2.pObj->GetCurrentBoundRect(); + } + aBoundRect2.Move(rCon2.aObjOfs.X(),rCon2.aObjOfs.Y()); + aBewareRect2=aBoundRect2; + + sal_Int32 nH = ((SdrEdgeNode2HorzDistItem&)rSet.Get(SDRATTR_EDGENODE2HORZDIST)).GetValue(); + sal_Int32 nV = ((SdrEdgeNode2VertDistItem&)rSet.Get(SDRATTR_EDGENODE2VERTDIST)).GetValue(); + + aBewareRect2.Left()-=nH; + aBewareRect2.Right()+=nH; + aBewareRect2.Top()-=nV; + aBewareRect2.Bottom()+=nV; + } else { + aBoundRect2=Rectangle(aPt2,aPt2); + aBoundRect2.Move(rCon2.aObjOfs.X(),rCon2.aObjOfs.Y()); + aBewareRect2=aBoundRect2; + } + XPolygon aBestXP; + ULONG nBestQual=0xFFFFFFFF; + SdrEdgeInfoRec aBestInfo; + FASTBOOL bAuto1=bCon1 && rCon1.bBestVertex; + FASTBOOL bAuto2=bCon2 && rCon2.bBestVertex; + if (bAuto1) rCon1.bAutoVertex=TRUE; + if (bAuto2) rCon2.bAutoVertex=TRUE; + USHORT nBestAuto1=0; + USHORT nBestAuto2=0; + USHORT nAnz1=bAuto1 ? 4 : 1; + USHORT nAnz2=bAuto2 ? 4 : 1; + for (USHORT nNum1=0; nNum1<nAnz1; nNum1++) { + if (bAuto1) rCon1.nConId=nNum1; + if (bCon1 && rCon1.TakeGluePoint(aGP1,TRUE)) { + aPt1=aGP1.GetPos(); + nEsc1=aGP1.GetEscDir(); + if (nEsc1==SDRESC_SMART) nEsc1=ImpCalcEscAngle(rCon1.pObj,aPt1-rCon1.aObjOfs); + } + for (USHORT nNum2=0; nNum2<nAnz2; nNum2++) { + if (bAuto2) rCon2.nConId=nNum2; + if (bCon2 && rCon2.TakeGluePoint(aGP2,TRUE)) { + aPt2=aGP2.GetPos(); + nEsc2=aGP2.GetEscDir(); + if (nEsc2==SDRESC_SMART) nEsc2=ImpCalcEscAngle(rCon2.pObj,aPt2-rCon2.aObjOfs); + } + for (long nA1=0; nA1<36000; nA1+=9000) { + USHORT nE1=nA1==0 ? SDRESC_RIGHT : nA1==9000 ? SDRESC_TOP : nA1==18000 ? SDRESC_LEFT : nA1==27000 ? SDRESC_BOTTOM : 0; + for (long nA2=0; nA2<36000; nA2+=9000) { + USHORT nE2=nA2==0 ? SDRESC_RIGHT : nA2==9000 ? SDRESC_TOP : nA2==18000 ? SDRESC_LEFT : nA2==27000 ? SDRESC_BOTTOM : 0; + if ((nEsc1&nE1)!=0 && (nEsc2&nE2)!=0) { + ULONG nQual=0; + SdrEdgeInfoRec aInfo; + if (pInfo!=NULL) aInfo=*pInfo; + XPolygon aXP(ImpCalcEdgeTrack(aPt1,nA1,aBoundRect1,aBewareRect1,aPt2,nA2,aBoundRect2,aBewareRect2,&nQual,&aInfo)); + if (nQual<nBestQual) { + aBestXP=aXP; + nBestQual=nQual; + aBestInfo=aInfo; + nBestAuto1=nNum1; + nBestAuto2=nNum2; + } + } + } + } + } + } + if (bAuto1) rCon1.nConId=nBestAuto1; + if (bAuto2) rCon2.nConId=nBestAuto2; + if (pInfo!=NULL) *pInfo=aBestInfo; + return aBestXP; +} + +XPolygon SdrEdgeObj::ImpCalcEdgeTrack(const Point& rPt1, long nAngle1, const Rectangle& rBoundRect1, const Rectangle& rBewareRect1, + const Point& rPt2, long nAngle2, const Rectangle& rBoundRect2, const Rectangle& rBewareRect2, + ULONG* pnQuality, SdrEdgeInfoRec* pInfo) const +{ + SdrEdgeKind eKind=((SdrEdgeKindItem&)(GetObjectItem(SDRATTR_EDGEKIND))).GetValue(); + FASTBOOL bRts1=nAngle1==0; + FASTBOOL bObn1=nAngle1==9000; + FASTBOOL bLks1=nAngle1==18000; + FASTBOOL bUnt1=nAngle1==27000; + FASTBOOL bHor1=bLks1 || bRts1; + FASTBOOL bVer1=bObn1 || bUnt1; + FASTBOOL bRts2=nAngle2==0; + FASTBOOL bObn2=nAngle2==9000; + FASTBOOL bLks2=nAngle2==18000; + FASTBOOL bUnt2=nAngle2==27000; + FASTBOOL bHor2=bLks2 || bRts2; + FASTBOOL bVer2=bObn2 || bUnt2; + FASTBOOL bInfo=pInfo!=NULL; + if (bInfo) { + pInfo->cOrthoForm=0; + pInfo->nAngle1=nAngle1; + pInfo->nAngle2=nAngle2; + pInfo->nObj1Lines=1; + pInfo->nObj2Lines=1; + pInfo->nMiddleLine=0xFFFF; + } + Point aPt1(rPt1); + Point aPt2(rPt2); + Rectangle aBoundRect1 (rBoundRect1 ); + Rectangle aBoundRect2 (rBoundRect2 ); + Rectangle aBewareRect1(rBewareRect1); + Rectangle aBewareRect2(rBewareRect2); + Point aMeeting((aPt1.X()+aPt2.X()+1)/2,(aPt1.Y()+aPt2.Y()+1)/2); + FASTBOOL bMeetingXMid=TRUE; + FASTBOOL bMeetingYMid=TRUE; + if (eKind==SDREDGE_ONELINE) { + XPolygon aXP(2); + aXP[0]=rPt1; + aXP[1]=rPt2; + if (pnQuality!=NULL) { + *pnQuality=Abs(rPt1.X()-rPt2.X())+Abs(rPt1.Y()-rPt2.Y()); + } + return aXP; + } else if (eKind==SDREDGE_THREELINES) { + XPolygon aXP(4); + aXP[0]=rPt1; + aXP[1]=rPt1; + aXP[2]=rPt2; + aXP[3]=rPt2; + if (bRts1) aXP[1].X()=aBewareRect1.Right(); //+=500; + if (bObn1) aXP[1].Y()=aBewareRect1.Top(); //-=500; + if (bLks1) aXP[1].X()=aBewareRect1.Left(); //-=500; + if (bUnt1) aXP[1].Y()=aBewareRect1.Bottom(); //+=500; + if (bRts2) aXP[2].X()=aBewareRect2.Right(); //+=500; + if (bObn2) aXP[2].Y()=aBewareRect2.Top(); //-=500; + if (bLks2) aXP[2].X()=aBewareRect2.Left(); //-=500; + if (bUnt2) aXP[2].Y()=aBewareRect2.Bottom(); //+=500; + if (pnQuality!=NULL) { + long nQ=Abs(aXP[1].X()-aXP[0].X())+Abs(aXP[1].Y()-aXP[0].Y()); + nQ+=Abs(aXP[2].X()-aXP[1].X())+Abs(aXP[2].Y()-aXP[1].Y()); + nQ+=Abs(aXP[3].X()-aXP[2].X())+Abs(aXP[3].Y()-aXP[2].Y()); + *pnQuality=nQ; + } + if (bInfo) { + pInfo->nObj1Lines=2; + pInfo->nObj2Lines=2; + if (bHor1) { + aXP[1].X()+=pInfo->aObj1Line2.X(); + } else { + aXP[1].Y()+=pInfo->aObj1Line2.Y(); + } + if (bHor2) { + aXP[2].X()+=pInfo->aObj2Line2.X(); + } else { + aXP[2].Y()+=pInfo->aObj2Line2.Y(); + } + } + return aXP; + } + USHORT nIntersections=0; + FASTBOOL bForceMeeting=FALSE; // Muss die Linie durch den MeetingPoint laufen? + { + Point aC1(aBewareRect1.Center()); + Point aC2(aBewareRect2.Center()); + if (aBewareRect1.Left()<=aBewareRect2.Right() && aBewareRect1.Right()>=aBewareRect2.Left()) { + // Ueberschneidung auf der X-Achse + long n1=Max(aBewareRect1.Left(),aBewareRect2.Left()); + long n2=Min(aBewareRect1.Right(),aBewareRect2.Right()); + aMeeting.X()=(n1+n2+1)/2; + } else { + // Ansonsten den Mittelpunkt des Freiraums + if (aC1.X()<aC2.X()) { + aMeeting.X()=(aBewareRect1.Right()+aBewareRect2.Left()+1)/2; + } else { + aMeeting.X()=(aBewareRect1.Left()+aBewareRect2.Right()+1)/2; + } + } + if (aBewareRect1.Top()<=aBewareRect2.Bottom() && aBewareRect1.Bottom()>=aBewareRect2.Top()) { + // Ueberschneidung auf der Y-Achse + long n1=Max(aBewareRect1.Top(),aBewareRect2.Top()); + long n2=Min(aBewareRect1.Bottom(),aBewareRect2.Bottom()); + aMeeting.Y()=(n1+n2+1)/2; + } else { + // Ansonsten den Mittelpunkt des Freiraums + if (aC1.Y()<aC2.Y()) { + aMeeting.Y()=(aBewareRect1.Bottom()+aBewareRect2.Top()+1)/2; + } else { + aMeeting.Y()=(aBewareRect1.Top()+aBewareRect2.Bottom()+1)/2; + } + } + // Im Prinzip gibt es 3 zu unterscheidene Faelle: + // 1. Beide in die selbe Richtung + // 2. Beide in genau entgegengesetzte Richtungen + // 3. Einer waagerecht und der andere senkrecht + long nXMin=Min(aBewareRect1.Left(),aBewareRect2.Left()); + long nXMax=Max(aBewareRect1.Right(),aBewareRect2.Right()); + long nYMin=Min(aBewareRect1.Top(),aBewareRect2.Top()); + long nYMax=Max(aBewareRect1.Bottom(),aBewareRect2.Bottom()); + //FASTBOOL bBoundOverlap=aBoundRect1.Right()>aBoundRect2.Left() && aBoundRect1.Left()<aBoundRect2.Right() && + aBoundRect1.Bottom()>aBoundRect2.Top() && aBoundRect1.Top()<aBoundRect2.Bottom(); + FASTBOOL bBewareOverlap=aBewareRect1.Right()>aBewareRect2.Left() && aBewareRect1.Left()<aBewareRect2.Right() && + aBewareRect1.Bottom()>aBewareRect2.Top() && aBewareRect1.Top()<aBewareRect2.Bottom(); + unsigned nMainCase=3; + if (nAngle1==nAngle2) nMainCase=1; + else if ((bHor1 && bHor2) || (bVer1 && bVer2)) nMainCase=2; + if (nMainCase==1) { // Fall 1: Beide in eine Richtung moeglich. + if (bVer1) aMeeting.X()=(aPt1.X()+aPt2.X()+1)/2; // ist hier besser, als der + if (bHor1) aMeeting.Y()=(aPt1.Y()+aPt2.Y()+1)/2; // Mittelpunkt des Freiraums + // bX1Ok bedeutet, dass die Vertikale, die aus Obj1 austritt, keinen Konflikt mit Obj2 bildet, ... + FASTBOOL bX1Ok=aPt1.X()<=aBewareRect2.Left() || aPt1.X()>=aBewareRect2.Right(); + FASTBOOL bX2Ok=aPt2.X()<=aBewareRect1.Left() || aPt2.X()>=aBewareRect1.Right(); + FASTBOOL bY1Ok=aPt1.Y()<=aBewareRect2.Top() || aPt1.Y()>=aBewareRect2.Bottom(); + FASTBOOL bY2Ok=aPt2.Y()<=aBewareRect1.Top() || aPt2.Y()>=aBewareRect1.Bottom(); + if (bLks1 && (bY1Ok || aBewareRect1.Left()<aBewareRect2.Right()) && (bY2Ok || aBewareRect2.Left()<aBewareRect1.Right())) { + aMeeting.X()=nXMin; + bMeetingXMid=FALSE; + } + if (bRts1 && (bY1Ok || aBewareRect1.Right()>aBewareRect2.Left()) && (bY2Ok || aBewareRect2.Right()>aBewareRect1.Left())) { + aMeeting.X()=nXMax; + bMeetingXMid=FALSE; + } + if (bObn1 && (bX1Ok || aBewareRect1.Top()<aBewareRect2.Bottom()) && (bX2Ok || aBewareRect2.Top()<aBewareRect1.Bottom())) { + aMeeting.Y()=nYMin; + bMeetingYMid=FALSE; + } + if (bUnt1 && (bX1Ok || aBewareRect1.Bottom()>aBewareRect2.Top()) && (bX2Ok || aBewareRect2.Bottom()>aBewareRect1.Top())) { + aMeeting.Y()=nYMax; + bMeetingYMid=FALSE; + } + } else if (nMainCase==2) { + // Fall 2: + bForceMeeting=TRUE; + if (bHor1) { // beide waagerecht + /* 9 Moeglichkeiten: ù ù ù */ + /* 2.1 Gegenueber, Ueberschneidung à ´ ù */ + /* nur auf der Y-Achse ù ù ù */ + /* 2.2, 2.3 Gegenueber, vertikal versetzt. à ù ù ù ù ù */ + /* Ueberschneidung weder auf der ù ´ ù ù ´ ù */ + /* X- noch auf der Y-Achse ù ù ù à ù ù */ + /* 2.4, 2.5 Untereinander, ù à ù ù ù ù */ + /* Ueberschneidung ù ´ ù ù ´ ù */ + /* nur auf X-Achse ù ù ù ù à ù */ + /* 2.6, 2.7 Gegeneinander, vertikal versetzt. ù ù à ù ù ù */ + /* Ueberschneidung weder auf der ù ´ ù ù ´ ù */ + /* X- noch auf der Y-Achse. ù ù ù ù ù à */ + /* 2.8 Gegeneinander. ù ù ù */ + /* Ueberschneidung nur ù ´ à */ + /* auf der Y-Achse. ù ù ù */ + /* 2.9 Die BewareRects der Objekte ueberschneiden */ + /* sich auf X- und Y-Achse. */ + /* Die Faelle gelten entsprechend umgesetzt auch fuer */ + /* senkrechte Linienaustritte. */ + /* Die Faelle 2.1-2.7 werden mit dem Default-Meeting ausreichend*/ + /* gut behandelt. Spezielle MeetingPoints werden hier also nur */ + /* fuer 2.8 und 2.9 bestimmt. */ + + // Normalisierung. aR1 soll der nach rechts und + // aR2 der nach links austretende sein. + Rectangle aBewR1(bRts1 ? aBewareRect1 : aBewareRect2); + Rectangle aBewR2(bRts1 ? aBewareRect2 : aBewareRect1); + Rectangle aBndR1(bRts1 ? aBoundRect1 : aBoundRect2); + Rectangle aBndR2(bRts1 ? aBoundRect2 : aBoundRect1); + if (aBewR1.Bottom()>aBewR2.Top() && aBewR1.Top()<aBewR2.Bottom()) { + // Ueberschneidung auf der Y-Achse. Faelle 2.1, 2.8, 2.9 + if (aBewR1.Right()>aBewR2.Left()) { + // Faelle 2.8, 2.9 + // Fall 2.8 ist immer Aussenrumlauf (bDirect=FALSE). + // Fall 2.9 kann auch Direktverbindung sein (bei geringer + // Ueberschneidung der BewareRects ohne Ueberschneidung der + // Boundrects wenn die Linienaustritte sonst das BewareRect + // des jeweils anderen Objekts verletzen wuerden. + FASTBOOL bCase29Direct=FALSE; + FASTBOOL bCase29=aBewR1.Right()>aBewR2.Left(); + if (aBndR1.Right()<=aBndR2.Left()) { // Fall 2.9 und keine Boundrectueberschneidung + if ((aPt1.Y()>aBewareRect2.Top() && aPt1.Y()<aBewareRect2.Bottom()) || + (aPt2.Y()>aBewareRect1.Top() && aPt2.Y()<aBewareRect1.Bottom())) { + bCase29Direct=TRUE; + } + } + if (!bCase29Direct) { + FASTBOOL bObenLang=Abs(nYMin-aMeeting.Y())<=Abs(nYMax-aMeeting.Y()); + if (bObenLang) { + aMeeting.Y()=nYMin; + } else { + aMeeting.Y()=nYMax; + } + bMeetingYMid=FALSE; + if (bCase29) { + // und nun noch dafuer sorgen, dass das + // umzingelte Obj nicht durchquert wird + if ((aBewR1.Center().Y()<aBewR2.Center().Y()) != bObenLang) { + aMeeting.X()=aBewR2.Right(); + } else { + aMeeting.X()=aBewR1.Left(); + } + bMeetingXMid=FALSE; + } + } else { + // Direkte Verbindung (3-Linien Z-Verbindung), da + // Verletzung der BewareRects unvermeidlich ist. + // Via Dreisatz werden die BewareRects nun verkleinert. + long nWant1=aBewR1.Right()-aBndR1.Right(); // Abstand bei Obj1 + long nWant2=aBndR2.Left()-aBewR2.Left(); // Abstand bei Obj2 + long nSpace=aBndR2.Left()-aBndR1.Right(); // verfuegbarer Platz + long nGet1=BigMulDiv(nWant1,nSpace,nWant1+nWant2); + long nGet2=nSpace-nGet1; + if (bRts1) { // Normalisierung zurueckwandeln + aBewareRect1.Right()+=nGet1-nWant1; + aBewareRect2.Left()-=nGet2-nWant2; + } else { + aBewareRect2.Right()+=nGet1-nWant1; + aBewareRect1.Left()-=nGet2-nWant2; + } + nIntersections++; // Qualitaet herabsetzen + } + } + } + } else if (bVer1) { // beide senkrecht + Rectangle aBewR1(bUnt1 ? aBewareRect1 : aBewareRect2); + Rectangle aBewR2(bUnt1 ? aBewareRect2 : aBewareRect1); + Rectangle aBndR1(bUnt1 ? aBoundRect1 : aBoundRect2); + Rectangle aBndR2(bUnt1 ? aBoundRect2 : aBoundRect1); + if (aBewR1.Right()>aBewR2.Left() && aBewR1.Left()<aBewR2.Right()) { + // Ueberschneidung auf der Y-Achse. Faelle 2.1, 2.8, 2.9 + if (aBewR1.Bottom()>aBewR2.Top()) { + // Faelle 2.8, 2.9 + // Fall 2.8 ist immer Aussenrumlauf (bDirect=FALSE). + // Fall 2.9 kann auch Direktverbindung sein (bei geringer + // Ueberschneidung der BewareRects ohne Ueberschneidung der + // Boundrects wenn die Linienaustritte sonst das BewareRect + // des jeweils anderen Objekts verletzen wuerden. + FASTBOOL bCase29Direct=FALSE; + FASTBOOL bCase29=aBewR1.Bottom()>aBewR2.Top(); + if (aBndR1.Bottom()<=aBndR2.Top()) { // Fall 2.9 und keine Boundrectueberschneidung + if ((aPt1.X()>aBewareRect2.Left() && aPt1.X()<aBewareRect2.Right()) || + (aPt2.X()>aBewareRect1.Left() && aPt2.X()<aBewareRect1.Right())) { + bCase29Direct=TRUE; + } + } + if (!bCase29Direct) { + FASTBOOL bLinksLang=Abs(nXMin-aMeeting.X())<=Abs(nXMax-aMeeting.X()); + if (bLinksLang) { + aMeeting.X()=nXMin; + } else { + aMeeting.X()=nXMax; + } + bMeetingXMid=FALSE; + if (bCase29) { + // und nun noch dafuer sorgen, dass das + // umzingelte Obj nicht durchquert wird + if ((aBewR1.Center().X()<aBewR2.Center().X()) != bLinksLang) { + aMeeting.Y()=aBewR2.Bottom(); + } else { + aMeeting.Y()=aBewR1.Top(); + } + bMeetingYMid=FALSE; + } + } else { + // Direkte Verbindung (3-Linien Z-Verbindung), da + // Verletzung der BewareRects unvermeidlich ist. + // Via Dreisatz werden die BewareRects nun verkleinert. + long nWant1=aBewR1.Bottom()-aBndR1.Bottom(); // Abstand bei Obj1 + long nWant2=aBndR2.Top()-aBewR2.Top(); // Abstand bei Obj2 + long nSpace=aBndR2.Top()-aBndR1.Bottom(); // verfuegbarer Platz + long nGet1=BigMulDiv(nWant1,nSpace,nWant1+nWant2); + long nGet2=nSpace-nGet1; + if (bUnt1) { // Normalisierung zurueckwandeln + aBewareRect1.Bottom()+=nGet1-nWant1; + aBewareRect2.Top()-=nGet2-nWant2; + } else { + aBewareRect2.Bottom()+=nGet1-nWant1; + aBewareRect1.Top()-=nGet2-nWant2; + } + nIntersections++; // Qualitaet herabsetzen + } + } + } + } + } else if (nMainCase==3) { // Fall 3: Einer waagerecht und der andere senkrecht. Sehr viele Fallunterscheidungen + /* Kleine Legende: ù ú ù ú ù -> Ohne Ueberschneidung, maximal Beruehrung. */ + /* ú ú ú ú ú -> Ueberschneidung */ + /* ù ú à ú ù -> Selbe Hoehe */ + /* ú ú ú ú ú -> Ueberschneidung */ + /* ù ú ù ú ù -> Ohne Ueberschneidung, maximal Beruehrung. */ + /* Linienaustritte links ´, rechts Ã, oben Á und unten Â. */ + /* Insgesamt sind 96 Konstellationen moeglich, wobei einige nicht einmal */ + /* eindeutig einem Fall und damit einer Behandlungsmethode zugeordnet werden */ + /* koennen. */ + /* 3.1: Hierzu moegen alle Konstellationen zaehlen, die durch den */ + /* Default-MeetingPoint zufriedenstellend abgedeckt sind (20+12). */ + /*    ú Á Á ú    Diese 12 ù ú ù  ù ù ú ù ú ù ù  ù ú ù ù ú ù ú ù */ + /* ú ú ú ú Á Á ú ú ú ú Konstel. ú ú ú ú ú ú ú ú ú  ú ú ú ú ú  ú ú ú ú */ + /* ù ú à ú ù ù ú ´ ú ù jedoch ù ú à ú Á ù ú à ú  Á ú ´ ú ù  ú ´ ú ù */ + /* ú ú ú ú   ú ú ú ú nur zum ú ú ú ú Á ú ú ú ú ú Á ú ú ú ú ú ú ú ú ú */ + /* Á Á Á ú   ú Á Á Á Teil: ù ú ù Á ù ù ú ù ú ù ù Á ù ú ù ù ú ù ú ù */ + /* Letztere 16 Faelle scheiden aus, sobald sich die Objekte offen */ + /* gegenueberstehen (siehe Fall 3.2). */ + /* 3.2: Die Objekte stehen sich offen gegenueber und somit ist eine */ + /* Verbindung mit lediglich 2 Linien moeglich (4+20). */ + /* Dieser Fall hat 1. Prioritaet. */ + /* ù ú ù ú   ú ù ú ù Diese 20 ù ú ù  ù ù  ù ú ù ù ú ù ú ù ù ú ù ú ù */ + /* ú ú ú ú ú ú ú ú ú ú Konstel. ú ú ú     ú ú ú ú ú ú ú ú ú ú ú ú ú */ + /* ù ú à ú ù ù ú ´ ú ù jedoch ù ú à Á Á Á Á ´ ú ù ù ú à     ´ ú ù */ + /* ú ú ú ú ú ú ú ú ú ú nur zum ú ú ú Á Á Á Á ú ú ú ú ú ú ú ú ú ú ú ú ú */ + /* ù ú ù ú Á Á ú ù ú ù Teil: ù ú ù Á ù ù Á ù ú ù ù ú ù ú ù ù ú ù ú ù */ + /* 3.3: Die Linienaustritte zeigen vom anderen Objekt weg bzw. hinter */ + /* dessen Ruecken vorbei (52+4). */ + /* Á Á Á Á ù ù Á Á Á Á ù ú ú ú ù ù ú ù ú ù Diese 4 ù ú ù ú ù ù ú ù ú ù */ + /* Á Á Á Á ú ú Á Á Á Á    ú ú ú ú    Konstel. ú ú ú  ú ú  ú ú ú */ + /* Á Á à ú ù ù ú ´ Á Á   à ú ù ù ú ´   jedoch ù ú à ú ù ù ú ´ ú ù */ + /* Á Á Á ú ú ú ú Á Á Á     ú ú     nur zum ú ú ú Á ú ú Á ú ú ú */ + /* ù ú ù ú ù ù ú ù ú ù     ù ù     Teil: ù ú ù ú ù ù ú ù ú ù */ + + // Fall 3.2 + Rectangle aTmpR1(aBewareRect1); + Rectangle aTmpR2(aBewareRect2); + if (bBewareOverlap) { + // Ueberschneidung der BewareRects: BoundRects fuer Check auf Fall 3.2 verwenden. + aTmpR1=aBoundRect1; + aTmpR2=aBoundRect2; + } + if ((((bRts1 && aTmpR1.Right ()<=aPt2.X()) || (bLks1 && aTmpR1.Left()>=aPt2.X())) && + ((bUnt2 && aTmpR2.Bottom()<=aPt1.Y()) || (bObn2 && aTmpR2.Top ()>=aPt1.Y()))) || + (((bRts2 && aTmpR2.Right ()<=aPt1.X()) || (bLks2 && aTmpR2.Left()>=aPt1.X())) && + ((bUnt1 && aTmpR1.Bottom()<=aPt2.Y()) || (bObn1 && aTmpR1.Top ()>=aPt2.Y())))) { + // Fall 3.2 trifft zu: Verbindung mit lediglich 2 Linien + bForceMeeting=TRUE; + bMeetingXMid=FALSE; + bMeetingYMid=FALSE; + if (bHor1) { + aMeeting.X()=aPt2.X(); + aMeeting.Y()=aPt1.Y(); + } else { + aMeeting.X()=aPt1.X(); + aMeeting.Y()=aPt2.Y(); + } + // Falls Ueberschneidung der BewareRects: + aBewareRect1=aTmpR1; + aBewareRect2=aTmpR2; + } else if ((((bRts1 && aBewareRect1.Right ()>aBewareRect2.Left ()) || + (bLks1 && aBewareRect1.Left ()<aBewareRect2.Right ())) && + ((bUnt2 && aBewareRect2.Bottom()>aBewareRect1.Top ()) || + (bObn2 && aBewareRect2.Top ()<aBewareRect1.Bottom()))) || + (((bRts2 && aBewareRect2.Right ()>aBewareRect1.Left ()) || + (bLks2 && aBewareRect2.Left ()<aBewareRect1.Right ())) && + ((bUnt1 && aBewareRect1.Bottom()>aBewareRect2.Top ()) || + (bObn1 && aBewareRect1.Top ()<aBewareRect2.Bottom())))) { + // Fall 3.3 + bForceMeeting=TRUE; + if (bRts1 || bRts2) { aMeeting.X()=nXMax; bMeetingXMid=FALSE; } + if (bLks1 || bLks2) { aMeeting.X()=nXMin; bMeetingXMid=FALSE; } + if (bUnt1 || bUnt2) { aMeeting.Y()=nYMax; bMeetingYMid=FALSE; } + if (bObn1 || bObn2) { aMeeting.Y()=nYMin; bMeetingYMid=FALSE; } + } + } + } + + XPolygon aXP1(ImpCalcObjToCenter(aPt1,nAngle1,aBewareRect1,aMeeting)); + XPolygon aXP2(ImpCalcObjToCenter(aPt2,nAngle2,aBewareRect2,aMeeting)); + USHORT nXP1Anz=aXP1.GetPointCount(); + USHORT nXP2Anz=aXP2.GetPointCount(); + if (bInfo) { + pInfo->nObj1Lines=nXP1Anz; if (nXP1Anz>1) pInfo->nObj1Lines--; + pInfo->nObj2Lines=nXP2Anz; if (nXP2Anz>1) pInfo->nObj2Lines--; + } + Point aEP1(aXP1[nXP1Anz-1]); + Point aEP2(aXP2[nXP2Anz-1]); + FASTBOOL bInsMeetingPoint=aEP1.X()!=aEP2.X() && aEP1.Y()!=aEP2.Y(); + FASTBOOL bHorzE1=aEP1.Y()==aXP1[nXP1Anz-2].Y(); // letzte Linie von XP1 horizontal? + FASTBOOL bHorzE2=aEP2.Y()==aXP2[nXP2Anz-2].Y(); // letzte Linie von XP2 horizontal? + if (aEP1==aEP2 && (bHorzE1 && bHorzE2 && aEP1.Y()==aEP2.Y()) || (!bHorzE1 && !bHorzE2 && aEP1.X()==aEP2.X())) { + // Sonderbehandlung fuer 'I'-Verbinder + nXP1Anz--; aXP1.Remove(nXP1Anz,1); + nXP2Anz--; aXP2.Remove(nXP2Anz,1); + bMeetingXMid=FALSE; + bMeetingYMid=FALSE; + } + if (bInsMeetingPoint) { + aXP1.Insert(XPOLY_APPEND,aMeeting,XPOLY_NORMAL); + if (bInfo) { + // Durch einfuegen des MeetingPoints kommen 2 weitere Linie hinzu. + // Evtl. wird eine von diesen die Mittellinie. + if (pInfo->nObj1Lines==pInfo->nObj2Lines) { + pInfo->nObj1Lines++; + pInfo->nObj2Lines++; + } else { + if (pInfo->nObj1Lines>pInfo->nObj2Lines) { + pInfo->nObj2Lines++; + pInfo->nMiddleLine=nXP1Anz-1; + } else { + pInfo->nObj1Lines++; + pInfo->nMiddleLine=nXP1Anz; + } + } + } + } else if (bInfo && aEP1!=aEP2 && nXP1Anz+nXP2Anz>=4) { + // Durch Verbinden der beiden Enden kommt eine weitere Linie hinzu. + // Dies wird die Mittellinie. + pInfo->nMiddleLine=nXP1Anz-1; + } + USHORT nNum=aXP2.GetPointCount(); + if (aXP1[nXP1Anz-1]==aXP2[nXP2Anz-1] && nXP1Anz>1 && nXP2Anz>1) nNum--; + while (nNum>0) { + nNum--; + aXP1.Insert(XPOLY_APPEND,aXP2[nNum],XPOLY_NORMAL); + } + USHORT nPntAnz=aXP1.GetPointCount(); + char cForm=0; + if (bInfo || pnQuality!=NULL) { + cForm='?'; + if (nPntAnz==2) cForm='I'; + else if (nPntAnz==3) cForm='L'; + else if (nPntAnz==4) { // Z oder U + if (nAngle1==nAngle2) cForm='U'; + else cForm='Z'; + } else if (nPntAnz==4) { /* Ú-¿ Ú-¿ */ + /* ... -Ù -Ù */ + } else if (nPntAnz==6) { // S oder C oder ... + if (nAngle1!=nAngle2) { + // Fuer Typ S hat Linie2 dieselbe Richtung wie Linie4. + // Bei Typ C sind die beiden genau entgegengesetzt. + Point aP1(aXP1[1]); + Point aP2(aXP1[2]); + Point aP3(aXP1[3]); + Point aP4(aXP1[4]); + if (aP1.Y()==aP2.Y()) { // beide Linien Horz + if ((aP1.X()<aP2.X())==(aP3.X()<aP4.X())) cForm='S'; + else cForm='C'; + } else { // sonst beide Linien Vert + if ((aP1.Y()<aP2.Y())==(aP3.Y()<aP4.Y())) cForm='S'; + else cForm='C'; + } + } else cForm='4'; // sonst der 3. Fall mit 5 Linien + } else cForm='?'; // + // Weitere Formen: + if (bInfo) { + pInfo->cOrthoForm=cForm; + if (cForm=='I' || cForm=='L' || cForm=='Z' || cForm=='U') { + pInfo->nObj1Lines=1; + pInfo->nObj2Lines=1; + if (cForm=='Z' || cForm=='U') { + pInfo->nMiddleLine=1; + } else { + pInfo->nMiddleLine=0xFFFF; + } + } else if (cForm=='S' || cForm=='C') { + pInfo->nObj1Lines=2; + pInfo->nObj2Lines=2; + pInfo->nMiddleLine=2; + } + } + } + if (pnQuality!=NULL) { + ULONG nQual=0; + ULONG nQual0=nQual; // Ueberlaeufe vorbeugen + FASTBOOL bOverflow=FALSE; + Point aPt0(aXP1[0]); + for (USHORT nPntNum=1; nPntNum<nPntAnz; nPntNum++) { + Point aPt1b(aXP1[nPntNum]); + nQual+=Abs(aPt1b.X()-aPt0.X())+Abs(aPt1b.Y()-aPt0.Y()); + if (nQual<nQual0) bOverflow=TRUE; + nQual0=nQual; + aPt0=aPt1b; + } + + USHORT nTmp=nPntAnz; + if (cForm=='Z') { + nTmp=2; // Z-Form hat gute Qualitaet (nTmp=2 statt 4) + ULONG n1=Abs(aXP1[1].X()-aXP1[0].X())+Abs(aXP1[1].Y()-aXP1[0].Y()); + ULONG n2=Abs(aXP1[2].X()-aXP1[1].X())+Abs(aXP1[2].Y()-aXP1[1].Y()); + ULONG n3=Abs(aXP1[3].X()-aXP1[2].X())+Abs(aXP1[3].Y()-aXP1[2].Y()); + // fuer moeglichst gleichlange Linien sorgen + ULONG nBesser=0; + n1+=n3; + n3=n2/4; + if (n1>=n2) nBesser=6; + else if (n1>=3*n3) nBesser=4; + else if (n1>=2*n3) nBesser=2; + if (aXP1[0].Y()!=aXP1[1].Y()) nBesser++; // Senkrechte Startlinie kriegt auch noch einen Pluspunkt (fuer H/V-Prio) + if (nQual>nBesser) nQual-=nBesser; else nQual=0; + } + if (nTmp>=3) { + nQual0=nQual; + nQual+=(ULONG)nTmp*0x01000000; + if (nQual<nQual0 || nTmp>15) bOverflow=TRUE; + } + if (nPntAnz>=2) { // Austrittswinkel nochmal pruefen + Point aP1(aXP1[1]); aP1-=aXP1[0]; + Point aP2(aXP1[nPntAnz-2]); aP2-=aXP1[nPntAnz-1]; + long nAng1=0; if (aP1.X()<0) nAng1=18000; if (aP1.Y()>0) nAng1=27000; + if (aP1.Y()<0) nAng1=9000; if (aP1.X()!=0 && aP1.Y()!=0) nAng1=1; // Schraeg!?! + long nAng2=0; if (aP2.X()<0) nAng2=18000; if (aP2.Y()>0) nAng2=27000; + if (aP2.Y()<0) nAng2=9000; if (aP2.X()!=0 && aP2.Y()!=0) nAng2=1; // Schraeg!?! + if (nAng1!=nAngle1) nIntersections++; + if (nAng2!=nAngle2) nIntersections++; + } + + // Fuer den Qualitaetscheck wieder die Original-Rects verwenden und + // gleichzeitig checken, ob eins fuer die Edge-Berechnung verkleinert + // wurde (z.B. Fall 2.9) + aBewareRect1=rBewareRect1; + aBewareRect2=rBewareRect2; + + for (USHORT i=0; i<nPntAnz; i++) { + Point aPt1b(aXP1[i]); + FASTBOOL b1=aPt1b.X()>aBewareRect1.Left() && aPt1b.X()<aBewareRect1.Right() && + aPt1b.Y()>aBewareRect1.Top() && aPt1b.Y()<aBewareRect1.Bottom(); + FASTBOOL b2=aPt1b.X()>aBewareRect2.Left() && aPt1b.X()<aBewareRect2.Right() && + aPt1b.Y()>aBewareRect2.Top() && aPt1b.Y()<aBewareRect2.Bottom(); + USHORT nInt0=nIntersections; + if (i==0 || i==nPntAnz-1) { + if (b1 && b2) nIntersections++; + } else { + if (b1) nIntersections++; + if (b2) nIntersections++; + } + // und nun noch auf Ueberschneidungen checken + if (i>0 && nInt0==nIntersections) { + if (aPt0.Y()==aPt1b.Y()) { // Horizontale Linie + if (aPt0.Y()>aBewareRect1.Top() && aPt0.Y()<aBewareRect1.Bottom() && + ((aPt0.X()<=aBewareRect1.Left() && aPt1b.X()>=aBewareRect1.Right()) || + (aPt1b.X()<=aBewareRect1.Left() && aPt0.X()>=aBewareRect1.Right()))) nIntersections++; + if (aPt0.Y()>aBewareRect2.Top() && aPt0.Y()<aBewareRect2.Bottom() && + ((aPt0.X()<=aBewareRect2.Left() && aPt1b.X()>=aBewareRect2.Right()) || + (aPt1b.X()<=aBewareRect2.Left() && aPt0.X()>=aBewareRect2.Right()))) nIntersections++; + } else { // Vertikale Linie + if (aPt0.X()>aBewareRect1.Left() && aPt0.X()<aBewareRect1.Right() && + ((aPt0.Y()<=aBewareRect1.Top() && aPt1b.Y()>=aBewareRect1.Bottom()) || + (aPt1b.Y()<=aBewareRect1.Top() && aPt0.Y()>=aBewareRect1.Bottom()))) nIntersections++; + if (aPt0.X()>aBewareRect2.Left() && aPt0.X()<aBewareRect2.Right() && + ((aPt0.Y()<=aBewareRect2.Top() && aPt1b.Y()>=aBewareRect2.Bottom()) || + (aPt1b.Y()<=aBewareRect2.Top() && aPt0.Y()>=aBewareRect2.Bottom()))) nIntersections++; + } + } + aPt0=aPt1b; + } + if (nPntAnz<=1) nIntersections++; + nQual0=nQual; + nQual+=(ULONG)nIntersections*0x10000000; + if (nQual<nQual0 || nIntersections>15) bOverflow=TRUE; + + if (bOverflow || nQual==0xFFFFFFFF) nQual=0xFFFFFFFE; + *pnQuality=nQual; + } + if (bInfo) { // nun die Linienversaetze auf aXP1 anwenden + if (pInfo->nMiddleLine!=0xFFFF) { + USHORT nIdx=pInfo->ImpGetPolyIdx(MIDDLELINE,aXP1); + if (pInfo->ImpIsHorzLine(MIDDLELINE,aXP1)) { + aXP1[nIdx].Y()+=pInfo->aMiddleLine.Y(); + aXP1[nIdx+1].Y()+=pInfo->aMiddleLine.Y(); + } else { + aXP1[nIdx].X()+=pInfo->aMiddleLine.X(); + aXP1[nIdx+1].X()+=pInfo->aMiddleLine.X(); + } + } + if (pInfo->nObj1Lines>=2) { + USHORT nIdx=pInfo->ImpGetPolyIdx(OBJ1LINE2,aXP1); + if (pInfo->ImpIsHorzLine(OBJ1LINE2,aXP1)) { + aXP1[nIdx].Y()+=pInfo->aObj1Line2.Y(); + aXP1[nIdx+1].Y()+=pInfo->aObj1Line2.Y(); + } else { + aXP1[nIdx].X()+=pInfo->aObj1Line2.X(); + aXP1[nIdx+1].X()+=pInfo->aObj1Line2.X(); + } + } + if (pInfo->nObj1Lines>=3) { + USHORT nIdx=pInfo->ImpGetPolyIdx(OBJ1LINE3,aXP1); + if (pInfo->ImpIsHorzLine(OBJ1LINE3,aXP1)) { + aXP1[nIdx].Y()+=pInfo->aObj1Line3.Y(); + aXP1[nIdx+1].Y()+=pInfo->aObj1Line3.Y(); + } else { + aXP1[nIdx].X()+=pInfo->aObj1Line3.X(); + aXP1[nIdx+1].X()+=pInfo->aObj1Line3.X(); + } + } + if (pInfo->nObj2Lines>=2) { + USHORT nIdx=pInfo->ImpGetPolyIdx(OBJ2LINE2,aXP1); + if (pInfo->ImpIsHorzLine(OBJ2LINE2,aXP1)) { + aXP1[nIdx].Y()+=pInfo->aObj2Line2.Y(); + aXP1[nIdx+1].Y()+=pInfo->aObj2Line2.Y(); + } else { + aXP1[nIdx].X()+=pInfo->aObj2Line2.X(); + aXP1[nIdx+1].X()+=pInfo->aObj2Line2.X(); + } + } + if (pInfo->nObj2Lines>=3) { + USHORT nIdx=pInfo->ImpGetPolyIdx(OBJ2LINE3,aXP1); + if (pInfo->ImpIsHorzLine(OBJ2LINE3,aXP1)) { + aXP1[nIdx].Y()+=pInfo->aObj2Line3.Y(); + aXP1[nIdx+1].Y()+=pInfo->aObj2Line3.Y(); + } else { + aXP1[nIdx].X()+=pInfo->aObj2Line3.X(); + aXP1[nIdx+1].X()+=pInfo->aObj2Line3.X(); + } + } + } + // Nun mache ich ggf. aus dem Verbinder eine Bezierkurve + if (eKind==SDREDGE_BEZIER && nPntAnz>2) { + Point* pPt1=&aXP1[0]; + Point* pPt2=&aXP1[1]; + Point* pPt3=&aXP1[nPntAnz-2]; + Point* pPt4=&aXP1[nPntAnz-1]; + long dx1=pPt2->X()-pPt1->X(); + long dy1=pPt2->Y()-pPt1->Y(); + long dx2=pPt3->X()-pPt4->X(); + long dy2=pPt3->Y()-pPt4->Y(); + if (cForm=='L') { // nPntAnz==3 + aXP1.SetFlags(1,XPOLY_CONTROL); + Point aPt3(*pPt2); + aXP1.Insert(2,aPt3,XPOLY_CONTROL); + nPntAnz=aXP1.GetPointCount(); + pPt1=&aXP1[0]; + pPt2=&aXP1[1]; + pPt3=&aXP1[nPntAnz-2]; + pPt4=&aXP1[nPntAnz-1]; + pPt2->X()-=dx1/3; + pPt2->Y()-=dy1/3; + pPt3->X()-=dx2/3; + pPt3->Y()-=dy2/3; + } else if (nPntAnz>=4 && nPntAnz<=6) { // Z oder U oder ... + // fuer Alle Anderen werden die Endpunkte der Ausgangslinien + // erstmal zu Kontrollpunkten. Bei nPntAnz>4 ist also noch + // Nacharbeit erforderlich! + aXP1.SetFlags(1,XPOLY_CONTROL); + aXP1.SetFlags(nPntAnz-2,XPOLY_CONTROL); + // Distanz x1.5 + pPt2->X()+=dx1/2; + pPt2->Y()+=dy1/2; + pPt3->X()+=dx2/2; + pPt3->Y()+=dy2/2; + if (nPntAnz==5) { + // Vor und hinter dem Mittelpunkt jeweils + // noch einen Kontrollpunkt einfuegen + Point aCenter(aXP1[2]); + long dx1b=aCenter.X()-aXP1[1].X(); + long dy1b=aCenter.Y()-aXP1[1].Y(); + long dx2b=aCenter.X()-aXP1[3].X(); + long dy2b=aCenter.Y()-aXP1[3].Y(); + aXP1.Insert(2,aCenter,XPOLY_CONTROL); + aXP1.SetFlags(3,XPOLY_SYMMTR); + aXP1.Insert(4,aCenter,XPOLY_CONTROL); + aXP1[2].X()-=dx1b/2; + aXP1[2].Y()-=dy1b/2; + aXP1[3].X()-=(dx1b+dx2b)/4; + aXP1[3].Y()-=(dy1b+dy2b)/4; + aXP1[4].X()-=dx2b/2; + aXP1[4].Y()-=dy2b/2; + } + if (nPntAnz==6) { + Point aPt1b(aXP1[2]); + Point aPt2b(aXP1[3]); + aXP1.Insert(2,aPt1b,XPOLY_CONTROL); + aXP1.Insert(5,aPt2b,XPOLY_CONTROL); + long dx=aPt1b.X()-aPt2b.X(); + long dy=aPt1b.Y()-aPt2b.Y(); + aXP1[3].X()-=dx/2; + aXP1[3].Y()-=dy/2; + aXP1.SetFlags(3,XPOLY_SYMMTR); + //aXP1[4].X()+=dx/2; + //aXP1[4].Y()+=dy/2; + aXP1.Remove(4,1); // weil identisch mit aXP1[3] + } + } + } + return aXP1; +} + +/* +Nach einer einfachen Rechnung koennte es max. 64 unterschiedliche Verlaeufe mit +5 Linien, 32 mit 4 Linien, 16 mit 3, 8 mit 2 Linien und 4 mit 1 Linie geben=124. +Normalisiert auf 1. Austrittswinkel nach rechts bleiben dann noch 31. +Dann noch eine vertikale Spiegelung wegnormalisiert bleiben noch 16 +characteristische Verlaufszuege mit 1-5 Linien: +Mit 1 Linie (Typ 'I'): -- +Mit 2 Linien (Typ 'L'): -Ù +Mit 3 Linien (Typ 'U'): -¿ (Typ 'Z'): Ú- + -Ù -Ù +Mit 4 Linien: 1 ist nicht plausibel, 3 ist=2 (90deg Drehung). Verbleibt 2,4 + Ú-Ù Ú¿ À¿ Ú¿ Ú¿ Ú-¿ + -Ù -Ù -Ù -Ù -Ù -Ù +Mit 5 Linien: nicht plausibel sind 1,2,4,5. 7 ist identisch mit 3 (Richtungsumkehr) + Bleibt also 3,6 und 8. '4' 'S' 'C' + ¿ Ú -¿ Ú- Ú-¿ Ú- + Ú-Ù Ú-Ù Ú-¿ Ú-¿ À¿ À¿ -Ù ³ Ú-¿ Ú-¿ À¿ Ú-¿ + -Ù -Ù -Ù Ù -Ù À- -Ù -Ù --Ù À Ù -Ù Ù -Ù À Ù +Insgesamt sind also 9 Grundtypen zu unterscheiden die den 400 Konstellationen +aus Objektposition und Austrittswinkeln zuzuordnen sind. +4 der 9 Grundtypen haben eine 'Mittellinie'. Die Anzahl der zu Objektabstaende +je Objekt variiert von 0-3: + Mi O1 O2 Anmerkung +'I': n 0 0 +'L': n 0 0 +'U': n 0-1 0-1 +'Z': j 0 0 +4.1: j 0 1 = U+1 bzw. 1+U +4.2: n 0-2 0-2 = Z+1 +'4': j 0 2 = Z+2 +'S': j 1 1 = 1+Z+1 +'C': n 0-3 0-3 = 1+U+1 +*/ + +void __EXPORT SdrEdgeObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + SfxSimpleHint* pSimple=PTR_CAST(SfxSimpleHint,&rHint); + ULONG nId=pSimple==0 ? 0 : pSimple->GetId(); + FASTBOOL bDataChg=nId==SFX_HINT_DATACHANGED; + FASTBOOL bDying=nId==SFX_HINT_DYING; + FASTBOOL bObj1=aCon1.pObj!=NULL && aCon1.pObj->GetBroadcaster()==&rBC; + FASTBOOL bObj2=aCon2.pObj!=NULL && aCon2.pObj->GetBroadcaster()==&rBC; + if (bDying && (bObj1 || bObj2)) { + // #35605# Dying vorher abfangen, damit AttrObj nicht + // wg. vermeintlicher Vorlagenaenderung rumbroadcastet + if (bObj1) aCon1.pObj=NULL; + if (bObj2) aCon2.pObj=NULL; + return; // Und mehr braucht hier nicht getan werden. + } + if ( bObj1 || bObj2 ) + { + bEdgeTrackUserDefined = sal_False; + } + SdrTextObj::Notify(rBC,rHint); + if (nNotifyingCount==0) { // Hier nun auch ein VerriegelungsFlag + ((SdrEdgeObj*)this)->nNotifyingCount++; + SdrHint* pSdrHint=PTR_CAST(SdrHint,&rHint); + if (bDataChg) { // StyleSheet geaendert + ImpSetAttrToEdgeInfo(); // Werte bei Vorlagenaenderung vom Pool nach aEdgeInfo kopieren + } + if (bDataChg || + (bObj1 && aCon1.pObj->GetPage()==pPage) || + (bObj2 && aCon2.pObj->GetPage()==pPage) || + (pSdrHint && pSdrHint->GetKind()==HINT_OBJREMOVED)) + { + // Broadcasting nur, wenn auf der selben Page + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 if (!bEdgeTrackDirty) SendRepaintBroadcast(); + ImpDirtyEdgeTrack(); + + // only redraw here, no objectchange + ActionChanged(); + // BroadcastObjectChange(); + + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } + ((SdrEdgeObj*)this)->nNotifyingCount--; + } +} + +/** updates edges that are connected to the edges of this object + as if the connected objects send a repaint broadcast + #103122# +*/ +void SdrEdgeObj::Reformat() +{ + if( NULL != aCon1.pObj ) + { + SfxSimpleHint aHint( SFX_HINT_DATACHANGED ); + Notify( *const_cast<SfxBroadcaster*>(aCon1.pObj->GetBroadcaster()), aHint ); + } + + if( NULL != aCon2.pObj ) + { + SfxSimpleHint aHint( SFX_HINT_DATACHANGED ); + Notify( *const_cast<SfxBroadcaster*>(aCon2.pObj->GetBroadcaster()), aHint ); + } +} + +void SdrEdgeObj::operator=(const SdrObject& rObj) +{ + SdrTextObj::operator=(rObj); + *pEdgeTrack =*((SdrEdgeObj&)rObj).pEdgeTrack; + bEdgeTrackDirty=((SdrEdgeObj&)rObj).bEdgeTrackDirty; + aCon1 =((SdrEdgeObj&)rObj).aCon1; + aCon2 =((SdrEdgeObj&)rObj).aCon2; + aCon1.pObj=NULL; + aCon2.pObj=NULL; + aEdgeInfo=((SdrEdgeObj&)rObj).aEdgeInfo; +} + +void SdrEdgeObj::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulEDGE); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrEdgeObj::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralEDGE); +} + +basegfx::B2DPolyPolygon SdrEdgeObj::TakeXorPoly() const +{ + basegfx::B2DPolyPolygon aPolyPolygon; + + if (bEdgeTrackDirty) + { + ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack(); + } + + if(pEdgeTrack) + { + aPolyPolygon.append(pEdgeTrack->getB2DPolygon()); + } + + return aPolyPolygon; +} + +void SdrEdgeObj::SetEdgeTrackPath( const basegfx::B2DPolyPolygon& rPoly ) +{ + if ( !rPoly.count() ) + { + bEdgeTrackDirty = sal_True; + bEdgeTrackUserDefined = sal_False; + } + else + { + *pEdgeTrack = XPolygon( rPoly.getB2DPolygon( 0 ) ); + bEdgeTrackDirty = sal_False; + bEdgeTrackUserDefined = sal_True; + + // #i110629# also set aRect and maSnapeRect dependent from pEdgeTrack + const Rectangle aPolygonBounds(pEdgeTrack->GetBoundRect()); + aRect = aPolygonBounds; + maSnapRect = aPolygonBounds; + } +} + +basegfx::B2DPolyPolygon SdrEdgeObj::GetEdgeTrackPath() const +{ + basegfx::B2DPolyPolygon aPolyPolygon; + + if (bEdgeTrackDirty) + ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack(); + + aPolyPolygon.append( pEdgeTrack->getB2DPolygon() ); + + return aPolyPolygon; +} + +sal_uInt32 SdrEdgeObj::GetHdlCount() const +{ + SdrEdgeKind eKind=((SdrEdgeKindItem&)(GetObjectItem(SDRATTR_EDGEKIND))).GetValue(); + sal_uInt32 nHdlAnz(0L); + sal_uInt32 nPntAnz(pEdgeTrack->GetPointCount()); + + if(nPntAnz) + { + nHdlAnz = 2L; + + if ((eKind==SDREDGE_ORTHOLINES || eKind==SDREDGE_BEZIER) && nPntAnz >= 4L) + { + sal_uInt32 nO1(aEdgeInfo.nObj1Lines > 0L ? aEdgeInfo.nObj1Lines - 1L : 0L); + sal_uInt32 nO2(aEdgeInfo.nObj2Lines > 0L ? aEdgeInfo.nObj2Lines - 1L : 0L); + sal_uInt32 nM(aEdgeInfo.nMiddleLine != 0xFFFF ? 1L : 0L); + nHdlAnz += nO1 + nO2 + nM; + } + else if (eKind==SDREDGE_THREELINES && nPntAnz == 4L) + { + if(GetConnectedNode(TRUE)) + nHdlAnz++; + + if(GetConnectedNode(FALSE)) + nHdlAnz++; + } + } + + return nHdlAnz; +} + +SdrHdl* SdrEdgeObj::GetHdl(sal_uInt32 nHdlNum) const +{ + SdrHdl* pHdl=NULL; + sal_uInt32 nPntAnz(pEdgeTrack->GetPointCount()); + if (nPntAnz!=0) { + if (nHdlNum==0) { + pHdl=new ImpEdgeHdl((*pEdgeTrack)[0],HDL_POLY); + if (aCon1.pObj!=NULL && aCon1.bBestVertex) pHdl->Set1PixMore(TRUE); + } else if (nHdlNum==1) { + pHdl=new ImpEdgeHdl((*pEdgeTrack)[USHORT(nPntAnz-1)],HDL_POLY); + if (aCon2.pObj!=NULL && aCon2.bBestVertex) pHdl->Set1PixMore(TRUE); + } else { + SdrEdgeKind eKind=((SdrEdgeKindItem&)(GetObjectItem(SDRATTR_EDGEKIND))).GetValue(); + if (eKind==SDREDGE_ORTHOLINES || eKind==SDREDGE_BEZIER) { + sal_uInt32 nO1(aEdgeInfo.nObj1Lines > 0L ? aEdgeInfo.nObj1Lines - 1L : 0L); + sal_uInt32 nO2(aEdgeInfo.nObj2Lines > 0L ? aEdgeInfo.nObj2Lines - 1L : 0L); + sal_uInt32 nM(aEdgeInfo.nMiddleLine != 0xFFFF ? 1L : 0L); + sal_uInt32 nNum(nHdlNum - 2L); + sal_Int32 nPt(0L); + pHdl=new ImpEdgeHdl(Point(),HDL_POLY); + if (nNum<nO1) { + nPt=nNum+1L; + if (nNum==0) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ1LINE2); + if (nNum==1) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ1LINE3); + } else { + nNum=nNum-nO1; + if (nNum<nO2) { + nPt=nPntAnz-3-nNum; + if (nNum==0) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ2LINE2); + if (nNum==1) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ2LINE3); + } else { + nNum=nNum-nO2; + if (nNum<nM) { + nPt=aEdgeInfo.nMiddleLine; + ((ImpEdgeHdl*)pHdl)->SetLineCode(MIDDLELINE); + } + } + } + if (nPt>0) { + Point aPos((*pEdgeTrack)[(sal_uInt16)nPt]); + aPos+=(*pEdgeTrack)[(sal_uInt16)nPt+1]; + aPos.X()/=2; + aPos.Y()/=2; + pHdl->SetPos(aPos); + } else { + delete pHdl; + pHdl=NULL; + } + } else if (eKind==SDREDGE_THREELINES) { + sal_uInt32 nNum(nHdlNum); + if (GetConnectedNode(TRUE)==NULL) nNum++; + Point aPos((*pEdgeTrack)[(sal_uInt16)nNum-1]); + pHdl=new ImpEdgeHdl(aPos,HDL_POLY); + if (nNum==2) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ1LINE2); + if (nNum==3) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ2LINE2); + } + } + if (pHdl!=NULL) { + pHdl->SetPointNum(nHdlNum); + } + } + return pHdl; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrEdgeObj::hasSpecialDrag() const +{ + return true; +} + +SdrObject* SdrEdgeObj::getFullDragClone() const +{ + // use Clone operator + SdrEdgeObj* pRetval = (SdrEdgeObj*)Clone(); + + // copy connections for clone, SdrEdgeObj::operator= does not do this + pRetval->ConnectToNode(true, GetConnectedNode(true)); + pRetval->ConnectToNode(false, GetConnectedNode(false)); + + return pRetval; +} + +bool SdrEdgeObj::beginSpecialDrag(SdrDragStat& rDrag) const +{ + if(!rDrag.GetHdl()) + return false; + + rDrag.SetEndDragChangesAttributes(true); + + if(rDrag.GetHdl()->GetPointNum() < 2) + { + rDrag.SetNoSnap(true); + } + + return true; +} + +bool SdrEdgeObj::applySpecialDrag(SdrDragStat& rDragStat) +{ + SdrEdgeObj* pOriginalEdge = dynamic_cast< SdrEdgeObj* >(rDragStat.GetHdl()->GetObj()); + const bool bOriginalEdgeModified(pOriginalEdge == this); + + if(!bOriginalEdgeModified && pOriginalEdge) + { + // copy connections when clone is modified. This is needed because + // as preparation to this modification the data from the original object + // was copied to the clone using the operator=. As can be seen there, + // that operator does not copy the connections (for good reason) + ConnectToNode(true, pOriginalEdge->GetConnection(true).GetObject()); + ConnectToNode(false, pOriginalEdge->GetConnection(false).GetObject()); + } + + if(rDragStat.GetHdl()->GetPointNum() < 2) + { + // start or end point connector drag + const bool bDragA(0 == rDragStat.GetHdl()->GetPointNum()); + const Point aPointNow(rDragStat.GetNow()); + + if(rDragStat.GetPageView()) + { + SdrObjConnection* pDraggedOne(bDragA ? &aCon1 : &aCon2); + + // clear connection + DisconnectFromNode(bDragA); + + // look for new connection + ImpFindConnector(aPointNow, *rDragStat.GetPageView(), *pDraggedOne, pOriginalEdge); + + if(pDraggedOne->pObj) + { + // if found, officially connect to it; ImpFindConnector only + // sets pObj hard + SdrObject* pNewConnection = pDraggedOne->pObj; + pDraggedOne->pObj = 0; + ConnectToNode(bDragA, pNewConnection); + } + + if(rDragStat.GetView() && !bOriginalEdgeModified) + { + // show IA helper, but only do this during IA, so not when the original + // Edge gets modified in the last call + rDragStat.GetView()->SetConnectMarker(*pDraggedOne, *rDragStat.GetPageView()); + } + } + + if(pEdgeTrack) + { + // change pEdgeTrack to modified position + if(bDragA) + { + (*pEdgeTrack)[0] = aPointNow; + } + else + { + (*pEdgeTrack)[sal_uInt16(pEdgeTrack->GetPointCount()-1)] = aPointNow; + } + } + + // reset edge info's offsets, this is a end point drag + aEdgeInfo.aObj1Line2 = Point(); + aEdgeInfo.aObj1Line3 = Point(); + aEdgeInfo.aObj2Line2 = Point(); + aEdgeInfo.aObj2Line3 = Point(); + aEdgeInfo.aMiddleLine = Point(); + } + else + { + // control point connector drag + const ImpEdgeHdl* pEdgeHdl = (ImpEdgeHdl*)rDragStat.GetHdl(); + const SdrEdgeLineCode eLineCode = pEdgeHdl->GetLineCode(); + const Point aDist(rDragStat.GetNow() - rDragStat.GetStart()); + sal_Int32 nDist(pEdgeHdl->IsHorzDrag() ? aDist.X() : aDist.Y()); + + nDist += aEdgeInfo.ImpGetLineVersatz(eLineCode, *pEdgeTrack); + aEdgeInfo.ImpSetLineVersatz(eLineCode, *pEdgeTrack, nDist); + } + + // force recalc EdgeTrack + *pEdgeTrack = ImpCalcEdgeTrack(*pEdgeTrack, aCon1, aCon2, &aEdgeInfo); + bEdgeTrackDirty=FALSE; + + // save EdgeInfos and mark object as user modified + ImpSetEdgeInfoToAttr(); + bEdgeTrackUserDefined = false; + //SetRectsDirty(); + //SetChanged(); + + if(bOriginalEdgeModified && rDragStat.GetView()) + { + // hide connect marker helper again when original gets changed. + // This happens at the end of the interaction + rDragStat.GetView()->HideConnectMarker(); + } + + return true; +} + +String SdrEdgeObj::getSpecialDragComment(const SdrDragStat& rDrag) const +{ + const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj()); + + if(bCreateComment) + { + return String(); + } + else + { + XubString aStr; + ImpTakeDescriptionStr(STR_DragEdgeTail, aStr); + + return aStr; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +basegfx::B2DPolygon SdrEdgeObj::ImplAddConnectorOverlay(SdrDragMethod& rDragMethod, bool bTail1, bool bTail2, bool bDetail) const +{ + basegfx::B2DPolygon aResult; + + if(bDetail) + { + SdrObjConnection aMyCon1(aCon1); + SdrObjConnection aMyCon2(aCon2); + + if (bTail1) + { + const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aMyCon1.aObjOfs.X(), aMyCon1.aObjOfs.Y())); + aMyCon1.aObjOfs.X() = basegfx::fround(aTemp.getX()); + aMyCon1.aObjOfs.Y() = basegfx::fround(aTemp.getY()); + } + + if (bTail2) + { + const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aMyCon2.aObjOfs.X(), aMyCon2.aObjOfs.Y())); + aMyCon2.aObjOfs.X() = basegfx::fround(aTemp.getX()); + aMyCon2.aObjOfs.Y() = basegfx::fround(aTemp.getY()); + } + + SdrEdgeInfoRec aInfo(aEdgeInfo); + XPolygon aXP(ImpCalcEdgeTrack(*pEdgeTrack, aMyCon1, aMyCon2, &aInfo)); + + if(aXP.GetPointCount()) + { + aResult = aXP.getB2DPolygon(); + } + } + else + { + Point aPt1((*pEdgeTrack)[0]); + Point aPt2((*pEdgeTrack)[sal_uInt16(pEdgeTrack->GetPointCount() - 1)]); + + if (aCon1.pObj && (aCon1.bBestConn || aCon1.bBestVertex)) + aPt1 = aCon1.pObj->GetSnapRect().Center(); + + if (aCon2.pObj && (aCon2.bBestConn || aCon2.bBestVertex)) + aPt2 = aCon2.pObj->GetSnapRect().Center(); + + if (bTail1) + { + const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aPt1.X(), aPt1.Y())); + aPt1.X() = basegfx::fround(aTemp.getX()); + aPt1.Y() = basegfx::fround(aTemp.getY()); + } + + if (bTail2) + { + const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aPt2.X(), aPt2.Y())); + aPt2.X() = basegfx::fround(aTemp.getX()); + aPt2.Y() = basegfx::fround(aTemp.getY()); + } + + aResult.append(basegfx::B2DPoint(aPt1.X(), aPt1.Y())); + aResult.append(basegfx::B2DPoint(aPt2.X(), aPt2.Y())); + } + + return aResult; +} + +FASTBOOL SdrEdgeObj::BegCreate(SdrDragStat& rDragStat) +{ + rDragStat.SetNoSnap(TRUE); + pEdgeTrack->SetPointCount(2); + (*pEdgeTrack)[0]=rDragStat.GetStart(); + (*pEdgeTrack)[1]=rDragStat.GetNow(); + if (rDragStat.GetPageView()!=NULL) { + ImpFindConnector(rDragStat.GetStart(),*rDragStat.GetPageView(),aCon1,this); + ConnectToNode(TRUE,aCon1.pObj); + } + *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo); + return TRUE; +} + +FASTBOOL SdrEdgeObj::MovCreate(SdrDragStat& rDragStat) +{ + USHORT nMax=pEdgeTrack->GetPointCount(); + (*pEdgeTrack)[nMax-1]=rDragStat.GetNow(); + if (rDragStat.GetPageView()!=NULL) { + ImpFindConnector(rDragStat.GetNow(),*rDragStat.GetPageView(),aCon2,this); + rDragStat.GetView()->SetConnectMarker(aCon2,*rDragStat.GetPageView()); + } + SetBoundRectDirty(); + bSnapRectDirty=TRUE; + ConnectToNode(FALSE,aCon2.pObj); + *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo); + bEdgeTrackDirty=FALSE; + return TRUE; +} + +FASTBOOL SdrEdgeObj::EndCreate(SdrDragStat& rDragStat, SdrCreateCmd eCmd) +{ + FASTBOOL bOk=(eCmd==SDRCREATE_FORCEEND || rDragStat.GetPointAnz()>=2); + if (bOk) { + ConnectToNode(TRUE,aCon1.pObj); + ConnectToNode(FALSE,aCon2.pObj); + if (rDragStat.GetView()!=NULL) { + rDragStat.GetView()->HideConnectMarker(); + } + ImpSetEdgeInfoToAttr(); // Die Werte aus aEdgeInfo in den Pool kopieren + } + SetRectsDirty(); + return bOk; +} + +FASTBOOL SdrEdgeObj::BckCreate(SdrDragStat& rDragStat) +{ + if (rDragStat.GetView()!=NULL) { + rDragStat.GetView()->HideConnectMarker(); + } + return FALSE; +} + +void SdrEdgeObj::BrkCreate(SdrDragStat& rDragStat) +{ + if (rDragStat.GetView()!=NULL) { + rDragStat.GetView()->HideConnectMarker(); + } +} + +basegfx::B2DPolyPolygon SdrEdgeObj::TakeCreatePoly(const SdrDragStat& /*rStatDrag*/) const +{ + basegfx::B2DPolyPolygon aRetval; + aRetval.append(pEdgeTrack->getB2DPolygon()); + return aRetval; +} + +Pointer SdrEdgeObj::GetCreatePointer() const +{ + return Pointer(POINTER_DRAW_CONNECT); +} + +FASTBOOL SdrEdgeObj::ImpFindConnector(const Point& rPt, const SdrPageView& rPV, SdrObjConnection& rCon, const SdrEdgeObj* pThis, OutputDevice* pOut) +{ + rCon.ResetVars(); + if (pOut==NULL) pOut=rPV.GetView().GetFirstOutputDevice(); // GetWin(0); + if (pOut==NULL) return FALSE; + SdrObjList* pOL=rPV.GetObjList(); + const SetOfByte& rVisLayer=rPV.GetVisibleLayers(); + // Sensitiver Bereich der Konnektoren ist doppelt so gross wie die Handles: + USHORT nMarkHdSiz=rPV.GetView().GetMarkHdlSizePixel(); + Size aHalfConSiz(nMarkHdSiz,nMarkHdSiz); + aHalfConSiz=pOut->PixelToLogic(aHalfConSiz); + Size aHalfCenterSiz(2*aHalfConSiz.Width(),2*aHalfConSiz.Height()); + Rectangle aMouseRect(rPt,rPt); + aMouseRect.Left() -=aHalfConSiz.Width(); + aMouseRect.Top() -=aHalfConSiz.Height(); + aMouseRect.Right() +=aHalfConSiz.Width(); + aMouseRect.Bottom()+=aHalfConSiz.Height(); + USHORT nBoundHitTol=(USHORT)aHalfConSiz.Width()/2; if (nBoundHitTol==0) nBoundHitTol=1; + ULONG no=pOL->GetObjCount(); + FASTBOOL bFnd=FALSE; + SdrObjConnection aTestCon; + SdrObjConnection aBestCon; + FASTBOOL bTestBoundHit=FALSE; + //FASTBOOL bBestBoundHit=FALSE; + + while (no>0 && !bFnd) { + // Problem: Gruppenobjekt mit verschiedenen Layern liefert LayerID 0 !!!! + no--; + SdrObject* pObj=pOL->GetObj(no); + if (rVisLayer.IsSet(pObj->GetLayer()) && pObj->IsVisible() && // only visible objects + (pThis==NULL || pObj!=(SdrObject*)pThis) && // nicht an mich selbst connecten + pObj->IsNode()) + { + Rectangle aObjBound(pObj->GetCurrentBoundRect()); + if (aObjBound.IsOver(aMouseRect)) { + aTestCon.ResetVars(); + bTestBoundHit=FALSE; + FASTBOOL bEdge=HAS_BASE(SdrEdgeObj,pObj); // kein BestCon fuer Edge + // Die Userdefined Konnektoren haben absolute Prioritaet. + // Danach kommt Vertex, Corner und Mitte(Best) gleich priorisiert. + // Zum Schluss kommt noch ein HitTest aufs Obj. + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + USHORT nConAnz=pGPL==NULL ? 0 : pGPL->GetCount(); + USHORT nGesAnz=nConAnz+9; + FASTBOOL bUserFnd=FALSE; + ULONG nBestDist=0xFFFFFFFF; + for (USHORT i=0; i<nGesAnz; i++) + { + FASTBOOL bUser=i<nConAnz; + FASTBOOL bVertex=i>=nConAnz+0 && i<nConAnz+4; + FASTBOOL bCorner=i>=nConAnz+4 && i<nConAnz+8; + FASTBOOL bCenter=i==nConAnz+8; + FASTBOOL bOk=FALSE; + Point aConPos; + USHORT nConNum=i; + if (bUser) { + const SdrGluePoint& rGP=(*pGPL)[nConNum]; + aConPos=rGP.GetAbsolutePos(*pObj); + nConNum=rGP.GetId(); + bOk=TRUE; + } else if (bVertex && !bUserFnd) { + nConNum=nConNum-nConAnz; + if (rPV.GetView().IsAutoVertexConnectors()) { + SdrGluePoint aPt(pObj->GetVertexGluePoint(nConNum)); + aConPos=aPt.GetAbsolutePos(*pObj); + bOk=TRUE; + } else i+=3; + } else if (bCorner && !bUserFnd) { + nConNum-=nConAnz+4; + if (rPV.GetView().IsAutoCornerConnectors()) { + SdrGluePoint aPt(pObj->GetCornerGluePoint(nConNum)); + aConPos=aPt.GetAbsolutePos(*pObj); + bOk=TRUE; + } else i+=3; + } + else if (bCenter && !bUserFnd && !bEdge) + { + // #109007# + // Suppress default connect at object center + if(!pThis || !pThis->GetSuppressDefaultConnect()) + { + // Edges nicht! + nConNum=0; + aConPos=aObjBound.Center(); + bOk=TRUE; + } + } + if (bOk && aMouseRect.IsInside(aConPos)) { + if (bUser) bUserFnd=TRUE; + bFnd=TRUE; + ULONG nDist=(ULONG)Abs(aConPos.X()-rPt.X())+(ULONG)Abs(aConPos.Y()-rPt.Y()); + if (nDist<nBestDist) { + nBestDist=nDist; + aTestCon.pObj=pObj; + aTestCon.nConId=nConNum; + aTestCon.bAutoCorner=bCorner; + aTestCon.bAutoVertex=bVertex; + aTestCon.bBestConn=FALSE; // bCenter; + aTestCon.bBestVertex=bCenter; + } + } + } + // Falls kein Konnektor getroffen wird nochmal + // HitTest versucht fuer BestConnector (=bCenter) + if(!bFnd && + !bEdge && + SdrObjectPrimitiveHit(*pObj, rPt, nBoundHitTol, rPV, &rVisLayer, false)) + { + // #109007# + // Suppress default connect at object inside bound + if(!pThis || !pThis->GetSuppressDefaultConnect()) + { + bFnd=TRUE; + aTestCon.pObj=pObj; + aTestCon.bBestConn=TRUE; + } + } + if (bFnd) { + Rectangle aMouseRect2(rPt,rPt); + aMouseRect.Left() -=nBoundHitTol; + aMouseRect.Top() -=nBoundHitTol; + aMouseRect.Right() +=nBoundHitTol; + aMouseRect.Bottom()+=nBoundHitTol; + bTestBoundHit=aObjBound.IsOver(aMouseRect2); + } + + } + } + } + rCon=aTestCon; + return bFnd; +} + +void SdrEdgeObj::NbcSetSnapRect(const Rectangle& rRect) +{ + const Rectangle aOld(GetSnapRect()); + + if(aOld != rRect) + { + if(aRect.IsEmpty() && 0 == pEdgeTrack->GetPointCount()) + { + // #i110629# When initializing, do not scale on empty Rectangle; this + // will mirror the underlying text object (!) + aRect = rRect; + maSnapRect = rRect; + } + else + { + long nMulX = rRect.Right() - rRect.Left(); + long nDivX = aOld.Right() - aOld.Left(); + long nMulY = rRect.Bottom() - rRect.Top(); + long nDivY = aOld.Bottom() - aOld.Top(); + if ( nDivX == 0 ) { nMulX = 1; nDivX = 1; } + if ( nDivY == 0 ) { nMulY = 1; nDivY = 1; } + Fraction aX(nMulX, nDivX); + Fraction aY(nMulY, nDivY); + NbcResize(aOld.TopLeft(), aX, aY); + NbcMove(Size(rRect.Left() - aOld.Left(), rRect.Top() - aOld.Top())); + } + } +} + +void SdrEdgeObj::NbcMove(const Size& rSiz) +{ + SdrTextObj::NbcMove(rSiz); + MoveXPoly(*pEdgeTrack,rSiz); +} + +void SdrEdgeObj::NbcResize(const Point& rRefPnt, const Fraction& aXFact, const Fraction& aYFact) +{ + SdrTextObj::NbcResize(rRefPnt,aXFact,aXFact); + ResizeXPoly(*pEdgeTrack,rRefPnt,aXFact,aYFact); + + // #75371# if resize is not from paste, forget user distances + if(!GetModel()->IsPasteResize()) + { + // #75735# + aEdgeInfo.aObj1Line2 = Point(); + aEdgeInfo.aObj1Line3 = Point(); + aEdgeInfo.aObj2Line2 = Point(); + aEdgeInfo.aObj2Line3 = Point(); + aEdgeInfo.aMiddleLine = Point(); + } +} + +SdrObject* SdrEdgeObj::DoConvertToPolyObj(BOOL bBezier) const +{ + basegfx::B2DPolyPolygon aPolyPolygon; + aPolyPolygon.append(pEdgeTrack->getB2DPolygon()); + SdrObject* pRet = ImpConvertMakeObj(aPolyPolygon, sal_False, bBezier); + pRet = ImpConvertAddText(pRet, bBezier); + + return pRet; +} + +sal_uInt32 SdrEdgeObj::GetSnapPointCount() const +{ + return 2L; +} + +Point SdrEdgeObj::GetSnapPoint(sal_uInt32 i) const +{ + ((SdrEdgeObj*)this)->ImpUndirtyEdgeTrack(); + USHORT nAnz=pEdgeTrack->GetPointCount(); + if (i==0) return (*pEdgeTrack)[0]; + else return (*pEdgeTrack)[nAnz-1]; +} + +sal_Bool SdrEdgeObj::IsPolyObj() const +{ + return sal_False; +} + +sal_uInt32 SdrEdgeObj::GetPointCount() const +{ + return 0L; +} + +Point SdrEdgeObj::GetPoint(sal_uInt32 i) const +{ + ((SdrEdgeObj*)this)->ImpUndirtyEdgeTrack(); + USHORT nAnz=pEdgeTrack->GetPointCount(); + if (0L == i) + return (*pEdgeTrack)[0]; + else + return (*pEdgeTrack)[nAnz-1]; +} + +void SdrEdgeObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i) +{ + // ToDo: Umconnekten fehlt noch + ImpUndirtyEdgeTrack(); + USHORT nAnz=pEdgeTrack->GetPointCount(); + if (0L == i) + (*pEdgeTrack)[0]=rPnt; + if (1L == i) + (*pEdgeTrack)[nAnz-1]=rPnt; + SetEdgeTrackDirty(); + SetRectsDirty(); +} + +SdrEdgeObjGeoData::SdrEdgeObjGeoData() +{ + pEdgeTrack=new XPolygon; +} + +SdrEdgeObjGeoData::~SdrEdgeObjGeoData() +{ + delete pEdgeTrack; +} + +SdrObjGeoData* SdrEdgeObj::NewGeoData() const +{ + return new SdrEdgeObjGeoData; +} + +void SdrEdgeObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrTextObj::SaveGeoData(rGeo); + SdrEdgeObjGeoData& rEGeo=(SdrEdgeObjGeoData&)rGeo; + rEGeo.aCon1 =aCon1; + rEGeo.aCon2 =aCon2; + *rEGeo.pEdgeTrack =*pEdgeTrack; + rEGeo.bEdgeTrackDirty=bEdgeTrackDirty; + rEGeo.bEdgeTrackUserDefined=bEdgeTrackUserDefined; + rEGeo.aEdgeInfo =aEdgeInfo; +} + +void SdrEdgeObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrTextObj::RestGeoData(rGeo); + SdrEdgeObjGeoData& rEGeo=(SdrEdgeObjGeoData&)rGeo; + if (aCon1.pObj!=rEGeo.aCon1.pObj) { + if (aCon1.pObj!=NULL) aCon1.pObj->RemoveListener(*this); + aCon1=rEGeo.aCon1; + if (aCon1.pObj!=NULL) aCon1.pObj->AddListener(*this); + } + if (aCon2.pObj!=rEGeo.aCon2.pObj) { + if (aCon2.pObj!=NULL) aCon2.pObj->RemoveListener(*this); + aCon2=rEGeo.aCon2; + if (aCon2.pObj!=NULL) aCon2.pObj->AddListener(*this); + } + *pEdgeTrack =*rEGeo.pEdgeTrack; + bEdgeTrackDirty=rEGeo.bEdgeTrackDirty; + bEdgeTrackUserDefined=rEGeo.bEdgeTrackUserDefined; + aEdgeInfo =rEGeo.aEdgeInfo; +} + +Point SdrEdgeObj::GetTailPoint( BOOL bTail ) const +{ + if( pEdgeTrack && pEdgeTrack->GetPointCount()!=0) + { + const XPolygon& rTrack0 = *pEdgeTrack; + if(bTail) + { + return rTrack0[0]; + } + else + { + const USHORT nSiz = rTrack0.GetPointCount() - 1; + return rTrack0[nSiz]; + } + } + else + { + if(bTail) + return aOutRect.TopLeft(); + else + return aOutRect.BottomRight(); + } + +} + +void SdrEdgeObj::SetTailPoint( BOOL bTail, const Point& rPt ) +{ + ImpSetTailPoint( bTail, rPt ); + SetChanged(); +} + +/** this method is used by the api to set a glue point for a connection + nId == -1 : The best default point is automaticly choosen + 0 <= nId <= 3 : One of the default points is choosen + nId >= 4 : A user defined glue point is choosen +*/ +void SdrEdgeObj::setGluePointIndex( sal_Bool bTail, sal_Int32 nIndex /* = -1 */ ) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetCurrentBoundRect(); + // #110094#-14 BroadcastObjectChange(); + + SdrObjConnection& rConn1 = GetConnection( bTail ); + + rConn1.SetAutoVertex( nIndex >= 0 && nIndex <= 3 ); + rConn1.SetBestConnection( nIndex < 0 ); + rConn1.SetBestVertex( nIndex < 0 ); + + if( nIndex > 3 ) + { +// nIndex -= 4; + nIndex -= 3; // SJ: the start api index is 0, whereas the implementation in svx starts from 1 + + // for user defined glue points we have + // to get the id for this index first + const SdrGluePointList* pList = rConn1.GetObject() ? rConn1.GetObject()->GetGluePointList() : NULL; + if( pList == NULL || SDRGLUEPOINT_NOTFOUND == pList->FindGluePoint((sal_uInt16)nIndex) ) + return; + } + else if( nIndex < 0 ) + { + nIndex = 0; + } + + rConn1.SetConnectorId( (USHORT)nIndex ); + + SetChanged(); + SetRectsDirty(); + ImpRecalcEdgeTrack(); + // bEdgeTrackDirty=TRUE; +} + +/** this method is used by the api to return a glue point id for a connection. + See setGluePointId for possible return values */ +sal_Int32 SdrEdgeObj::getGluePointIndex( sal_Bool bTail ) +{ + SdrObjConnection& rConn1 = GetConnection( bTail ); + sal_Int32 nId = -1; + if( !rConn1.IsBestConnection() ) + { + nId = rConn1.GetConnectorId(); + if( !rConn1.IsAutoVertex() ) +// nId += 4; + nId += 3; // SJ: the start api index is 0, whereas the implementation in svx starts from 1 + } + return nId; +} + +// #102344# Implementation was missing; edge track needs to be invalidated additionally. +void SdrEdgeObj::NbcSetAnchorPos(const Point& rPnt) +{ + // call parent functionality + SdrTextObj::NbcSetAnchorPos(rPnt); + + // Additionally, invalidate edge track + ImpDirtyEdgeTrack(); +} + +sal_Bool SdrEdgeObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon) const +{ + // use base method from SdrObject, it's not rotatable and + // a call to GetSnapRect() is used. That's what we need for Connector. + return SdrObject::TRGetBaseGeometry(rMatrix, rPolyPolygon); +} + +void SdrEdgeObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon) +{ + // evtl. take care for existing connections. For now, just use the + // implementation from SdrObject. + SdrObject::TRSetBaseGeometry(rMatrix, rPolyPolygon); +} + +// for geometry access +::basegfx::B2DPolygon SdrEdgeObj::getEdgeTrack() const +{ + if(bEdgeTrackDirty) + { + const_cast< SdrEdgeObj* >(this)->ImpRecalcEdgeTrack(); + } + + if(pEdgeTrack) + { + return pEdgeTrack->getB2DPolygon(); + } + else + { + return ::basegfx::B2DPolygon(); + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx new file mode 100644 index 000000000000..d1f65c30050d --- /dev/null +++ b/svx/source/svdraw/svdograf.cxx @@ -0,0 +1,1282 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#define _ANIMATION +#include <unotools/streamwrap.hxx> + +#include <sfx2/lnkbase.hxx> +#include <math.h> +#include <vcl/salbtype.hxx> +#include <sot/formats.hxx> +#include <sot/storage.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <svl/style.hxx> +#include <svtools/filter.hxx> +#include <svl/urihelper.hxx> +#include <svtools/grfmgr.hxx> +#include <vcl/svapp.hxx> + +#include <sfx2/linkmgr.hxx> +#include <svx/svdetc.hxx> +#include "svdglob.hxx" +#include "svdstr.hrc" +#include <svx/svdpool.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdmrkv.hxx> +#include <svx/svdpagv.hxx> +#include "svdviter.hxx" +#include <svx/svdview.hxx> +#include "svtools/filter.hxx" +#include <svx/svdograf.hxx> +#include <svx/svdogrp.hxx> +#include <svx/xbitmap.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/svdundo.hxx> +#include "svdfmtf.hxx" +#include <svx/sdgcpitm.hxx> +#include <editeng/eeitem.hxx> +#include <svx/sdr/properties/graphicproperties.hxx> +#include <svx/sdr/contact/viewcontactofgraphic.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; + +// ----------- +// - Defines - +// ----------- + +#define GRAFSTREAMPOS_INVALID 0xffffffff +#define SWAPGRAPHIC_TIMEOUT 5000 + +// ------------------ +// - SdrGraphicLink - +// ------------------ + +class SdrGraphicLink : public sfx2::SvBaseLink +{ + SdrGrafObj* pGrafObj; + +public: + SdrGraphicLink(SdrGrafObj* pObj); + virtual ~SdrGraphicLink(); + + virtual void Closed(); + virtual void DataChanged( const String& rMimeType, + const ::com::sun::star::uno::Any & rValue ); + + BOOL Connect() { return 0 != GetRealObject(); } + void UpdateSynchron(); +}; + +// ----------------------------------------------------------------------------- + +SdrGraphicLink::SdrGraphicLink(SdrGrafObj* pObj): + ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, SOT_FORMATSTR_ID_SVXB ), + pGrafObj(pObj) +{ + SetSynchron( FALSE ); +} + +// ----------------------------------------------------------------------------- + +SdrGraphicLink::~SdrGraphicLink() +{ +} + +// ----------------------------------------------------------------------------- + +void SdrGraphicLink::DataChanged( const String& rMimeType, + const ::com::sun::star::uno::Any & rValue ) +{ + SdrModel* pModel = pGrafObj ? pGrafObj->GetModel() : 0; + sfx2::LinkManager* pLinkManager= pModel ? pModel->GetLinkManager() : 0; + + if( pLinkManager && rValue.hasValue() ) + { + pLinkManager->GetDisplayNames( this, 0, &pGrafObj->aFileName, 0, &pGrafObj->aFilterName ); + + Graphic aGraphic; + if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGraphic )) + { + pGrafObj->NbcSetGraphic( aGraphic ); + pGrafObj->ActionChanged(); + } + else if( SotExchange::GetFormatIdFromMimeType( rMimeType ) != sfx2::LinkManager::RegisterStatusInfoId() ) + { + // only repaint, no objectchange + pGrafObj->ActionChanged(); + // pGrafObj->BroadcastObjectChange(); + } + } +} + +// ----------------------------------------------------------------------------- + +void SdrGraphicLink::Closed() +{ + // Die Verbindung wird aufgehoben; pLink des Objekts auf NULL setzen, da die Link-Instanz ja gerade destruiert wird. + pGrafObj->ForceSwapIn(); + pGrafObj->pGraphicLink=NULL; + pGrafObj->ReleaseGraphicLink(); + SvBaseLink::Closed(); +} + +// ----------------------------------------------------------------------------- + +void SdrGraphicLink::UpdateSynchron() +{ + if( GetObj() ) + { + String aMimeType( SotExchange::GetFormatMimeType( GetContentType() )); + ::com::sun::star::uno::Any aValue; + GetObj()->GetData( aValue, aMimeType, TRUE ); + DataChanged( aMimeType, aValue ); + } +} + +// -------------- +// - SdrGrafObj - +// -------------- + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrGrafObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::GraphicProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrGrafObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfGraphic(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrGrafObj,SdrRectObj); + +// ----------------------------------------------------------------------------- + +SdrGrafObj::SdrGrafObj() +: SdrRectObj(), + pGraphicLink ( NULL ), + bMirrored ( FALSE ) +{ + pGraphic = new GraphicObject; + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + bNoShear = TRUE; + + // #111096# + mbGrafAnimationAllowed = sal_True; + + // #i25616# + mbLineIsOutsideGeometry = sal_True; + mbInsidePaint = sal_False; + mbIsPreview = sal_False; + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_False; +} + +// ----------------------------------------------------------------------------- + +SdrGrafObj::SdrGrafObj(const Graphic& rGrf, const Rectangle& rRect) +: SdrRectObj ( rRect ), + pGraphicLink ( NULL ), + bMirrored ( FALSE ) +{ + pGraphic = new GraphicObject( rGrf ); + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + bNoShear = TRUE; + + // #111096# + mbGrafAnimationAllowed = sal_True; + + // #i25616# + mbLineIsOutsideGeometry = sal_True; + mbInsidePaint = sal_False; + mbIsPreview = sal_False; + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_False; +} + +// ----------------------------------------------------------------------------- + +SdrGrafObj::SdrGrafObj( const Graphic& rGrf ) +: SdrRectObj(), + pGraphicLink ( NULL ), + bMirrored ( FALSE ) +{ + pGraphic = new GraphicObject( rGrf ); + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + bNoShear = TRUE; + + // #111096# + mbGrafAnimationAllowed = sal_True; + + // #i25616# + mbLineIsOutsideGeometry = sal_True; + mbInsidePaint = sal_False; + mbIsPreview = sal_False; + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_False; +} + +// ----------------------------------------------------------------------------- + +SdrGrafObj::~SdrGrafObj() +{ + delete pGraphic; + ImpLinkAbmeldung(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SetGraphicObject( const GraphicObject& rGrfObj ) +{ + *pGraphic = rGrfObj; + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + pGraphic->SetUserData(); + mbIsPreview = sal_False; + SetChanged(); + BroadcastObjectChange(); +} + +// ----------------------------------------------------------------------------- + +const GraphicObject& SdrGrafObj::GetGraphicObject(bool bForceSwapIn) const +{ + if(bForceSwapIn) + { + ForceSwapIn(); + } + + return *pGraphic; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::NbcSetGraphic( const Graphic& rGrf ) +{ + pGraphic->SetGraphic( rGrf ); + pGraphic->SetUserData(); + mbIsPreview = sal_False; +} + +void SdrGrafObj::SetGraphic( const Graphic& rGrf ) +{ + NbcSetGraphic(rGrf); + SetChanged(); + BroadcastObjectChange(); +} + +// ----------------------------------------------------------------------------- + +const Graphic& SdrGrafObj::GetGraphic() const +{ + ForceSwapIn(); + return pGraphic->GetGraphic(); +} + +// ----------------------------------------------------------------------------- + +Graphic SdrGrafObj::GetTransformedGraphic( ULONG nTransformFlags ) const +{ + // #107947# Refactored most of the code to GraphicObject, where + // everybody can use e.g. the cropping functionality + + GraphicType eType = GetGraphicType(); + MapMode aDestMap( pModel->GetScaleUnit(), Point(), pModel->GetScaleFraction(), pModel->GetScaleFraction() ); + const Size aDestSize( GetLogicRect().GetSize() ); + const BOOL bMirror = ( nTransformFlags & SDRGRAFOBJ_TRANSFORMATTR_MIRROR ) != 0; + const BOOL bRotate = ( ( nTransformFlags & SDRGRAFOBJ_TRANSFORMATTR_ROTATE ) != 0 ) && + ( aGeo.nDrehWink && aGeo.nDrehWink != 18000 ) && ( GRAPHIC_NONE != eType ); + + // #104115# Need cropping info earlier + ( (SdrGrafObj*) this )->ImpSetAttrToGrafInfo(); + GraphicAttr aActAttr; + + if( SDRGRAFOBJ_TRANSFORMATTR_NONE != nTransformFlags && + GRAPHIC_NONE != eType ) + { + // actually transform the graphic only in this case. On the + // other hand, cropping will always happen + aActAttr = aGrafInfo; + + if( bMirror ) + { + USHORT nMirrorCase = ( aGeo.nDrehWink == 18000 ) ? ( bMirrored ? 3 : 4 ) : ( bMirrored ? 2 : 1 ); + FASTBOOL bHMirr = nMirrorCase == 2 || nMirrorCase == 4; + FASTBOOL bVMirr = nMirrorCase == 3 || nMirrorCase == 4; + + aActAttr.SetMirrorFlags( ( bHMirr ? BMP_MIRROR_HORZ : 0 ) | ( bVMirr ? BMP_MIRROR_VERT : 0 ) ); + } + + if( bRotate ) + aActAttr.SetRotation( sal_uInt16(aGeo.nDrehWink / 10) ); + } + + // #107947# Delegate to moved code in GraphicObject + return GetGraphicObject().GetTransformedGraphic( aDestSize, aDestMap, aActAttr ); +} + +// ----------------------------------------------------------------------------- + +GraphicType SdrGrafObj::GetGraphicType() const +{ + return pGraphic->GetType(); +} + +sal_Bool SdrGrafObj::IsAnimated() const +{ + return pGraphic->IsAnimated(); +} + +sal_Bool SdrGrafObj::IsEPS() const +{ + return pGraphic->IsEPS(); +} + +sal_Bool SdrGrafObj::IsSwappedOut() const +{ + return mbIsPreview ? sal_True : pGraphic->IsSwappedOut(); +} + +const MapMode& SdrGrafObj::GetGrafPrefMapMode() const +{ + return pGraphic->GetPrefMapMode(); +} + +const Size& SdrGrafObj::GetGrafPrefSize() const +{ + return pGraphic->GetPrefSize(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SetGrafStreamURL( const String& rGraphicStreamURL ) +{ + mbIsPreview = sal_False; + if( !rGraphicStreamURL.Len() ) + { + pGraphic->SetUserData(); + } + else if( pModel->IsSwapGraphics() ) + { + pGraphic->SetUserData( rGraphicStreamURL ); + + // set state of graphic object to 'swapped out' + if( pGraphic->GetType() == GRAPHIC_NONE ) + pGraphic->SetSwapState(); + } +} + +// ----------------------------------------------------------------------------- + +String SdrGrafObj::GetGrafStreamURL() const +{ + return pGraphic->GetUserData(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SetFileName(const String& rFileName) +{ + aFileName = rFileName; + SetChanged(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SetFilterName(const String& rFilterName) +{ + aFilterName = rFilterName; + SetChanged(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::ForceSwapIn() const +{ + if( mbIsPreview ) + { + // removing preview graphic + const String aUserData( pGraphic->GetUserData() ); + + Graphic aEmpty; + pGraphic->SetGraphic( aEmpty ); + pGraphic->SetUserData( aUserData ); + pGraphic->SetSwapState(); + + const_cast< SdrGrafObj* >( this )->mbIsPreview = sal_False; + } + + pGraphic->FireSwapInRequest(); + + if( pGraphic->IsSwappedOut() || + ( pGraphic->GetType() == GRAPHIC_NONE ) || + ( pGraphic->GetType() == GRAPHIC_DEFAULT ) ) + { + Graphic aDefaultGraphic; + aDefaultGraphic.SetDefaultType(); + pGraphic->SetGraphic( aDefaultGraphic ); + } +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::ForceSwapOut() const +{ + pGraphic->FireSwapOutRequest(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::ImpLinkAnmeldung() +{ + sfx2::LinkManager* pLinkManager = pModel != NULL ? pModel->GetLinkManager() : NULL; + + if( pLinkManager != NULL && pGraphicLink == NULL ) + { + if( aFileName.Len() ) + { + pGraphicLink = new SdrGraphicLink( this ); + pLinkManager->InsertFileLink( *pGraphicLink, OBJECT_CLIENT_GRF, aFileName, ( aFilterName.Len() ? &aFilterName : NULL ), NULL ); + pGraphicLink->Connect(); + } + } +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::ImpLinkAbmeldung() +{ + sfx2::LinkManager* pLinkManager = pModel != NULL ? pModel->GetLinkManager() : NULL; + + if( pLinkManager != NULL && pGraphicLink!=NULL) + { + // Bei Remove wird *pGraphicLink implizit deleted + pLinkManager->Remove( pGraphicLink ); + pGraphicLink=NULL; + } +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SetGraphicLink( const String& rFileName, const String& rFilterName ) +{ + ImpLinkAbmeldung(); + aFileName = rFileName; + aFilterName = rFilterName; + ImpLinkAnmeldung(); + pGraphic->SetUserData(); + + // #92205# A linked graphic is per definition swapped out (has to be loaded) + pGraphic->SetSwapState(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::ReleaseGraphicLink() +{ + ImpLinkAbmeldung(); + aFileName = String(); + aFilterName = String(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + FASTBOOL bAnim = pGraphic->IsAnimated(); + FASTBOOL bNoPresGrf = ( pGraphic->GetType() != GRAPHIC_NONE ) && !bEmptyPresObj; + + rInfo.bResizeFreeAllowed = aGeo.nDrehWink % 9000 == 0 || + aGeo.nDrehWink % 18000 == 0 || + aGeo.nDrehWink % 27000 == 0; + + rInfo.bResizePropAllowed = TRUE; + rInfo.bRotateFreeAllowed = bNoPresGrf && !bAnim; + rInfo.bRotate90Allowed = bNoPresGrf && !bAnim; + rInfo.bMirrorFreeAllowed = bNoPresGrf && !bAnim; + rInfo.bMirror45Allowed = bNoPresGrf && !bAnim; + rInfo.bMirror90Allowed = !bEmptyPresObj; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed = FALSE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bCanConvToPath = FALSE; + rInfo.bCanConvToPathLineToArea = FALSE; + rInfo.bCanConvToPolyLineToArea = FALSE; + rInfo.bCanConvToPoly = !IsEPS(); + rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +// ----------------------------------------------------------------------------- + +UINT16 SdrGrafObj::GetObjIdentifier() const +{ + return UINT16( OBJ_GRAF ); +} + +// ----------------------------------------------------------------------------- + +sal_Bool SdrGrafObj::ImpUpdateGraphicLink() const +{ + sal_Bool bRet = sal_False; + + if( pGraphicLink ) + { + const sal_Bool bIsChanged = pModel->IsChanged(); + pGraphicLink->UpdateSynchron(); + pModel->SetChanged( bIsChanged ); + + bRet = sal_True; + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::TakeObjNameSingul(XubString& rName) const +{ + switch( pGraphic->GetType() ) + { + case GRAPHIC_BITMAP: + { + const USHORT nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ? + ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK : STR_ObjNameSingulGRAFBMPTRANS ) : + ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK : STR_ObjNameSingulGRAFBMP ) ); + + rName=ImpGetResStr( nId ); + } + break; + + case GRAPHIC_GDIMETAFILE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK : STR_ObjNameSingulGRAFMTF ); + break; + + case GRAPHIC_NONE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK : STR_ObjNameSingulGRAFNONE ); + break; + + default: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK : STR_ObjNameSingulGRAF ); + break; + } + + const String aName(GetName()); + + if( aName.Len() ) + { + rName.AppendAscii( " '" ); + rName += aName; + rName += sal_Unicode( '\'' ); + } +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::TakeObjNamePlural( XubString& rName ) const +{ + switch( pGraphic->GetType() ) + { + case GRAPHIC_BITMAP: + { + const USHORT nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ? + ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK : STR_ObjNamePluralGRAFBMPTRANS ) : + ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK : STR_ObjNamePluralGRAFBMP ) ); + + rName=ImpGetResStr( nId ); + } + break; + + case GRAPHIC_GDIMETAFILE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK : STR_ObjNamePluralGRAFMTF ); + break; + + case GRAPHIC_NONE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK : STR_ObjNamePluralGRAFNONE ); + break; + + default: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK : STR_ObjNamePluralGRAF ); + break; + } + + const String aName(GetName()); + + if( aName.Len() ) + { + rName.AppendAscii( " '" ); + rName += aName; + rName += sal_Unicode( '\'' ); + } +} + +// ----------------------------------------------------------------------------- + +SdrObject* SdrGrafObj::getFullDragClone() const +{ + // call parent + SdrGrafObj* pRetval = static_cast< SdrGrafObj* >(SdrRectObj::getFullDragClone()); + + // #i103116# the full drag clone leads to problems + // with linked graphics, so reset the link in this + // temporary interaction object and load graphic + if(pRetval && IsLinkedGraphic()) + { + pRetval->ForceSwapIn(); + pRetval->ReleaseGraphicLink(); + } + + return pRetval; +} + +void SdrGrafObj::operator=( const SdrObject& rObj ) +{ + SdrRectObj::operator=( rObj ); + + const SdrGrafObj& rGraf = (SdrGrafObj&) rObj; + + pGraphic->SetGraphic( rGraf.GetGraphic(), &rGraf.GetGraphicObject() ); + aCropRect = rGraf.aCropRect; + aFileName = rGraf.aFileName; + aFilterName = rGraf.aFilterName; + bMirrored = rGraf.bMirrored; + + if( rGraf.pGraphicLink != NULL) + { + SetGraphicLink( aFileName, aFilterName ); + } + + ImpSetAttrToGrafInfo(); +} + +// ----------------------------------------------------------------------------- +// #i25616# + +basegfx::B2DPolyPolygon SdrGrafObj::TakeXorPoly() const +{ + if(mbInsidePaint) + { + basegfx::B2DPolyPolygon aRetval; + + // take grown rectangle + const sal_Int32 nHalfLineWidth(ImpGetLineWdt() / 2); + const Rectangle aGrownRect( + aRect.Left() - nHalfLineWidth, + aRect.Top() - nHalfLineWidth, + aRect.Right() + nHalfLineWidth, + aRect.Bottom() + nHalfLineWidth); + + XPolygon aXPoly(ImpCalcXPoly(aGrownRect, GetEckenradius())); + aRetval.append(aXPoly.getB2DPolygon()); + + return aRetval; + } + else + { + // call parent + return SdrRectObj::TakeXorPoly(); + } +} + +// ----------------------------------------------------------------------------- + +sal_uInt32 SdrGrafObj::GetHdlCount() const +{ + return 8L; +} + +// ----------------------------------------------------------------------------- + +SdrHdl* SdrGrafObj::GetHdl(sal_uInt32 nHdlNum) const +{ + return SdrRectObj::GetHdl( nHdlNum + 1L ); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + SdrRectObj::NbcResize( rRef, xFact, yFact ); + + FASTBOOL bMirrX = xFact.GetNumerator() < 0; + FASTBOOL bMirrY = yFact.GetNumerator() < 0; + + if( bMirrX != bMirrY ) + bMirrored = !bMirrored; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + SdrRectObj::NbcRotate(rRef,nWink,sn,cs); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + SdrRectObj::NbcMirror(rRef1,rRef2); + bMirrored = !bMirrored; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + SdrRectObj::NbcRotate( rRef, nWink, tn, bVShear ); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::NbcSetSnapRect(const Rectangle& rRect) +{ + SdrRectObj::NbcSetSnapRect(rRect); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::NbcSetLogicRect( const Rectangle& rRect) +{ + //FASTBOOL bChg=rRect.GetSize()!=aRect.GetSize(); + SdrRectObj::NbcSetLogicRect(rRect); +} + +// ----------------------------------------------------------------------------- + +SdrObjGeoData* SdrGrafObj::NewGeoData() const +{ + return new SdrGrafObjGeoData; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrRectObj::SaveGeoData(rGeo); + SdrGrafObjGeoData& rGGeo=(SdrGrafObjGeoData&)rGeo; + rGGeo.bMirrored=bMirrored; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + //long nDrehMerk = aGeo.nDrehWink; + //long nShearMerk = aGeo.nShearWink; + //FASTBOOL bMirrMerk = bMirrored; + Size aSizMerk( aRect.GetSize() ); + + SdrRectObj::RestGeoData(rGeo); + SdrGrafObjGeoData& rGGeo=(SdrGrafObjGeoData&)rGeo; + bMirrored=rGGeo.bMirrored; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SetPage( SdrPage* pNewPage ) +{ + FASTBOOL bRemove = pNewPage == NULL && pPage != NULL; + FASTBOOL bInsert = pNewPage != NULL && pPage == NULL; + + if( bRemove ) + { + // hier kein SwapIn noetig, weil wenn nicht geladen, dann auch nicht animiert. + if( pGraphic->IsAnimated()) + pGraphic->StopAnimation(); + + if( pGraphicLink != NULL ) + ImpLinkAbmeldung(); + } + + SdrRectObj::SetPage( pNewPage ); + + if(aFileName.Len() && bInsert) + ImpLinkAnmeldung(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::SetModel( SdrModel* pNewModel ) +{ + FASTBOOL bChg = pNewModel != pModel; + + if( bChg ) + { + if( pGraphic->HasUserData() ) + { + ForceSwapIn(); + pGraphic->SetUserData(); + } + + if( pGraphicLink != NULL ) + ImpLinkAbmeldung(); + } + + // Model umsetzen + SdrRectObj::SetModel(pNewModel); + + if( bChg && aFileName.Len() ) + ImpLinkAnmeldung(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::StartAnimation( OutputDevice* /*pOutDev*/, const Point& /*rPoint*/, const Size& /*rSize*/, long /*nExtraData*/) +{ + // #111096# + // use new graf animation + SetGrafAnimationAllowed(sal_True); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::StopAnimation(OutputDevice* /*pOutDev*/, long /*nExtraData*/) +{ + // #111096# + // use new graf animation + SetGrafAnimationAllowed(sal_False); +} + +// ----------------------------------------------------------------------------- + +FASTBOOL SdrGrafObj::HasGDIMetaFile() const +{ + return( pGraphic->GetType() == GRAPHIC_GDIMETAFILE ); +} + +// ----------------------------------------------------------------------------- + +const GDIMetaFile* SdrGrafObj::GetGDIMetaFile() const +{ + DBG_ERROR( "Invalid return value! Don't use it! (KA)" ); + return &GetGraphic().GetGDIMetaFile(); +} + +// ----------------------------------------------------------------------------- + +SdrObject* SdrGrafObj::DoConvertToPolyObj(BOOL bBezier) const +{ + SdrObject* pRetval = NULL; + + switch( GetGraphicType() ) + { + case GRAPHIC_GDIMETAFILE: + { + // NUR die aus dem MetaFile erzeugbaren Objekte in eine Gruppe packen und zurueckliefern + SdrObjGroup* pGrp = new SdrObjGroup(); + ImpSdrGDIMetaFileImport aFilter(*GetModel()); + Point aOutPos( aRect.TopLeft() ); + const Size aOutSiz( aRect.GetSize() ); + + aFilter.SetScaleRect(GetSnapRect()); + aFilter.SetLayer(GetLayer()); + + UINT32 nInsAnz = aFilter.DoImport(GetTransformedGraphic().GetGDIMetaFile(), *pGrp->GetSubList(), 0); + if(nInsAnz) + { + pRetval = pGrp; + pGrp->NbcSetLayer(GetLayer()); + pGrp->SetModel(GetModel()); + pRetval = ImpConvertAddText(pRetval, bBezier); + + // convert all children + if( pRetval ) + { + SdrObject* pHalfDone = pRetval; + pRetval = pHalfDone->DoConvertToPolyObj(bBezier); + SdrObject::Free( pHalfDone ); // resulting object is newly created + + if( pRetval ) + { + // flatten subgroups. As we call + // DoConvertToPolyObj() on the resulting group + // objects, subgroups can exist (e.g. text is + // a group object for every line). + SdrObjList* pList = pRetval->GetSubList(); + if( pList ) + pList->FlattenGroups(); + } + } + } + else + delete pGrp; + break; + } + case GRAPHIC_BITMAP: + { + // Grundobjekt kreieren und Fuellung ergaenzen + pRetval = SdrRectObj::DoConvertToPolyObj(bBezier); + + // Bitmap als Attribut retten + if(pRetval) + { + // Bitmap als Fuellung holen + SfxItemSet aSet(GetObjectItemSet()); + + aSet.Put(XFillStyleItem(XFILL_BITMAP)); + Bitmap aBitmap( GetTransformedGraphic().GetBitmap() ); + XOBitmap aXBmp(aBitmap, XBITMAP_STRETCH); + aSet.Put(XFillBitmapItem(String(), aXBmp)); + aSet.Put(XFillBmpTileItem(FALSE)); + + pRetval->SetMergedItemSet(aSet); + } + break; + } + case GRAPHIC_NONE: + case GRAPHIC_DEFAULT: + { + pRetval = SdrRectObj::DoConvertToPolyObj(bBezier); + break; + } + } + + return pRetval; +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + SetXPolyDirty(); + SdrRectObj::Notify( rBC, rHint ); + ImpSetAttrToGrafInfo(); +} + +void SdrGrafObj::ImpSetAttrToGrafInfo() +{ + const SfxItemSet& rSet = GetObjectItemSet(); + const sal_uInt16 nTrans = ( (SdrGrafTransparenceItem&) rSet.Get( SDRATTR_GRAFTRANSPARENCE ) ).GetValue(); + const SdrGrafCropItem& rCrop = (const SdrGrafCropItem&) rSet.Get( SDRATTR_GRAFCROP ); + + aGrafInfo.SetLuminance( ( (SdrGrafLuminanceItem&) rSet.Get( SDRATTR_GRAFLUMINANCE ) ).GetValue() ); + aGrafInfo.SetContrast( ( (SdrGrafContrastItem&) rSet.Get( SDRATTR_GRAFCONTRAST ) ).GetValue() ); + aGrafInfo.SetChannelR( ( (SdrGrafRedItem&) rSet.Get( SDRATTR_GRAFRED ) ).GetValue() ); + aGrafInfo.SetChannelG( ( (SdrGrafGreenItem&) rSet.Get( SDRATTR_GRAFGREEN ) ).GetValue() ); + aGrafInfo.SetChannelB( ( (SdrGrafBlueItem&) rSet.Get( SDRATTR_GRAFBLUE ) ).GetValue() ); + aGrafInfo.SetGamma( ( (SdrGrafGamma100Item&) rSet.Get( SDRATTR_GRAFGAMMA ) ).GetValue() * 0.01 ); + aGrafInfo.SetTransparency( (BYTE) FRound( Min( nTrans, (USHORT) 100 ) * 2.55 ) ); + aGrafInfo.SetInvert( ( (SdrGrafInvertItem&) rSet.Get( SDRATTR_GRAFINVERT ) ).GetValue() ); + aGrafInfo.SetDrawMode( ( (SdrGrafModeItem&) rSet.Get( SDRATTR_GRAFMODE ) ).GetValue() ); + aGrafInfo.SetCrop( rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom() ); + + SetXPolyDirty(); + SetRectsDirty(); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::ImpSetGrafInfoToAttr() +{ + SetObjectItem( SdrGrafLuminanceItem( aGrafInfo.GetLuminance() ) ); + SetObjectItem( SdrGrafContrastItem( aGrafInfo.GetContrast() ) ); + SetObjectItem( SdrGrafRedItem( aGrafInfo.GetChannelR() ) ); + SetObjectItem( SdrGrafGreenItem( aGrafInfo.GetChannelG() ) ); + SetObjectItem( SdrGrafBlueItem( aGrafInfo.GetChannelB() ) ); + SetObjectItem( SdrGrafGamma100Item( FRound( aGrafInfo.GetGamma() * 100.0 ) ) ); + SetObjectItem( SdrGrafTransparenceItem( (USHORT) FRound( aGrafInfo.GetTransparency() / 2.55 ) ) ); + SetObjectItem( SdrGrafInvertItem( aGrafInfo.IsInvert() ) ); + SetObjectItem( SdrGrafModeItem( aGrafInfo.GetDrawMode() ) ); + SetObjectItem( SdrGrafCropItem( aGrafInfo.GetLeftCrop(), aGrafInfo.GetTopCrop(), aGrafInfo.GetRightCrop(), aGrafInfo.GetBottomCrop() ) ); +} + +// ----------------------------------------------------------------------------- + +void SdrGrafObj::AdjustToMaxRect( const Rectangle& rMaxRect, bool bShrinkOnly ) +{ + Size aSize; + Size aMaxSize( rMaxRect.GetSize() ); + if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL ) + aSize = Application::GetDefaultDevice()->PixelToLogic( pGraphic->GetPrefSize(), MAP_100TH_MM ); + else + aSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(), + pGraphic->GetPrefMapMode(), + MapMode( MAP_100TH_MM ) ); + + if( aSize.Height() != 0 && aSize.Width() != 0 ) + { + Point aPos( rMaxRect.TopLeft() ); + + // Falls Grafik zu gross, wird die Grafik + // in die Seite eingepasst + if ( (!bShrinkOnly || + ( aSize.Height() > aMaxSize.Height() ) || + ( aSize.Width() > aMaxSize.Width() ) )&& + aSize.Height() && aMaxSize.Height() ) + { + float fGrfWH = (float)aSize.Width() / + (float)aSize.Height(); + float fWinWH = (float)aMaxSize.Width() / + (float)aMaxSize.Height(); + + // Grafik an Pagesize anpassen (skaliert) + if ( fGrfWH < fWinWH ) + { + aSize.Width() = (long)(aMaxSize.Height() * fGrfWH); + aSize.Height()= aMaxSize.Height(); + } + else if ( fGrfWH > 0.F ) + { + aSize.Width() = aMaxSize.Width(); + aSize.Height()= (long)(aMaxSize.Width() / fGrfWH); + } + + aPos = rMaxRect.Center(); + } + + if( bShrinkOnly ) + aPos = aRect.TopLeft(); + + aPos.X() -= aSize.Width() / 2; + aPos.Y() -= aSize.Height() / 2; + SetLogicRect( Rectangle( aPos, aSize ) ); + } +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SdrGrafObj, ImpSwapHdl, GraphicObject*, pO ) +{ + SvStream* pRet = GRFMGR_AUTOSWAPSTREAM_NONE; + + if( pO->IsInSwapOut() ) + { + if( pModel && !mbIsPreview && pModel->IsSwapGraphics() && pGraphic->GetSizeBytes() > 20480 ) + { + // test if this object is visualized from someone + // ## test only if there are VOCs other than the preview renderer + if(!GetViewContact().HasViewObjectContacts(true)) + { + const ULONG nSwapMode = pModel->GetSwapGraphicsMode(); + + if( ( pGraphic->HasUserData() || pGraphicLink ) && + ( nSwapMode & SDR_SWAPGRAPHICSMODE_PURGE ) ) + { + pRet = NULL; + } + else if( nSwapMode & SDR_SWAPGRAPHICSMODE_TEMP ) + { + pRet = GRFMGR_AUTOSWAPSTREAM_TEMP; + pGraphic->SetUserData(); + } + + // #i102380# + sdr::contact::ViewContactOfGraphic* pVC = dynamic_cast< sdr::contact::ViewContactOfGraphic* >(&GetViewContact()); + + if(pVC) + { + pVC->flushGraphicObjects(); + } + } + } + } + else if( pO->IsInSwapIn() ) + { + // kann aus dem original Doc-Stream nachgeladen werden... + if( pModel != NULL ) + { + if( pGraphic->HasUserData() ) + { + SdrDocumentStreamInfo aStreamInfo; + + aStreamInfo.mbDeleteAfterUse = FALSE; + aStreamInfo.maUserData = pGraphic->GetUserData(); + + SvStream* pStream = pModel->GetDocumentStream( aStreamInfo ); + + if( pStream != NULL ) + { + Graphic aGraphic; + + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData = NULL; + + if(mbInsidePaint && !GetViewContact().HasViewObjectContacts(true)) + { +// Rectangle aSnapRect(GetSnapRect()); +// const Rectangle aSnapRectPixel(pOutDev->LogicToPixel(aSnapRect)); + + pFilterData = new com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >( 3 ); + + com::sun::star::awt::Size aPreviewSizeHint( 64, 64 ); + sal_Bool bAllowPartialStreamRead = sal_True; + sal_Bool bCreateNativeLink = sal_False; + (*pFilterData)[ 0 ].Name = String( RTL_CONSTASCII_USTRINGPARAM( "PreviewSizeHint" ) ); + (*pFilterData)[ 0 ].Value <<= aPreviewSizeHint; + (*pFilterData)[ 1 ].Name = String( RTL_CONSTASCII_USTRINGPARAM( "AllowPartialStreamRead" ) ); + (*pFilterData)[ 1 ].Value <<= bAllowPartialStreamRead; + (*pFilterData)[ 2 ].Name = String( RTL_CONSTASCII_USTRINGPARAM( "CreateNativeLink" ) ); + (*pFilterData)[ 2 ].Value <<= bCreateNativeLink; + + mbIsPreview = sal_True; + } + + if( !GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pStream, + GRFILTER_FORMAT_DONTKNOW, NULL, 0, pFilterData ) ) + { + const String aUserData( pGraphic->GetUserData() ); + + pGraphic->SetGraphic( aGraphic ); + pGraphic->SetUserData( aUserData ); + + // #142146# Graphic successfully swapped in. + pRet = GRFMGR_AUTOSWAPSTREAM_LOADED; + } + delete pFilterData; + + pStream->ResetError(); + + if( aStreamInfo.mbDeleteAfterUse || aStreamInfo.mxStorageRef.is() ) + { + if ( aStreamInfo.mxStorageRef.is() ) + { + aStreamInfo.mxStorageRef->dispose(); + aStreamInfo.mxStorageRef = 0; + } + + delete pStream; + } + } + } + else if( !ImpUpdateGraphicLink() ) + { + pRet = GRFMGR_AUTOSWAPSTREAM_TEMP; + } + else + { + pRet = GRFMGR_AUTOSWAPSTREAM_LOADED; + } + } + else + pRet = GRFMGR_AUTOSWAPSTREAM_TEMP; + } + + return (long)(void*) pRet; +} + +// ----------------------------------------------------------------------------- + +// #111096# +// Access to GrafAnimationAllowed flag +sal_Bool SdrGrafObj::IsGrafAnimationAllowed() const +{ + return mbGrafAnimationAllowed; +} + +void SdrGrafObj::SetGrafAnimationAllowed(sal_Bool bNew) +{ + if(mbGrafAnimationAllowed != bNew) + { + mbGrafAnimationAllowed = bNew; + ActionChanged(); + } +} + +// #i25616# +sal_Bool SdrGrafObj::IsObjectTransparent() const +{ + if(((const SdrGrafTransparenceItem&)GetObjectItem(SDRATTR_GRAFTRANSPARENCE)).GetValue() + || pGraphic->IsTransparent()) + { + return sal_True; + } + + return sal_False; +} + +Reference< XInputStream > SdrGrafObj::getInputStream() +{ + Reference< XInputStream > xStream; + + if( pModel ) + { +// if( !pGraphic->HasUserData() ) +// pGraphic->SwapOut(); + + // kann aus dem original Doc-Stream nachgeladen werden... + if( pGraphic->HasUserData() ) + { + SdrDocumentStreamInfo aStreamInfo; + + aStreamInfo.mbDeleteAfterUse = FALSE; + aStreamInfo.maUserData = pGraphic->GetUserData(); + + SvStream* pStream = pModel->GetDocumentStream( aStreamInfo ); + + if( pStream ) + xStream.set( new utl::OInputStreamWrapper( pStream, sal_True ) ); + } + else if( pGraphic && GetGraphic().IsLink() ) + { + Graphic aGraphic( GetGraphic() ); + GfxLink aLink( aGraphic.GetLink() ); + sal_uInt32 nSize = aLink.GetDataSize(); + const void* pSourceData = (const void*)aLink.GetData(); + if( nSize && pSourceData ) + { + sal_uInt8 * pBuffer = new sal_uInt8[ nSize ]; + if( pBuffer ) + { + memcpy( pBuffer, pSourceData, nSize ); + + SvMemoryStream* pStream = new SvMemoryStream( (void*)pBuffer, (sal_Size)nSize, STREAM_READ ); + pStream->ObjectOwnsMemory( sal_True ); + xStream.set( new utl::OInputStreamWrapper( pStream, sal_True ) ); + } + } + } + + if( !xStream.is() && aFileName.Len() ) + { + SvFileStream* pStream = new SvFileStream( aFileName, STREAM_READ ); + if( pStream ) + xStream.set( new utl::OInputStreamWrapper( pStream ) ); + } + } + + return xStream; +} + +// eof diff --git a/svx/source/svdraw/svdogrp.cxx b/svx/source/svdraw/svdogrp.cxx new file mode 100644 index 000000000000..4060369f8016 --- /dev/null +++ b/svx/source/svdraw/svdogrp.cxx @@ -0,0 +1,801 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <sfx2/linkmgr.hxx> + +#include <ucbhelper/content.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/datetime.hxx> + +#include <svx/svdogrp.hxx> + +#include <sfx2/lnkbase.hxx> +#include <tools/urlobj.hxx> + +#include <svl/urihelper.hxx> + +#include <svx/xpool.hxx> +#include <svx/xpoly.hxx> + +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include "svditer.hxx" +#include <svx/svdobj.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdattrx.hxx> // NotPersistItems +#include <svx/svdoedge.hxx> // #32383# Die Verbinder nach Move nochmal anbroadcasten +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname + +#include <svx/svxids.hrc> +#include <svl/whiter.hxx> +#include <svx/svdpool.hxx> +#include <svx/sdr/properties/groupproperties.hxx> + +// #110094# +#include <svx/sdr/contact/viewcontactofgroup.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@@@@ @@@@@@ @@@@ @@@@@ @@@@ @@ @@ @@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@@ @@@@@ @@ @@ @@ @@ @@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@ @@@@@ @@@@ @@@@@ @@ @@ @@@@ @@@@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrObjGroup::CreateObjectSpecificProperties() +{ + return new sdr::properties::GroupProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// #110094# DrawContact section + +sdr::contact::ViewContact* SdrObjGroup::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfGroup(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrObjGroup,SdrObject); + +SdrObjGroup::SdrObjGroup() +{ + pSub=new SdrObjList(NULL,NULL); + pSub->SetOwnerObj(this); + pSub->SetListKind(SDROBJLIST_GROUPOBJ); + bRefPoint=FALSE; + nDrehWink=0; + nShearWink=0; + bClosedObj=FALSE; +} + + +SdrObjGroup::~SdrObjGroup() +{ + delete pSub; +} + +void SdrObjGroup::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bNoContortion=FALSE; + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + SdrObjTransformInfoRec aInfo; + pObj->TakeObjInfo(aInfo); + if (!aInfo.bMoveAllowed ) rInfo.bMoveAllowed =FALSE; + if (!aInfo.bResizeFreeAllowed ) rInfo.bResizeFreeAllowed =FALSE; + if (!aInfo.bResizePropAllowed ) rInfo.bResizePropAllowed =FALSE; + if (!aInfo.bRotateFreeAllowed ) rInfo.bRotateFreeAllowed =FALSE; + if (!aInfo.bRotate90Allowed ) rInfo.bRotate90Allowed =FALSE; + if (!aInfo.bMirrorFreeAllowed ) rInfo.bMirrorFreeAllowed =FALSE; + if (!aInfo.bMirror45Allowed ) rInfo.bMirror45Allowed =FALSE; + if (!aInfo.bMirror90Allowed ) rInfo.bMirror90Allowed =FALSE; + if (!aInfo.bShearAllowed ) rInfo.bShearAllowed =FALSE; + if (!aInfo.bEdgeRadiusAllowed ) rInfo.bEdgeRadiusAllowed =FALSE; + if (!aInfo.bNoOrthoDesired ) rInfo.bNoOrthoDesired =FALSE; + if (aInfo.bNoContortion ) rInfo.bNoContortion =TRUE; + if (!aInfo.bCanConvToPath ) rInfo.bCanConvToPath =FALSE; + + if(!aInfo.bCanConvToContour) + rInfo.bCanConvToContour = FALSE; + + if (!aInfo.bCanConvToPoly ) rInfo.bCanConvToPoly =FALSE; + if (!aInfo.bCanConvToPathLineToArea) rInfo.bCanConvToPathLineToArea=FALSE; + if (!aInfo.bCanConvToPolyLineToArea) rInfo.bCanConvToPolyLineToArea=FALSE; + } + if (nObjAnz==0) { + rInfo.bRotateFreeAllowed=FALSE; + rInfo.bRotate90Allowed =FALSE; + rInfo.bMirrorFreeAllowed=FALSE; + rInfo.bMirror45Allowed =FALSE; + rInfo.bMirror90Allowed =FALSE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =FALSE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bNoContortion =TRUE; + } + if(nObjAnz != 1) + { + // only allowed if single object selected + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + } +} + + +void SdrObjGroup::SetBoundRectDirty() +{ + // avoid resetting aOutRect which in case of this object is model data, + // not re-creatable view data +} + +UINT16 SdrObjGroup::GetObjIdentifier() const +{ + return UINT16(OBJ_GRUP); +} + + +SdrLayerID SdrObjGroup::GetLayer() const +{ + FASTBOOL b1st=TRUE; + SdrLayerID nLay=SdrLayerID(SdrObject::GetLayer()); + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrLayerID nLay1=pOL->GetObj(i)->GetLayer(); + if (b1st) { nLay=nLay1; b1st=FALSE; } + else if (nLay1!=nLay) return 0; + } + return nLay; +} + + +void SdrObjGroup::NbcSetLayer(SdrLayerID nLayer) +{ + SdrObject::NbcSetLayer(nLayer); + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + pOL->GetObj(i)->NbcSetLayer(nLayer); + } +} + + +void SdrObjGroup::SetObjList(SdrObjList* pNewObjList) +{ + SdrObject::SetObjList(pNewObjList); + pSub->SetUpList(pNewObjList); +} + + +void SdrObjGroup::SetPage(SdrPage* pNewPage) +{ + SdrObject::SetPage(pNewPage); + pSub->SetPage(pNewPage); +} + + +void SdrObjGroup::SetModel(SdrModel* pNewModel) +{ + if(pNewModel!=pModel) + { + // #i30648# + // This method also needs to migrate the used ItemSet + // when the destination model uses a different pool + // than the current one. Else it is possible to create + // SdrObjGroups which reference the old pool which might + // be destroyed (as the bug shows). + SdrModel* pOldModel = pModel; + + // test for correct pool in ItemSet; move to new pool if necessary + if(pNewModel && GetObjectItemPool() && GetObjectItemPool() != &pNewModel->GetItemPool()) + { + MigrateItemPool(GetObjectItemPool(), &pNewModel->GetItemPool(), pNewModel); + } + + // call parent + SdrObject::SetModel(pNewModel); + + // set new model at content + pSub->SetModel(pNewModel); + + // modify properties + GetProperties().SetModel(pOldModel, pNewModel); + } +} + + +FASTBOOL SdrObjGroup::HasRefPoint() const +{ + return bRefPoint; +} + + +Point SdrObjGroup::GetRefPoint() const +{ + return aRefPoint; +} + + +void SdrObjGroup::SetRefPoint(const Point& rPnt) +{ + bRefPoint=TRUE; + aRefPoint=rPnt; +} + + +SdrObjList* SdrObjGroup::GetSubList() const +{ + return pSub; +} + +const Rectangle& SdrObjGroup::GetCurrentBoundRect() const +{ + // --> OD 2007-02-01 #144962# + // <aOutRect> has to contain the bounding rectangle + if ( pSub->GetObjCount()!=0 ) + { + const_cast<SdrObjGroup*>(this)->aOutRect = pSub->GetAllObjBoundRect(); + } + + return aOutRect; + // <-- +} + + +const Rectangle& SdrObjGroup::GetSnapRect() const +{ + // --> OD 2007-02-01 #144962# + // <aOutRect> has to contain the bounding rectangle + if ( pSub->GetObjCount()!=0 ) + { + return pSub->GetAllObjSnapRect(); + } + else + { + return aOutRect; + } + // <-- +} + +void SdrObjGroup::operator=(const SdrObject& rObj) +{ + if(rObj.IsGroupObject()) + { + // copy SdrObject stuff + SdrObject::operator=(rObj); + + // #i36404# + // copy SubList, init model and page first + SdrObjList& rSourceSubList = *rObj.GetSubList(); + pSub->SetPage(rSourceSubList.GetPage()); + pSub->SetModel(rSourceSubList.GetModel()); + pSub->CopyObjects(*rObj.GetSubList()); + + // copy local paremeters + nDrehWink =((SdrObjGroup&)rObj).nDrehWink; + nShearWink =((SdrObjGroup&)rObj).nShearWink; + aRefPoint =((SdrObjGroup&)rObj).aRefPoint; + bRefPoint =((SdrObjGroup&)rObj).bRefPoint; + } +} + + +void SdrObjGroup::TakeObjNameSingul(XubString& rName) const +{ + if(!pSub->GetObjCount()) + { + rName = ImpGetResStr(STR_ObjNameSingulGRUPEMPTY); + } + else + { + rName = ImpGetResStr(STR_ObjNameSingulGRUP); + } + + const String aName(GetName()); + + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + + +void SdrObjGroup::TakeObjNamePlural(XubString& rName) const +{ + if (pSub->GetObjCount()==0) { + rName=ImpGetResStr(STR_ObjNamePluralGRUPEMPTY); + } else { + rName=ImpGetResStr(STR_ObjNamePluralGRUP); + } +} + + +void SdrObjGroup::RecalcSnapRect() +{ + // nicht erforderlich, da die Rects von der SubList verwendet werden. +} + +basegfx::B2DPolyPolygon SdrObjGroup::TakeXorPoly() const +{ + basegfx::B2DPolyPolygon aRetval; + const sal_uInt32 nObjCount(pSub->GetObjCount()); + + for(sal_uInt32 a(0L); a < nObjCount; a++) + { + SdrObject* pObj = pSub->GetObj(a); + aRetval.append(pObj->TakeXorPoly()); + } + + if(!aRetval.count()) + { + const basegfx::B2DRange aRange(aOutRect.Left(), aOutRect.Top(), aOutRect.Right(), aOutRect.Bottom()); + aRetval.append(basegfx::tools::createPolygonFromRect(aRange)); + } + + return aRetval; +} + +bool SdrObjGroup::beginSpecialDrag(SdrDragStat& /*rDrag*/) const +{ + return false; +} + + +FASTBOOL SdrObjGroup::BegCreate(SdrDragStat& /*rStat*/) +{ + return FALSE; +} + + +long SdrObjGroup::GetRotateAngle() const +{ + return nDrehWink; +} + + +long SdrObjGroup::GetShearAngle(FASTBOOL /*bVertical*/) const +{ + return nShearWink; +} + + +void SdrObjGroup::NbcSetSnapRect(const Rectangle& rRect) +{ + Rectangle aOld(GetSnapRect()); + long nMulX=rRect.Right()-rRect.Left(); + long nDivX=aOld.Right()-aOld.Left(); + long nMulY=rRect.Bottom()-rRect.Top(); + long nDivY=aOld.Bottom()-aOld.Top(); + if (nDivX==0) { nMulX=1; nDivX=1; } + if (nDivY==0) { nMulY=1; nDivY=1; } + if (nMulX!=nDivX || nMulY!=nDivY) { + Fraction aX(nMulX,nDivX); + Fraction aY(nMulY,nDivY); + NbcResize(aOld.TopLeft(),aX,aY); + } + if (rRect.Left()!=aOld.Left() || rRect.Top()!=aOld.Top()) { + NbcMove(Size(rRect.Left()-aOld.Left(),rRect.Top()-aOld.Top())); + } +} + + +void SdrObjGroup::NbcSetLogicRect(const Rectangle& rRect) +{ + NbcSetSnapRect(rRect); +} + + +void SdrObjGroup::NbcMove(const Size& rSiz) +{ + MovePoint(aRefPoint,rSiz); + if (pSub->GetObjCount()!=0) { + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + pObj->NbcMove(rSiz); + } + } else { + MoveRect(aOutRect,rSiz); + SetRectsDirty(); + } +} + + +void SdrObjGroup::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0); + FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0); + if (bXMirr || bYMirr) { + Point aRef1(GetSnapRect().Center()); + if (bXMirr) { + Point aRef2(aRef1); + aRef2.Y()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + if (bYMirr) { + Point aRef2(aRef1); + aRef2.X()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + } + ResizePoint(aRefPoint,rRef,xFact,yFact); + if (pSub->GetObjCount()!=0) { + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + pObj->NbcResize(rRef,xFact,yFact); + } + } else { + ResizeRect(aOutRect,rRef,xFact,yFact); + SetRectsDirty(); + } +} + + +void SdrObjGroup::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + SetGlueReallyAbsolute(TRUE); + nDrehWink=NormAngle360(nDrehWink+nWink); + RotatePoint(aRefPoint,rRef,sn,cs); + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + pObj->NbcRotate(rRef,nWink,sn,cs); + } + NbcRotateGluePoints(rRef,nWink,sn,cs); + SetGlueReallyAbsolute(FALSE); +} + + +void SdrObjGroup::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + SetGlueReallyAbsolute(TRUE); + MirrorPoint(aRefPoint,rRef1,rRef2); // fehlende Implementation in SvdEtc !!! + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + pObj->NbcMirror(rRef1,rRef2); + } + NbcMirrorGluePoints(rRef1,rRef2); + SetGlueReallyAbsolute(FALSE); +} + + +void SdrObjGroup::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + SetGlueReallyAbsolute(TRUE); + nShearWink+=nWink; + ShearPoint(aRefPoint,rRef,tn); + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + pObj->NbcShear(rRef,nWink,tn,bVShear); + } + NbcShearGluePoints(rRef,nWink,tn,bVShear); + SetGlueReallyAbsolute(FALSE); +} + + +void SdrObjGroup::NbcSetAnchorPos(const Point& rPnt) +{ + aAnchor=rPnt; + Size aSiz(rPnt.X()-aAnchor.X(),rPnt.Y()-aAnchor.Y()); + MovePoint(aRefPoint,aSiz); + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + pObj->NbcSetAnchorPos(rPnt); + } +} + + +void SdrObjGroup::SetSnapRect(const Rectangle& rRect) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + Rectangle aOld(GetSnapRect()); + long nMulX=rRect.Right()-rRect.Left(); + long nDivX=aOld.Right()-aOld.Left(); + long nMulY=rRect.Bottom()-rRect.Top(); + long nDivY=aOld.Bottom()-aOld.Top(); + if (nDivX==0) { nMulX=1; nDivX=1; } + if (nDivY==0) { nMulY=1; nDivY=1; } + if (nMulX!=nDivX || nMulY!=nDivY) { + Fraction aX(nMulX,nDivX); + Fraction aY(nMulY,nDivY); + Resize(aOld.TopLeft(),aX,aY); + } + if (rRect.Left()!=aOld.Left() || rRect.Top()!=aOld.Top()) { + Move(Size(rRect.Left()-aOld.Left(),rRect.Top()-aOld.Top())); + } + + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + + +void SdrObjGroup::SetLogicRect(const Rectangle& rRect) +{ + SetSnapRect(rRect); +} + + +void SdrObjGroup::Move(const Size& rSiz) +{ + if (rSiz.Width()!=0 || rSiz.Height()!=0) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + MovePoint(aRefPoint,rSiz); + if (pSub->GetObjCount()!=0) { + // #32383# Erst die Verbinder verschieben, dann den Rest + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + ULONG i; + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (pObj->IsEdgeObj()) pObj->Move(rSiz); + } + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (!pObj->IsEdgeObj()) pObj->Move(rSiz); + } + } else { + // #110094#-14 SendRepaintBroadcast(); + MoveRect(aOutRect,rSiz); + SetRectsDirty(); + } + + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} + + +void SdrObjGroup::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + if (xFact.GetNumerator()!=xFact.GetDenominator() || yFact.GetNumerator()!=yFact.GetDenominator()) { + FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0); + FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0); + if (bXMirr || bYMirr) { + Point aRef1(GetSnapRect().Center()); + if (bXMirr) { + Point aRef2(aRef1); + aRef2.Y()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + if (bYMirr) { + Point aRef2(aRef1); + aRef2.X()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + } + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + ResizePoint(aRefPoint,rRef,xFact,yFact); + if (pSub->GetObjCount()!=0) { + // #32383# Erst die Verbinder verschieben, dann den Rest + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + ULONG i; + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (pObj->IsEdgeObj()) pObj->Resize(rRef,xFact,yFact); + } + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (!pObj->IsEdgeObj()) pObj->Resize(rRef,xFact,yFact); + } + } else { + // #110094#-14 SendRepaintBroadcast(); + ResizeRect(aOutRect,rRef,xFact,yFact); + SetRectsDirty(); + } + + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + + +void SdrObjGroup::Rotate(const Point& rRef, long nWink, double sn, double cs) +{ + if (nWink!=0) { + SetGlueReallyAbsolute(TRUE); + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + nDrehWink=NormAngle360(nDrehWink+nWink); + RotatePoint(aRefPoint,rRef,sn,cs); + // #32383# Erst die Verbinder verschieben, dann den Rest + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + ULONG i; + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (pObj->IsEdgeObj()) pObj->Rotate(rRef,nWink,sn,cs); + } + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (!pObj->IsEdgeObj()) pObj->Rotate(rRef,nWink,sn,cs); + } + NbcRotateGluePoints(rRef,nWink,sn,cs); + SetGlueReallyAbsolute(FALSE); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + + +void SdrObjGroup::Mirror(const Point& rRef1, const Point& rRef2) +{ + SetGlueReallyAbsolute(TRUE); + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + MirrorPoint(aRefPoint,rRef1,rRef2); // fehlende Implementation in SvdEtc !!! + // #32383# Erst die Verbinder verschieben, dann den Rest + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + ULONG i; + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (pObj->IsEdgeObj()) pObj->Mirror(rRef1,rRef2); + } + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (!pObj->IsEdgeObj()) pObj->Mirror(rRef1,rRef2); + } + NbcMirrorGluePoints(rRef1,rRef2); + SetGlueReallyAbsolute(FALSE); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + + +void SdrObjGroup::Shear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + if (nWink!=0) { + SetGlueReallyAbsolute(TRUE); + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + nShearWink+=nWink; + ShearPoint(aRefPoint,rRef,tn); + // #32383# Erst die Verbinder verschieben, dann den Rest + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + ULONG i; + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (pObj->IsEdgeObj()) pObj->Shear(rRef,nWink,tn,bVShear); + } + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (!pObj->IsEdgeObj()) pObj->Shear(rRef,nWink,tn,bVShear); + } + NbcShearGluePoints(rRef,nWink,tn,bVShear); + SetGlueReallyAbsolute(FALSE); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + + +void SdrObjGroup::SetAnchorPos(const Point& rPnt) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + FASTBOOL bChg=aAnchor!=rPnt; + aAnchor=rPnt; + Size aSiz(rPnt.X()-aAnchor.X(),rPnt.Y()-aAnchor.Y()); + MovePoint(aRefPoint,aSiz); + // #32383# Erst die Verbinder verschieben, dann den Rest + SdrObjList* pOL=pSub; + ULONG nObjAnz=pOL->GetObjCount(); + ULONG i; + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (pObj->IsEdgeObj()) pObj->SetAnchorPos(rPnt); + } + for (i=0; i<nObjAnz; i++) { + SdrObject* pObj=pOL->GetObj(i); + if (!pObj->IsEdgeObj()) pObj->SetAnchorPos(rPnt); + } + if (bChg) { + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} + + + +void SdrObjGroup::NbcSetRelativePos(const Point& rPnt) +{ + Point aRelPos0(GetSnapRect().TopLeft()-aAnchor); + Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y()); + NbcMove(aSiz); // Der ruft auch das SetRectsDirty() +} + +void SdrObjGroup::SetRelativePos(const Point& rPnt) +{ + Point aRelPos0(GetSnapRect().TopLeft()-aAnchor); + Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y()); + if (aSiz.Width()!=0 || aSiz.Height()!=0) Move(aSiz); // Der ruft auch das SetRectsDirty() und Broadcast, ... +} + +void SdrObjGroup::NbcReformatText() +{ + pSub->NbcReformatAllTextObjects(); +} + +void SdrObjGroup::ReformatText() +{ + pSub->ReformatAllTextObjects(); +} + +SdrObject* SdrObjGroup::DoConvertToPolyObj(BOOL bBezier) const +{ + SdrObject* pGroup = new SdrObjGroup; + pGroup->SetModel(GetModel()); + + for(UINT32 a=0;a<pSub->GetObjCount();a++) + { + SdrObject* pIterObj = pSub->GetObj(a); + SdrObject* pResult = pIterObj->DoConvertToPolyObj(bBezier); + + // pResult can be NULL e.g. for empty objects + if( pResult ) + pGroup->GetSubList()->NbcInsertObject(pResult); + } + + return pGroup; +} + +// eof diff --git a/svx/source/svdraw/svdomeas.cxx b/svx/source/svdraw/svdomeas.cxx new file mode 100644 index 000000000000..2bcf016d0e4a --- /dev/null +++ b/svx/source/svdraw/svdomeas.cxx @@ -0,0 +1,1494 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdomeas.hxx> +#include <math.h> +#include "svditext.hxx" // +#include <svx/xpoly.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdhdl.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svddrag.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdattrx.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdview.hxx> +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname +#include <svl/style.hxx> +#include <svl/smplhint.hxx> +#include <editeng/eeitem.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnstcit.hxx> +#include <svx/xlnedcit.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/outliner.hxx> +#include <editeng/editobj.hxx> +#include <editeng/measfld.hxx> +#include <editeng/flditem.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdpage.hxx> +#include <unotools/syslocale.hxx> +#include "svdoimp.hxx" +#include <svx/sdr/properties/measureproperties.hxx> +#include <svx/sdr/contact/viewcontactofsdrmeasureobj.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrMeasureObjGeoData::SdrMeasureObjGeoData() {} +SdrMeasureObjGeoData::~SdrMeasureObjGeoData() {} + +void SdrMeasureObj::TakeRepresentation( XubString& rStr, SdrMeasureFieldKind eMeasureFieldKind ) const +{ + rStr.Erase(); + Fraction aMeasureScale(1, 1); + BOOL bTextRota90(FALSE); + BOOL bShowUnit(FALSE); + FieldUnit eMeasureUnit(FUNIT_NONE); + FieldUnit eModUIUnit(FUNIT_NONE); + + const SfxItemSet& rSet = GetMergedItemSet(); + bTextRota90 = ((SdrMeasureTextRota90Item&)rSet.Get(SDRATTR_MEASURETEXTROTA90)).GetValue(); + eMeasureUnit = ((SdrMeasureUnitItem&)rSet.Get(SDRATTR_MEASUREUNIT)).GetValue(); + aMeasureScale = ((SdrMeasureScaleItem&)rSet.Get(SDRATTR_MEASURESCALE)).GetValue(); + bShowUnit = ((SdrMeasureShowUnitItem&)rSet.Get(SDRATTR_MEASURESHOWUNIT)).GetValue(); + sal_Int16 nNumDigits = ((SdrMeasureDecimalPlacesItem&)rSet.Get(SDRATTR_MEASUREDECIMALPLACES)).GetValue(); + + //SdrModel* pModel = rObj.pModel; + + switch(eMeasureFieldKind) + { + case SDRMEASUREFIELD_VALUE: + { + if(pModel) + { + eModUIUnit = pModel->GetUIUnit(); + + if(eMeasureUnit == FUNIT_NONE) + eMeasureUnit = eModUIUnit; + + INT32 nLen(GetLen(aPt2 - aPt1)); + Fraction aFact(1,1); + + if(eMeasureUnit != eModUIUnit) + { + // Zur Umrechnung der Einheiten + aFact *= GetMapFactor(eModUIUnit, eMeasureUnit).X(); + } + + if(aMeasureScale.GetNumerator() != aMeasureScale.GetDenominator()) + { + aFact *= aMeasureScale; + } + + if(aFact.GetNumerator() != aFact.GetDenominator()) + { + // Scaling ueber BigInt, um Ueberlaeufe zu vermeiden + nLen = BigMulDiv(nLen, aFact.GetNumerator(), aFact.GetDenominator()); + } + + pModel->TakeMetricStr(nLen, rStr, TRUE, nNumDigits); + + if(!aFact.IsValid()) + { + rStr = String(); + rStr += sal_Unicode('?'); + } + + sal_Unicode cDec(SvtSysLocale().GetLocaleData().getNumDecimalSep().GetChar(0)); + + if(rStr.Search(cDec) != STRING_NOTFOUND) + { + xub_StrLen nLen2(rStr.Len() - 1); + + while(rStr.GetChar(nLen2) == sal_Unicode('0')) + { + rStr.Erase(nLen2); + nLen2--; + } + + if(rStr.GetChar(nLen2) == cDec) + { + rStr.Erase(nLen2); + nLen2--; + } + + if(!rStr.Len()) + rStr += sal_Unicode('0'); + } + } + else + { + // falls kein Model da ... (z.B. Preview im Dialog) + rStr = String(); + rStr.AppendAscii("4711"); + } + + break; + } + case SDRMEASUREFIELD_UNIT: + { + if(bShowUnit) + { + if(pModel) + { + eModUIUnit = pModel->GetUIUnit(); + + if(eMeasureUnit == FUNIT_NONE) + eMeasureUnit = eModUIUnit; + + if(bShowUnit) + pModel->TakeUnitStr(eMeasureUnit, rStr); + } + } + + break; + } + case SDRMEASUREFIELD_ROTA90BLANCS: + { + if(bTextRota90) + { + rStr = String(); + rStr += sal_Unicode(' '); + } + + break; + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrMeasureObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::MeasureProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrMeasureObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrMeasureObj(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrMeasureObj,SdrTextObj); + +SdrMeasureObj::SdrMeasureObj(): + bTextDirty(FALSE) +{ + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_False; +} + +SdrMeasureObj::SdrMeasureObj(const Point& rPt1, const Point& rPt2): + aPt1(rPt1), + aPt2(rPt2), + bTextDirty(FALSE) +{ + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_False; +} + +SdrMeasureObj::~SdrMeasureObj() +{ +} + +void SdrMeasureObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bSelectAllowed =TRUE; + rInfo.bMoveAllowed =TRUE; + rInfo.bResizeFreeAllowed=TRUE; + rInfo.bResizePropAllowed=TRUE; + rInfo.bRotateFreeAllowed=TRUE; + rInfo.bRotate90Allowed =TRUE; + rInfo.bMirrorFreeAllowed=TRUE; + rInfo.bMirror45Allowed =TRUE; + rInfo.bMirror90Allowed =TRUE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =TRUE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bNoOrthoDesired =TRUE; + rInfo.bNoContortion =FALSE; + rInfo.bCanConvToPath =FALSE; + rInfo.bCanConvToPoly =TRUE; + rInfo.bCanConvToPathLineToArea=FALSE; + rInfo.bCanConvToPolyLineToArea=FALSE; + rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +UINT16 SdrMeasureObj::GetObjIdentifier() const +{ + return (UINT16)OBJ_MEASURE; +} + +struct ImpMeasureRec : public SdrDragStatUserData +{ + Point aPt1; + Point aPt2; + SdrMeasureKind eKind; + SdrMeasureTextHPos eWantTextHPos; + SdrMeasureTextVPos eWantTextVPos; + long nLineDist; + long nHelplineOverhang; + long nHelplineDist; + long nHelpline1Len; + long nHelpline2Len; + FASTBOOL bBelowRefEdge; + FASTBOOL bTextRota90; + FASTBOOL bTextUpsideDown; + long nMeasureOverhang; + FieldUnit eMeasureUnit; + Fraction aMeasureScale; + FASTBOOL bShowUnit; + String aFormatString; + FASTBOOL bTextAutoAngle; + long nTextAutoAngleView; + FASTBOOL bTextIsFixedAngle; + long nTextFixedAngle; +}; + +struct ImpLineRec +{ + Point aP1; + Point aP2; +}; + +struct ImpMeasurePoly +{ + ImpLineRec aMainline1; // die mit dem 1. Pfeil + ImpLineRec aMainline2; // die mit dem 2. Pfeil + ImpLineRec aMainline3; // die dazwischen + ImpLineRec aHelpline1; + ImpLineRec aHelpline2; + Rectangle aTextRect; + Size aTextSize; + long nLineLen; + long nLineWink; + long nTextWink; + long nHlpWink; + double nLineSin; + double nLineCos; + double nHlpSin; + double nHlpCos; + USHORT nMainlineAnz; + SdrMeasureTextHPos eUsedTextHPos; + SdrMeasureTextVPos eUsedTextVPos; + long nLineWdt2; // Halbe Strichstaerke + long nArrow1Len; // Laenge des 1. Pfeils. Bei Center nur die Haelfte + long nArrow2Len; // Laenge des 2. Pfeils. Bei Center nur die Haelfte + long nArrow1Wdt; // Breite des 1. Pfeils + long nArrow2Wdt; // Breite des 2. Pfeils + long nShortLineLen; // Linienlaenge, wenn PfeileAussen + FASTBOOL bArrow1Center; // Pfeil 1 zentriert? + FASTBOOL bArrow2Center; // Pfeil 2 zentriert? + FASTBOOL bAutoUpsideDown; // UpsideDown durch Automatik + FASTBOOL bPfeileAussen; + FASTBOOL bBreakedLine; +}; + +void SdrMeasureObj::ImpTakeAttr(ImpMeasureRec& rRec) const +{ + rRec.aPt1 = aPt1; + rRec.aPt2 = aPt2; + + const SfxItemSet& rSet = GetObjectItemSet(); + rRec.eKind =((SdrMeasureKindItem& )rSet.Get(SDRATTR_MEASUREKIND )).GetValue(); + rRec.eWantTextHPos =((SdrMeasureTextHPosItem& )rSet.Get(SDRATTR_MEASURETEXTHPOS )).GetValue(); + rRec.eWantTextVPos =((SdrMeasureTextVPosItem& )rSet.Get(SDRATTR_MEASURETEXTVPOS )).GetValue(); + rRec.nLineDist =((SdrMeasureLineDistItem& )rSet.Get(SDRATTR_MEASURELINEDIST )).GetValue(); + rRec.nHelplineOverhang=((SdrMeasureHelplineOverhangItem&)rSet.Get(SDRATTR_MEASUREHELPLINEOVERHANG)).GetValue(); + rRec.nHelplineDist =((SdrMeasureHelplineDistItem& )rSet.Get(SDRATTR_MEASUREHELPLINEDIST )).GetValue(); + rRec.nHelpline1Len =((SdrMeasureHelpline1LenItem& )rSet.Get(SDRATTR_MEASUREHELPLINE1LEN )).GetValue(); + rRec.nHelpline2Len =((SdrMeasureHelpline2LenItem& )rSet.Get(SDRATTR_MEASUREHELPLINE2LEN )).GetValue(); + rRec.bBelowRefEdge =((SdrMeasureBelowRefEdgeItem& )rSet.Get(SDRATTR_MEASUREBELOWREFEDGE )).GetValue(); + rRec.bTextRota90 =((SdrMeasureTextRota90Item& )rSet.Get(SDRATTR_MEASURETEXTROTA90 )).GetValue(); + rRec.bTextUpsideDown =((SdrMeasureTextUpsideDownItem& )rSet.Get(SDRATTR_MEASURETEXTUPSIDEDOWN )).GetValue(); + rRec.nMeasureOverhang =((SdrMeasureOverhangItem& )rSet.Get(SDRATTR_MEASUREOVERHANG )).GetValue(); + rRec.eMeasureUnit =((SdrMeasureUnitItem& )rSet.Get(SDRATTR_MEASUREUNIT )).GetValue(); + rRec.aMeasureScale =((SdrMeasureScaleItem& )rSet.Get(SDRATTR_MEASURESCALE )).GetValue(); + rRec.bShowUnit =((SdrMeasureShowUnitItem& )rSet.Get(SDRATTR_MEASURESHOWUNIT )).GetValue(); + rRec.aFormatString =((SdrMeasureFormatStringItem& )rSet.Get(SDRATTR_MEASUREFORMATSTRING )).GetValue(); + rRec.bTextAutoAngle =((SdrMeasureTextAutoAngleItem& )rSet.Get(SDRATTR_MEASURETEXTAUTOANGLE )).GetValue(); + rRec.nTextAutoAngleView=((SdrMeasureTextAutoAngleViewItem&)rSet.Get(SDRATTR_MEASURETEXTAUTOANGLEVIEW)).GetValue(); + rRec.bTextIsFixedAngle =((SdrMeasureTextIsFixedAngleItem& )rSet.Get(SDRATTR_MEASURETEXTISFIXEDANGLE )).GetValue(); + rRec.nTextFixedAngle =((SdrMeasureTextFixedAngleItem& )rSet.Get(SDRATTR_MEASURETEXTFIXEDANGLE )).GetValue(); +} + +long impGetLineStartEndDistance(const basegfx::B2DPolyPolygon& rPolyPolygon, long nNewWidth, bool bCenter) +{ + const basegfx::B2DRange aPolygonRange(rPolyPolygon.getB2DRange()); + const double fOldWidth(aPolygonRange.getWidth() > 1.0 ? aPolygonRange.getWidth() : 1.0); + const double fScale((double)nNewWidth / fOldWidth); + long nHeight(basegfx::fround(aPolygonRange.getHeight() * fScale)); + + if(bCenter) + { + nHeight /= 2L; + } + + return nHeight; +} + +void SdrMeasureObj::ImpCalcGeometrics(const ImpMeasureRec& rRec, ImpMeasurePoly& rPol) const +{ + Point aP1(rRec.aPt1); + Point aP2(rRec.aPt2); + Point aDelt(aP2); aDelt-=aP1; + + rPol.aTextSize=GetTextSize(); + rPol.nLineLen=GetLen(aDelt); + + rPol.nLineWdt2=0; + long nArrow1Len=0; bool bArrow1Center=false; + long nArrow2Len=0; bool bArrow2Center=false; + long nArrow1Wdt=0; + long nArrow2Wdt=0; + rPol.nArrow1Wdt=0; + rPol.nArrow2Wdt=0; + long nArrowNeed=0; + long nShortLen=0; + FASTBOOL bPfeileAussen=FALSE; + + const SfxItemSet& rSet = GetObjectItemSet(); + sal_Int32 nLineWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue(); // Strichstaerke + rPol.nLineWdt2 = (nLineWdt + 1) / 2; + + nArrow1Wdt = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue(); + if(nArrow1Wdt < 0) + nArrow1Wdt = -nLineWdt * nArrow1Wdt / 100; // <0 = relativ + + nArrow2Wdt = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue(); + if(nArrow2Wdt < 0) + nArrow2Wdt = -nLineWdt * nArrow2Wdt / 100; // <0 = relativ + + basegfx::B2DPolyPolygon aPol1(((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetLineStartValue()); + basegfx::B2DPolyPolygon aPol2(((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetLineEndValue()); + bArrow1Center = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue(); + bArrow2Center = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue(); + nArrow1Len = impGetLineStartEndDistance(aPol1, nArrow1Wdt, bArrow1Center) - 1; + nArrow2Len = impGetLineStartEndDistance(aPol2, nArrow2Wdt, bArrow2Center) - 1; + + // nArrowLen ist bei bCenter bereits halbiert + // Bei 2 Pfeilen a 4mm ist unter 10mm Schluss. + nArrowNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2; + if (rPol.nLineLen<nArrowNeed) bPfeileAussen=TRUE; + nShortLen=(nArrow1Len+nArrow1Wdt + nArrow2Len+nArrow2Wdt) /2; + + rPol.eUsedTextHPos=rRec.eWantTextHPos; + rPol.eUsedTextVPos=rRec.eWantTextVPos; + if (rPol.eUsedTextVPos==SDRMEASURE_TEXTVAUTO) rPol.eUsedTextVPos=SDRMEASURE_ABOVE; + FASTBOOL bBrkLine=rPol.eUsedTextVPos==SDRMEASURETEXT_BREAKEDLINE; + if (rPol.eUsedTextVPos==SDRMEASURETEXT_VERTICALCENTERED) + { + OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject(); + if (pOutlinerParaObject!=NULL && pOutlinerParaObject->GetTextObject().GetParagraphCount()==1) + { + bBrkLine=TRUE; // Unterbrochene Linie, wenn nur 1 Absatz. + } + } + rPol.bBreakedLine=bBrkLine; + if (rPol.eUsedTextHPos==SDRMEASURE_TEXTHAUTO) { // bei zu breitem Text diesen eventuell nach aussen schieben + FASTBOOL bOutside=FALSE; + long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height(); + if (nNeedSiz>rPol.nLineLen) bOutside=TRUE; // Text passt nicht in die Mitte + if (bBrkLine) { + if (nNeedSiz+nArrowNeed>rPol.nLineLen) bPfeileAussen=TRUE; // Text passt in die Mitte, wenn die Pfeile nach aussen kommen + } else { + long nSmallNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2/4; + if (nNeedSiz+nSmallNeed>rPol.nLineLen) bPfeileAussen=TRUE; // Text passt in die Mitte, wenn die Pfeile nach aussen kommen + } + rPol.eUsedTextHPos=bOutside ? SDRMEASURE_TEXTLEFTOUTSIDE : SDRMEASURE_TEXTINSIDE; + } + if (rPol.eUsedTextHPos!=SDRMEASURE_TEXTINSIDE) bPfeileAussen=TRUE; + rPol.nArrow1Wdt=nArrow1Wdt; + rPol.nArrow2Wdt=nArrow2Wdt; + rPol.nShortLineLen=nShortLen; + rPol.bPfeileAussen=bPfeileAussen; + rPol.nArrow1Len=nArrow1Len; + rPol.bArrow1Center=bArrow1Center; + rPol.nArrow2Len=nArrow2Len; + rPol.bArrow2Center=bArrow2Center; + + rPol.nLineWink=GetAngle(aDelt); + double a=rPol.nLineWink*nPi180; + double nLineSin=sin(a); + double nLineCos=cos(a); + rPol.nLineSin=nLineSin; + rPol.nLineCos=nLineCos; + + rPol.nTextWink=rPol.nLineWink; + if (rRec.bTextRota90) rPol.nTextWink+=9000; + + rPol.bAutoUpsideDown=FALSE; + if (rRec.bTextAutoAngle) { + long nTmpWink=NormAngle360(rPol.nTextWink-rRec.nTextAutoAngleView); + if (nTmpWink>=18000) { + rPol.nTextWink+=18000; + rPol.bAutoUpsideDown=TRUE; + } + } + + if (rRec.bTextUpsideDown) rPol.nTextWink+=18000; + rPol.nTextWink=NormAngle360(rPol.nTextWink); + rPol.nHlpWink=rPol.nLineWink+9000; + if (rRec.bBelowRefEdge) rPol.nHlpWink+=18000; + rPol.nHlpWink=NormAngle360(rPol.nHlpWink); + double nHlpSin=nLineCos; + double nHlpCos=-nLineSin; + if (rRec.bBelowRefEdge) { + nHlpSin=-nHlpSin; + nHlpCos=-nHlpCos; + } + rPol.nHlpSin=nHlpSin; + rPol.nHlpCos=nHlpCos; + + long nLineDist=rRec.nLineDist; + long nOverhang=rRec.nHelplineOverhang; + long nHelplineDist=rRec.nHelplineDist; + + long dx= Round(nLineDist*nHlpCos); + long dy=-Round(nLineDist*nHlpSin); + long dxh1a= Round((nHelplineDist-rRec.nHelpline1Len)*nHlpCos); + long dyh1a=-Round((nHelplineDist-rRec.nHelpline1Len)*nHlpSin); + long dxh1b= Round((nHelplineDist-rRec.nHelpline2Len)*nHlpCos); + long dyh1b=-Round((nHelplineDist-rRec.nHelpline2Len)*nHlpSin); + long dxh2= Round((nLineDist+nOverhang)*nHlpCos); + long dyh2=-Round((nLineDist+nOverhang)*nHlpSin); + + // Masshilfslinie 1 + rPol.aHelpline1.aP1=Point(aP1.X()+dxh1a,aP1.Y()+dyh1a); + rPol.aHelpline1.aP2=Point(aP1.X()+dxh2,aP1.Y()+dyh2); + + // Masshilfslinie 2 + rPol.aHelpline2.aP1=Point(aP2.X()+dxh1b,aP2.Y()+dyh1b); + rPol.aHelpline2.aP2=Point(aP2.X()+dxh2,aP2.Y()+dyh2); + + // Masslinie(n) + Point aMainlinePt1(aP1.X()+dx,aP1.Y()+dy); + Point aMainlinePt2(aP2.X()+dx,aP2.Y()+dy); + if (!bPfeileAussen) { + rPol.aMainline1.aP1=aMainlinePt1; + rPol.aMainline1.aP2=aMainlinePt2; + rPol.aMainline2=rPol.aMainline1; + rPol.aMainline3=rPol.aMainline1; + rPol.nMainlineAnz=1; + if (bBrkLine) { + long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height(); + long nHalfLen=(rPol.nLineLen-nNeedSiz-nArrow1Wdt/4-nArrow2Wdt/4) /2; + rPol.nMainlineAnz=2; + rPol.aMainline1.aP2=aMainlinePt1; + rPol.aMainline1.aP2.X()+=nHalfLen; + RotatePoint(rPol.aMainline1.aP2,rPol.aMainline1.aP1,nLineSin,nLineCos); + rPol.aMainline2.aP1=aMainlinePt2; + rPol.aMainline2.aP1.X()-=nHalfLen; + RotatePoint(rPol.aMainline2.aP1,rPol.aMainline2.aP2,nLineSin,nLineCos); + } + } else { + long nLen1=nShortLen; // Pfeilbreite als Linienlaenge ausserhalb des Pfeils + long nLen2=nShortLen; + long nTextWdt=rRec.bTextRota90 ? rPol.aTextSize.Height() : rPol.aTextSize.Width(); + if (!bBrkLine) { + if (rPol.eUsedTextHPos==SDRMEASURE_TEXTLEFTOUTSIDE) nLen1=nArrow1Len+nTextWdt; + if (rPol.eUsedTextHPos==SDRMEASURE_TEXTRIGHTOUTSIDE) nLen2=nArrow2Len+nTextWdt; + } + rPol.aMainline1.aP1=aMainlinePt1; + rPol.aMainline1.aP2=aMainlinePt1; rPol.aMainline1.aP2.X()-=nLen1; RotatePoint(rPol.aMainline1.aP2,aMainlinePt1,nLineSin,nLineCos); + rPol.aMainline2.aP1=aMainlinePt2; rPol.aMainline2.aP1.X()+=nLen2; RotatePoint(rPol.aMainline2.aP1,aMainlinePt2,nLineSin,nLineCos); + rPol.aMainline2.aP2=aMainlinePt2; + rPol.aMainline3.aP1=aMainlinePt1; + rPol.aMainline3.aP2=aMainlinePt2; + rPol.nMainlineAnz=3; + if (bBrkLine && rPol.eUsedTextHPos==SDRMEASURE_TEXTINSIDE) rPol.nMainlineAnz=2; + } +} + +basegfx::B2DPolyPolygon SdrMeasureObj::ImpCalcXPoly(const ImpMeasurePoly& rPol) const +{ + basegfx::B2DPolyPolygon aRetval; + basegfx::B2DPolygon aPartPolyA; + aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP1.X(), rPol.aMainline1.aP1.Y())); + aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP2.X(), rPol.aMainline1.aP2.Y())); + aRetval.append(aPartPolyA); + + if(rPol.nMainlineAnz > 1) + { + aPartPolyA.clear(); + aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP1.X(), rPol.aMainline2.aP1.Y())); + aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP2.X(), rPol.aMainline2.aP2.Y())); + aRetval.append(aPartPolyA); + } + + if(rPol.nMainlineAnz > 2) + { + aPartPolyA.clear(); + aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP1.X(), rPol.aMainline3.aP1.Y())); + aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP2.X(), rPol.aMainline3.aP2.Y())); + aRetval.append(aPartPolyA); + } + + aPartPolyA.clear(); + aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP1.X(), rPol.aHelpline1.aP1.Y())); + aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP2.X(), rPol.aHelpline1.aP2.Y())); + aRetval.append(aPartPolyA); + + aPartPolyA.clear(); + aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP1.X(), rPol.aHelpline2.aP1.Y())); + aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP2.X(), rPol.aHelpline2.aP2.Y())); + aRetval.append(aPartPolyA); + + return aRetval; +} + +FASTBOOL SdrMeasureObj::CalcFieldValue(const SvxFieldItem& rField, USHORT nPara, USHORT nPos, + FASTBOOL bEdit, + Color*& rpTxtColor, Color*& rpFldColor, XubString& rRet) const +{ + const SvxFieldData* pField=rField.GetField(); + SdrMeasureField* pMeasureField=PTR_CAST(SdrMeasureField,pField); + if (pMeasureField!=NULL) { + TakeRepresentation(rRet, pMeasureField->GetMeasureFieldKind()); + if (rpFldColor!=NULL) { + if (!bEdit) + { + delete rpFldColor; + rpFldColor=NULL; + } + } + return TRUE; + } else { + return SdrTextObj::CalcFieldValue(rField,nPara,nPos,bEdit,rpTxtColor,rpFldColor,rRet); + } +} + +void SdrMeasureObj::UndirtyText() const +{ + if (bTextDirty) + { + SdrOutliner& rOutliner=ImpGetDrawOutliner(); + OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject(); + if(pOutlinerParaObject==NULL) + { + rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS), EE_FEATURE_FIELD), ESelection(0,0)); + rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_VALUE), EE_FEATURE_FIELD),ESelection(0,1)); + rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_UNIT), EE_FEATURE_FIELD),ESelection(0,2)); + rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS), EE_FEATURE_FIELD),ESelection(0,3)); + + if(GetStyleSheet()) + rOutliner.SetStyleSheet(0, GetStyleSheet()); + + rOutliner.SetParaAttribs(0, GetObjectItemSet()); + + // casting auf nonconst + const_cast<SdrMeasureObj*>(this)->NbcSetOutlinerParaObject( rOutliner.CreateParaObject() ); + } + else + { + rOutliner.SetText(*pOutlinerParaObject); + } + + rOutliner.SetUpdateMode(TRUE); + rOutliner.UpdateFields(); + Size aSiz(rOutliner.CalcTextSize()); + rOutliner.Clear(); + // 3x casting auf nonconst + ((SdrMeasureObj*)this)->aTextSize=aSiz; + ((SdrMeasureObj*)this)->bTextSizeDirty=FALSE; + ((SdrMeasureObj*)this)->bTextDirty=FALSE; + } +} + +void SdrMeasureObj::TakeUnrotatedSnapRect(Rectangle& rRect) const +{ + if (bTextDirty) UndirtyText(); + ImpMeasureRec aRec; + ImpMeasurePoly aMPol; + ImpTakeAttr(aRec); + ImpCalcGeometrics(aRec,aMPol); + + // TextSize ermitteln inkl. Textrahmenabstaende + Size aTextSize2(aMPol.aTextSize); + if (aTextSize2.Width()<1) aTextSize2.Width()=1; + if (aTextSize2.Height()<1) aTextSize2.Height()=1; + aTextSize2.Width()+=GetTextLeftDistance()+GetTextRightDistance(); + aTextSize2.Height()+=GetTextUpperDistance()+GetTextLowerDistance(); + + Point aPt1b(aMPol.aMainline1.aP1); + long nLen=aMPol.nLineLen; + long nLWdt=aMPol.nLineWdt2; + long nArr1Len=aMPol.nArrow1Len; + long nArr2Len=aMPol.nArrow2Len; + if (aMPol.bBreakedLine) { + // Bei Unterbrochener Linie und Outside muss der Text nicht neben den + // Pfeil sondern neben die Linie an dem Pfeil plaziert werden + nArr1Len=aMPol.nShortLineLen+aMPol.nArrow1Wdt/4; + nArr2Len=aMPol.nShortLineLen+aMPol.nArrow2Wdt/4; + } + + Point aTextPos; + FASTBOOL bRota90=aRec.bTextRota90; + FASTBOOL bUpsideDown=aRec.bTextUpsideDown!=aMPol.bAutoUpsideDown; + FASTBOOL bBelowRefEdge=aRec.bBelowRefEdge; + SdrMeasureTextHPos eMH=aMPol.eUsedTextHPos; + SdrMeasureTextVPos eMV=aMPol.eUsedTextVPos; + if (!bRota90) { + switch (eMH) { + case SDRMEASURE_TEXTLEFTOUTSIDE: aTextPos.X()=aPt1b.X()-aTextSize2.Width()-nArr1Len-nLWdt; break; + case SDRMEASURE_TEXTRIGHTOUTSIDE: aTextPos.X()=aPt1b.X()+nLen+nArr2Len+nLWdt; break; + default: aTextPos.X()=aPt1b.X(); aTextSize2.Width()=nLen; + } + switch (eMV) { + case SDRMEASURETEXT_VERTICALCENTERED: + case SDRMEASURETEXT_BREAKEDLINE: aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()/2; break; + case SDRMEASURE_BELOW: { + if (!bUpsideDown) aTextPos.Y()=aPt1b.Y()+nLWdt; + else aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()-nLWdt; + } break; + default: { + if (!bUpsideDown) aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()-nLWdt; + else aTextPos.Y()=aPt1b.Y()+nLWdt; + } + } + if (bUpsideDown) { + aTextPos.X()+=aTextSize2.Width(); + aTextPos.Y()+=aTextSize2.Height(); + } + } else { // also wenn bTextRota90==TRUE + switch (eMH) { + case SDRMEASURE_TEXTLEFTOUTSIDE: aTextPos.X()=aPt1b.X()-aTextSize2.Height()-nArr1Len; break; + case SDRMEASURE_TEXTRIGHTOUTSIDE: aTextPos.X()=aPt1b.X()+nLen+nArr2Len; break; + default: aTextPos.X()=aPt1b.X(); aTextSize2.Height()=nLen; + } + switch (eMV) { + case SDRMEASURETEXT_VERTICALCENTERED: + case SDRMEASURETEXT_BREAKEDLINE: aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()/2; break; + case SDRMEASURE_BELOW: { + if (!bBelowRefEdge) aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()+nLWdt; + else aTextPos.Y()=aPt1b.Y()-nLWdt; + } break; + default: { + if (!bBelowRefEdge) aTextPos.Y()=aPt1b.Y()-nLWdt; + else aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()+nLWdt; + } + } + if (bUpsideDown) { + aTextPos.X()+=aTextSize2.Height(); + aTextPos.Y()-=aTextSize2.Width(); + } + } + if (aMPol.nTextWink!=aGeo.nDrehWink) { + ((SdrMeasureObj*)this)->aGeo.nDrehWink=aMPol.nTextWink; + ((SdrMeasureObj*)this)->aGeo.RecalcSinCos(); + } + RotatePoint(aTextPos,aPt1b,aMPol.nLineSin,aMPol.nLineCos); + aTextSize2.Width()++; aTextSize2.Height()++; // wg. des komischen Verhaltens beim Rect-Ctor + rRect=Rectangle(aTextPos,aTextSize2); + rRect.Justify(); + ((SdrMeasureObj*)this)->aRect=rRect; + + if (aMPol.nTextWink!=aGeo.nDrehWink) { + ((SdrMeasureObj*)this)->aGeo.nDrehWink=aMPol.nTextWink; + ((SdrMeasureObj*)this)->aGeo.RecalcSinCos(); + } +} + +void SdrMeasureObj::operator=(const SdrObject& rObj) +{ + SdrTextObj::operator=(rObj); + aPt1=((SdrMeasureObj&)rObj).aPt1; + aPt2=((SdrMeasureObj&)rObj).aPt2; + bTextDirty=((SdrMeasureObj&)rObj).bTextDirty; +} + +void SdrMeasureObj::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulMEASURE); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrMeasureObj::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralMEASURE); +} + +basegfx::B2DPolyPolygon SdrMeasureObj::TakeXorPoly() const +{ + ImpMeasureRec aRec; + ImpMeasurePoly aMPol; + ImpTakeAttr(aRec); + ImpCalcGeometrics(aRec,aMPol); + return ImpCalcXPoly(aMPol); +} + +sal_uInt32 SdrMeasureObj::GetHdlCount() const +{ + return 6L; +} + +SdrHdl* SdrMeasureObj::GetHdl(sal_uInt32 nHdlNum) const +{ + ImpMeasureRec aRec; + ImpMeasurePoly aMPol; + ImpTakeAttr(aRec); + aRec.nHelplineDist=0; + ImpCalcGeometrics(aRec,aMPol); + Point aPt; + //SdrHdlKind eHdl=HDL_POLY; + switch (nHdlNum) { + case 0: aPt=aMPol.aHelpline1.aP1; break; + case 1: aPt=aMPol.aHelpline2.aP1; break; + case 2: aPt=aPt1; break; + case 3: aPt=aPt2; break; + case 4: aPt=aMPol.aHelpline1.aP2; break; + case 5: aPt=aMPol.aHelpline2.aP2; break; + } // switch + SdrHdl* pHdl=new ImpMeasureHdl(aPt,HDL_USER); + pHdl->SetObjHdlNum(nHdlNum); + pHdl->SetDrehWink(aMPol.nLineWink); + return pHdl; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrMeasureObj::hasSpecialDrag() const +{ + return true; +} + +bool SdrMeasureObj::beginSpecialDrag(SdrDragStat& rDrag) const +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + + if(pHdl) + { + const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); + + if(nHdlNum != 2 && nHdlNum != 3) + { + rDrag.SetEndDragChangesAttributes(true); + } + + return true; + } + + return false; +} + +bool SdrMeasureObj::applySpecialDrag(SdrDragStat& rDrag) +{ + ImpMeasureRec aMeasureRec; + const SdrHdl* pHdl = rDrag.GetHdl(); + const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); + + ImpTakeAttr(aMeasureRec); + ImpEvalDrag(aMeasureRec, rDrag); + + switch (nHdlNum) + { + case 2: + { + aPt1 = aMeasureRec.aPt1; + SetTextDirty(); + break; + } + case 3: + { + aPt2 = aMeasureRec.aPt2; + SetTextDirty(); + break; + } + default: + { + switch(nHdlNum) + { + case 0: + case 1: + { + ImpMeasureRec aOrigMeasureRec; + ImpTakeAttr(aOrigMeasureRec); + + if(aMeasureRec.nHelpline1Len != aOrigMeasureRec.nHelpline1Len) + { + SetObjectItem(SdrMeasureHelpline1LenItem(aMeasureRec.nHelpline1Len)); + } + + if(aMeasureRec.nHelpline2Len != aOrigMeasureRec.nHelpline2Len) + { + SetObjectItem(SdrMeasureHelpline2LenItem(aMeasureRec.nHelpline2Len)); + } + + break; + } + + case 4: + case 5: + { + ImpMeasureRec aOrigMeasureRec; + ImpTakeAttr(aOrigMeasureRec); + + if(aMeasureRec.nLineDist != aOrigMeasureRec.nLineDist) + { + SetObjectItem(SdrMeasureLineDistItem(aMeasureRec.nLineDist)); + } + + if(aMeasureRec.bBelowRefEdge != aOrigMeasureRec.bBelowRefEdge) + { + SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec.bBelowRefEdge)); + } + } + } + } + } // switch + + SetRectsDirty(); + SetChanged(); + + return true; +} + +String SdrMeasureObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const +{ + XubString aStr; + return aStr; +} + +void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec& rRec, const SdrDragStat& rDrag) const +{ + long nLineWink=GetAngle(rRec.aPt2-rRec.aPt1); + double a=nLineWink*nPi180; + double nSin=sin(a); + double nCos=cos(a); + + const SdrHdl* pHdl=rDrag.GetHdl(); + sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); + FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho(); + FASTBOOL bBigOrtho=bOrtho && rDrag.GetView()->IsBigOrtho(); + FASTBOOL bBelow=rRec.bBelowRefEdge; + Point aPt(rDrag.GetNow()); + + switch (nHdlNum) { + case 0: { + RotatePoint(aPt,aPt1,nSin,-nCos); + rRec.nHelpline1Len=aPt1.Y()-aPt.Y(); + if (bBelow) rRec.nHelpline1Len=-rRec.nHelpline1Len; + if (bOrtho) rRec.nHelpline2Len=rRec.nHelpline1Len; + } break; + case 1: { + RotatePoint(aPt,aPt2,nSin,-nCos); + rRec.nHelpline2Len=aPt2.Y()-aPt.Y(); + if (bBelow) rRec.nHelpline2Len=-rRec.nHelpline2Len; + if (bOrtho) rRec.nHelpline1Len=rRec.nHelpline2Len; + } break; + case 2: case 3: { + FASTBOOL bAnf=nHdlNum==2; + Point& rMov=bAnf ? rRec.aPt1 : rRec.aPt2; + Point aMov(rMov); + Point aFix(bAnf ? rRec.aPt2 : rRec.aPt1); + if (bOrtho) { + long ndx0=aMov.X()-aFix.X(); + long ndy0=aMov.Y()-aFix.Y(); + FASTBOOL bHLin=ndy0==0; + FASTBOOL bVLin=ndx0==0; + if (!bHLin || !bVLin) { // sonst ist aPt1==aPt2 + long ndx=aPt.X()-aFix.X(); + long ndy=aPt.Y()-aFix.Y(); + double nXFact=0; if (!bVLin) nXFact=(double)ndx/(double)ndx0; + double nYFact=0; if (!bHLin) nYFact=(double)ndy/(double)ndy0; + FASTBOOL bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho); + FASTBOOL bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho); + if (bHor) ndy=long(ndy0*nXFact); + if (bVer) ndx=long(ndx0*nYFact); + aPt=aFix; + aPt.X()+=ndx; + aPt.Y()+=ndy; + } // else Ortho8 + } + rMov=aPt; + } break; + case 4: case 5: { + long nVal0=rRec.nLineDist; + RotatePoint(aPt,(nHdlNum==4 ? aPt1 : aPt2),nSin,-nCos); + rRec.nLineDist=aPt.Y()- (nHdlNum==4 ? aPt1.Y() : aPt2.Y()); + if (bBelow) rRec.nLineDist=-rRec.nLineDist; + if (rRec.nLineDist<0) { + rRec.nLineDist=-rRec.nLineDist; + rRec.bBelowRefEdge=!bBelow; + } + rRec.nLineDist-=rRec.nHelplineOverhang; + if (bOrtho) rRec.nLineDist=nVal0; + } break; + } // switch +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrMeasureObj::BegCreate(SdrDragStat& rStat) +{ + rStat.SetOrtho8Possible(); + aPt1=rStat.GetStart(); + aPt2=rStat.GetNow(); + SetTextDirty(); + return TRUE; +} + +FASTBOOL SdrMeasureObj::MovCreate(SdrDragStat& rStat) +{ + SdrView* pView=rStat.GetView(); + aPt1=rStat.GetStart(); + aPt2=rStat.GetNow(); + if (pView!=NULL && pView->IsCreate1stPointAsCenter()) { + aPt1+=aPt1; + aPt1-=rStat.Now(); + } + SetTextDirty(); + SetBoundRectDirty(); + bSnapRectDirty=TRUE; + return TRUE; +} + +FASTBOOL SdrMeasureObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + SetTextDirty(); + SetRectsDirty(); + return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); +} + +FASTBOOL SdrMeasureObj::BckCreate(SdrDragStat& /*rStat*/) +{ + return FALSE; +} + +void SdrMeasureObj::BrkCreate(SdrDragStat& /*rStat*/) +{ +} + +basegfx::B2DPolyPolygon SdrMeasureObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const +{ + ImpMeasureRec aRec; + ImpMeasurePoly aMPol; + + ImpTakeAttr(aRec); + ImpCalcGeometrics(aRec, aMPol); + + return ImpCalcXPoly(aMPol); +} + +Pointer SdrMeasureObj::GetCreatePointer() const +{ + return Pointer(POINTER_CROSS); +} + +void SdrMeasureObj::NbcMove(const Size& rSiz) +{ + SdrTextObj::NbcMove(rSiz); + MovePoint(aPt1,rSiz); + MovePoint(aPt2,rSiz); +} + +void SdrMeasureObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + SdrTextObj::NbcResize(rRef,xFact,yFact); + ResizePoint(aPt1,rRef,xFact,yFact); + ResizePoint(aPt2,rRef,xFact,yFact); + SetTextDirty(); +} + +void SdrMeasureObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + SdrTextObj::NbcRotate(rRef,nWink,sn,cs); + long nLen0=GetLen(aPt2-aPt1); + RotatePoint(aPt1,rRef,sn,cs); + RotatePoint(aPt2,rRef,sn,cs); + long nLen1=GetLen(aPt2-aPt1); + if (nLen1!=nLen0) { // Aha, Rundungsfehler + long dx=aPt2.X()-aPt1.X(); + long dy=aPt2.Y()-aPt1.Y(); + dx=BigMulDiv(dx,nLen0,nLen1); + dy=BigMulDiv(dy,nLen0,nLen1); + if (rRef==aPt2) { + aPt1.X()=aPt2.X()-dx; + aPt1.Y()=aPt2.Y()-dy; + } else { + aPt2.X()=aPt1.X()+dx; + aPt2.Y()=aPt1.Y()+dy; + } + } + SetRectsDirty(); +} + +void SdrMeasureObj::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + SdrTextObj::NbcMirror(rRef1,rRef2); + MirrorPoint(aPt1,rRef1,rRef2); + MirrorPoint(aPt2,rRef1,rRef2); + SetRectsDirty(); +} + +void SdrMeasureObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + SdrTextObj::NbcShear(rRef,nWink,tn,bVShear); + ShearPoint(aPt1,rRef,tn,bVShear); + ShearPoint(aPt2,rRef,tn,bVShear); + SetRectsDirty(); + SetTextDirty(); +} + +long SdrMeasureObj::GetRotateAngle() const +{ + return GetAngle(aPt2-aPt1); +} + +void SdrMeasureObj::RecalcSnapRect() +{ + // #94520# Added correct implementation here. + ImpMeasureRec aRec; + ImpMeasurePoly aMPol; + XPolyPolygon aXPP; + + ImpTakeAttr(aRec); + ImpCalcGeometrics(aRec, aMPol); + aXPP = XPolyPolygon(ImpCalcXPoly(aMPol)); + maSnapRect = aXPP.GetBoundRect(); +} + +sal_uInt32 SdrMeasureObj::GetSnapPointCount() const +{ + return 2L; +} + +Point SdrMeasureObj::GetSnapPoint(sal_uInt32 i) const +{ + if (i==0) return aPt1; + else return aPt2; +} + +sal_Bool SdrMeasureObj::IsPolyObj() const +{ + return sal_True; +} + +sal_uInt32 SdrMeasureObj::GetPointCount() const +{ + return 2L; +} + +Point SdrMeasureObj::GetPoint(sal_uInt32 i) const +{ + return (0L == i) ? aPt1 : aPt2; +} + +void SdrMeasureObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i) +{ + if (0L == i) + aPt1=rPnt; + if (1L == i) + aPt2=rPnt; + SetRectsDirty(); + SetTextDirty(); +} + +SdrObjGeoData* SdrMeasureObj::NewGeoData() const +{ + return new SdrMeasureObjGeoData; +} + +void SdrMeasureObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrTextObj::SaveGeoData(rGeo); + SdrMeasureObjGeoData& rMGeo=(SdrMeasureObjGeoData&)rGeo; + rMGeo.aPt1=aPt1; + rMGeo.aPt2=aPt2; +} + +void SdrMeasureObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrTextObj::RestGeoData(rGeo); + SdrMeasureObjGeoData& rMGeo=(SdrMeasureObjGeoData&)rGeo; + aPt1=rMGeo.aPt1; + aPt2=rMGeo.aPt2; + SetTextDirty(); +} + +SdrObject* SdrMeasureObj::DoConvertToPolyObj(BOOL bBezier) const +{ + // get XOR Poly as base + XPolyPolygon aTmpPolyPolygon(TakeXorPoly()); + + // get local ItemSet and StyleSheet + SfxItemSet aSet(GetObjectItemSet()); + SfxStyleSheet* pStyleSheet = GetStyleSheet(); + + // prepare group + SdrObjGroup* pGroup = new SdrObjGroup; + pGroup->SetModel(GetModel()); + + // prepare parameters + basegfx::B2DPolyPolygon aPolyPoly; + SdrPathObj* pPath; + UINT16 nCount(aTmpPolyPolygon.Count()); + UINT16 nLoopStart(0); + + if(nCount == 3) + { + // three lines, first one is the middle one + aPolyPoly.clear(); + aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); + + pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); + pPath->SetModel(GetModel()); + pPath->SetMergedItemSet(aSet); + pPath->SetStyleSheet(pStyleSheet, true); + pGroup->GetSubList()->NbcInsertObject(pPath); + aSet.Put(XLineStartWidthItem(0L)); + aSet.Put(XLineEndWidthItem(0L)); + nLoopStart = 1; + } + else if(nCount == 4) + { + // four lines, middle line with gap, so there are two lines used + // which have one arrow each + //INT32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue(); + INT32 nEndWidth = ((const XLineEndWidthItem&)(aSet.Get(XATTR_LINEENDWIDTH))).GetValue(); + aSet.Put(XLineEndWidthItem(0L)); + + aPolyPoly.clear(); + aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); + pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); + pPath->SetModel(GetModel()); + pPath->SetMergedItemSet(aSet); + pPath->SetStyleSheet(pStyleSheet, true); + + pGroup->GetSubList()->NbcInsertObject(pPath); + + aSet.Put(XLineEndWidthItem(nEndWidth)); + aSet.Put(XLineStartWidthItem(0L)); + + aPolyPoly.clear(); + aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon()); + pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); + pPath->SetModel(GetModel()); + pPath->SetMergedItemSet(aSet); + pPath->SetStyleSheet(pStyleSheet, true); + + pGroup->GetSubList()->NbcInsertObject(pPath); + + aSet.Put(XLineEndWidthItem(0L)); + nLoopStart = 2; + } + else if(nCount == 5) + { + // five lines, first two are the outer ones + //INT32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue(); + INT32 nEndWidth = ((const XLineEndWidthItem&)(aSet.Get(XATTR_LINEENDWIDTH))).GetValue(); + + aSet.Put(XLineEndWidthItem(0L)); + + aPolyPoly.clear(); + aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); + pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); + pPath->SetModel(GetModel()); + pPath->SetMergedItemSet(aSet); + pPath->SetStyleSheet(pStyleSheet, true); + + pGroup->GetSubList()->NbcInsertObject(pPath); + + aSet.Put(XLineEndWidthItem(nEndWidth)); + aSet.Put(XLineStartWidthItem(0L)); + + aPolyPoly.clear(); + aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon()); + pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); + pPath->SetModel(GetModel()); + pPath->SetMergedItemSet(aSet); + pPath->SetStyleSheet(pStyleSheet, true); + + pGroup->GetSubList()->NbcInsertObject(pPath); + + aSet.Put(XLineEndWidthItem(0L)); + nLoopStart = 2; + } + + for(;nLoopStart<nCount;nLoopStart++) + { + aPolyPoly.clear(); + aPolyPoly.append(aTmpPolyPolygon[nLoopStart].getB2DPolygon()); + pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); + pPath->SetModel(GetModel()); + pPath->SetMergedItemSet(aSet); + pPath->SetStyleSheet(pStyleSheet, true); + + pGroup->GetSubList()->NbcInsertObject(pPath); + } + + return ImpConvertAddText(pGroup, bBezier); +} + +sal_Bool SdrMeasureObj::BegTextEdit(SdrOutliner& rOutl) +{ + UndirtyText(); + return SdrTextObj::BegTextEdit(rOutl); +} + +const Size& SdrMeasureObj::GetTextSize() const +{ + if (bTextDirty) UndirtyText(); + return SdrTextObj::GetTextSize(); +} + +OutlinerParaObject* SdrMeasureObj::GetOutlinerParaObject() const +{ + if(bTextDirty) + UndirtyText(); + return SdrTextObj::GetOutlinerParaObject(); +} + +void SdrMeasureObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject) +{ + SdrTextObj::NbcSetOutlinerParaObject(pTextObject); + if(SdrTextObj::GetOutlinerParaObject()) + SetTextDirty(); // Text neu berechnen! +} + +void SdrMeasureObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, + Rectangle* pAnchorRect, BOOL bLineWidth ) const +{ + if (bTextDirty) UndirtyText(); + SdrTextObj::TakeTextRect( rOutliner, rTextRect, bNoEditText, pAnchorRect, bLineWidth ); +} + +void SdrMeasureObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const +{ + if (bTextDirty) UndirtyText(); + SdrTextObj::TakeTextAnchorRect(rAnchorRect); +} + +void SdrMeasureObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const +{ + if (bTextDirty) UndirtyText(); + SdrTextObj::TakeTextEditArea(pPaperMin,pPaperMax,pViewInit,pViewMin); +} + +USHORT SdrMeasureObj::GetOutlinerViewAnchorMode() const +{ + if (bTextDirty) UndirtyText(); + ImpMeasureRec aRec; + ImpMeasurePoly aMPol; + ImpTakeAttr(aRec); + ImpCalcGeometrics(aRec,aMPol); + + SdrTextHorzAdjust eTH=GetTextHorizontalAdjust(); + SdrTextVertAdjust eTV=GetTextVerticalAdjust(); + SdrMeasureTextHPos eMH=aMPol.eUsedTextHPos; + SdrMeasureTextVPos eMV=aMPol.eUsedTextVPos; + FASTBOOL bTextRota90=aRec.bTextRota90; + //FASTBOOL bTextUpsideDown=aRec.bTextUpsideDown; + FASTBOOL bBelowRefEdge=aRec.bBelowRefEdge; + + // bTextUpsideDown muss hier noch ausgewertet werden!!!! + if (!bTextRota90) { + if (eMH==SDRMEASURE_TEXTLEFTOUTSIDE) eTH=SDRTEXTHORZADJUST_RIGHT; + if (eMH==SDRMEASURE_TEXTRIGHTOUTSIDE) eTH=SDRTEXTHORZADJUST_LEFT; + // bei eMH==SDRMEASURE_TEXTINSIDE kann horizontal geankert werden. + if (eMV==SDRMEASURE_ABOVE) eTV=SDRTEXTVERTADJUST_BOTTOM; + if (eMV==SDRMEASURE_BELOW) eTV=SDRTEXTVERTADJUST_TOP; + if (eMV==SDRMEASURETEXT_BREAKEDLINE || eMV==SDRMEASURETEXT_VERTICALCENTERED) eTV=SDRTEXTVERTADJUST_CENTER; + } else { + if (eMH==SDRMEASURE_TEXTLEFTOUTSIDE) eTV=SDRTEXTVERTADJUST_BOTTOM; + if (eMH==SDRMEASURE_TEXTRIGHTOUTSIDE) eTV=SDRTEXTVERTADJUST_TOP; + // bei eMH==SDRMEASURE_TEXTINSIDE kann vertikal geankert werden. + if (!bBelowRefEdge) { + if (eMV==SDRMEASURE_ABOVE) eTH=SDRTEXTHORZADJUST_LEFT; + if (eMV==SDRMEASURE_BELOW) eTH=SDRTEXTHORZADJUST_RIGHT; + } else { + if (eMV==SDRMEASURE_ABOVE) eTH=SDRTEXTHORZADJUST_RIGHT; + if (eMV==SDRMEASURE_BELOW) eTH=SDRTEXTHORZADJUST_LEFT; + } + if (eMV==SDRMEASURETEXT_BREAKEDLINE || eMV==SDRMEASURETEXT_VERTICALCENTERED) eTH=SDRTEXTHORZADJUST_CENTER; + } + + EVAnchorMode eRet=ANCHOR_BOTTOM_HCENTER; + if (eTH==SDRTEXTHORZADJUST_LEFT) { + if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_LEFT; + else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_LEFT; + else eRet=ANCHOR_VCENTER_LEFT; + } else if (eTH==SDRTEXTHORZADJUST_RIGHT) { + if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_RIGHT; + else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_RIGHT; + else eRet=ANCHOR_VCENTER_RIGHT; + } else { + if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_HCENTER; + else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_HCENTER; + else eRet=ANCHOR_VCENTER_HCENTER; + } + return (USHORT)eRet; +} + +////////////////////////////////////////////////////////////////////////////// +// #i97878# +// TRGetBaseGeometry/TRSetBaseGeometry needs to be based on two positions, +// same as line geometry in SdrPathObj. Thus needs to be overloaded and +// implemented since currently it is derived from SdrTextObj which uses +// a functionality based on SnapRect which is not useful here + +inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } +inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } + +sal_Bool SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const +{ + // handle the same as a simple line since the definition is based on two points + const basegfx::B2DRange aRange(aPt1.X(), aPt1.Y(), aPt2.X(), aPt2.Y()); + basegfx::B2DTuple aScale(aRange.getRange()); + basegfx::B2DTuple aTranslate(aRange.getMinimum()); + + // position maybe relative to anchorpos, convert + if( pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // force MapUnit to 100th mm + SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // postion + aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); + aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); + + // size + aScale.setX(ImplTwipsToMM(aScale.getX())); + aScale.setY(ImplTwipsToMM(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); + } + } + } + + // build return value matrix + rMatrix = basegfx::tools::createScaleTranslateB2DHomMatrix(aScale, aTranslate); + + return sal_True; +} + +void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) +{ + // use given transformation to derive the two defining points from unit line + basegfx::B2DPoint aPosA(rMatrix * basegfx::B2DPoint(0.0, 0.0)); + basegfx::B2DPoint aPosB(rMatrix * basegfx::B2DPoint(1.0, 0.0)); + + // force metric to pool metric + SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // position + aPosA.setX(ImplMMToTwips(aPosA.getX())); + aPosA.setY(ImplMMToTwips(aPosA.getY())); + aPosB.setX(ImplMMToTwips(aPosB.getX())); + aPosB.setY(ImplMMToTwips(aPosB.getY())); + + break; + } + default: + { + DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); + } + } + } + + if( pModel->IsWriter() ) + { + // if anchor is used, make position relative to it + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + const basegfx::B2DVector aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y()); + + aPosA += aAnchorOffset; + aPosB += aAnchorOffset; + } + } + + // derive new model data + const Point aNewPt1(basegfx::fround(aPosA.getX()), basegfx::fround(aPosA.getY())); + const Point aNewPt2(basegfx::fround(aPosB.getX()), basegfx::fround(aPosB.getY())); + + if(aNewPt1 != aPt1 || aNewPt2 != aPt2) + { + // set model values and broadcast + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + + aPt1 = aNewPt1; + aPt2 = aNewPt2; + + SetTextDirty(); + ActionChanged(); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdomedia.cxx b/svx/source/svdraw/svdomedia.cxx new file mode 100644 index 000000000000..9dd615490f9e --- /dev/null +++ b/svx/source/svdraw/svdomedia.cxx @@ -0,0 +1,285 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <vcl/svapp.hxx> + +#include <svx/svdomedia.hxx> +#include "svdglob.hxx" +#include "svdstr.hrc" +#include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx> +#include <avmedia/mediawindow.hxx> + +// --------------- +// - SdrMediaObj - +// --------------- + +TYPEINIT1( SdrMediaObj, SdrRectObj ); + +// ------------------------------------------------------------------------------ + +SdrMediaObj::SdrMediaObj() +{ +} + +// ------------------------------------------------------------------------------ + +SdrMediaObj::SdrMediaObj( const Rectangle& rRect ) : + SdrRectObj( rRect ) +{ +} + +// ------------------------------------------------------------------------------ + +SdrMediaObj::~SdrMediaObj() +{ +} + +// ------------------------------------------------------------------------------ + +FASTBOOL SdrMediaObj::HasTextEdit() const +{ + return FALSE; +} + +// ------------------------------------------------------------------------------ + +sdr::contact::ViewContact* SdrMediaObj::CreateObjectSpecificViewContact() +{ + return new ::sdr::contact::ViewContactOfSdrMediaObj( *this ); +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const +{ + rInfo.bSelectAllowed = true; + rInfo.bMoveAllowed = true; + rInfo.bResizeFreeAllowed = true; + rInfo.bResizePropAllowed = true; + rInfo.bRotateFreeAllowed = false; + rInfo.bRotate90Allowed = false; + rInfo.bMirrorFreeAllowed = false; + rInfo.bMirror45Allowed = false; + rInfo.bMirror90Allowed = false; + rInfo.bTransparenceAllowed = false; + rInfo.bGradientAllowed = false; + rInfo.bShearAllowed = false; + rInfo.bEdgeRadiusAllowed = false; + rInfo.bNoOrthoDesired = false; + rInfo.bNoContortion = false; + rInfo.bCanConvToPath = false; + rInfo.bCanConvToPoly = false; + rInfo.bCanConvToContour = false; + rInfo.bCanConvToPathLineToArea = false; + rInfo.bCanConvToPolyLineToArea = false; +} + +// ------------------------------------------------------------------------------ + +UINT16 SdrMediaObj::GetObjIdentifier() const +{ + return UINT16( OBJ_MEDIA ); +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulMEDIA); + + String aName( GetName() ); + + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralMEDIA); +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::operator=(const SdrObject& rObj) +{ + SdrRectObj::operator=( rObj ); + + if( rObj.ISA( SdrMediaObj ) ) + { + const SdrMediaObj& rMediaObj = static_cast< const SdrMediaObj& >( rObj ); + + setMediaProperties( rMediaObj.getMediaProperties() ); + setGraphic( rMediaObj.mapGraphic.get() ); + } +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::AdjustToMaxRect( const Rectangle& rMaxRect, bool bShrinkOnly /* = false */ ) +{ + Size aSize( Application::GetDefaultDevice()->PixelToLogic( getPreferredSize(), MAP_100TH_MM ) ); + Size aMaxSize( rMaxRect.GetSize() ); + + if( aSize.Height() != 0 && aSize.Width() != 0 ) + { + Point aPos( rMaxRect.TopLeft() ); + + // Falls Grafik zu gross, wird die Grafik + // in die Seite eingepasst + if ( (!bShrinkOnly || + ( aSize.Height() > aMaxSize.Height() ) || + ( aSize.Width() > aMaxSize.Width() ) )&& + aSize.Height() && aMaxSize.Height() ) + { + float fGrfWH = (float)aSize.Width() / + (float)aSize.Height(); + float fWinWH = (float)aMaxSize.Width() / + (float)aMaxSize.Height(); + + // Grafik an Pagesize anpassen (skaliert) + if ( fGrfWH < fWinWH ) + { + aSize.Width() = (long)(aMaxSize.Height() * fGrfWH); + aSize.Height()= aMaxSize.Height(); + } + else if ( fGrfWH > 0.F ) + { + aSize.Width() = aMaxSize.Width(); + aSize.Height()= (long)(aMaxSize.Width() / fGrfWH); + } + + aPos = rMaxRect.Center(); + } + + if( bShrinkOnly ) + aPos = aRect.TopLeft(); + + aPos.X() -= aSize.Width() / 2; + aPos.Y() -= aSize.Height() / 2; + SetLogicRect( Rectangle( aPos, aSize ) ); + } +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::setURL( const ::rtl::OUString& rURL ) +{ + ::avmedia::MediaItem aURLItem; + + aURLItem.setURL( rURL ); + setMediaProperties( aURLItem ); +} + +// ------------------------------------------------------------------------------ + +const ::rtl::OUString& SdrMediaObj::getURL() const +{ + return getMediaProperties().getURL(); +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState ) +{ + mediaPropertiesChanged( rState ); + static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() ); +} + +// ------------------------------------------------------------------------------ + +const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const +{ + return maMediaProperties; +} + +// ------------------------------------------------------------------------------ + +bool SdrMediaObj::hasPreferredSize() const +{ + return static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).hasPreferredSize(); +} + +// ------------------------------------------------------------------------------ + +Size SdrMediaObj::getPreferredSize() const +{ + return static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize(); +} + +// ------------------------------------------------------------------------------ + +const Graphic& SdrMediaObj::getGraphic() const +{ + if( !mapGraphic.get() ) + const_cast< SdrMediaObj* >( this )->mapGraphic.reset( new Graphic( ::avmedia::MediaWindow::grabFrame( getURL(), true ) ) ); + + return *mapGraphic; +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::setGraphic( const Graphic* pGraphic ) +{ + mapGraphic.reset( pGraphic ? new Graphic( *pGraphic ) : NULL ); +} + +// ------------------------------------------------------------------------------ + +void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties ) +{ + const sal_uInt32 nMaskSet = rNewProperties.getMaskSet(); + + // use only a subset of MediaItem properties for own own properties + if( ( AVMEDIA_SETMASK_URL & nMaskSet ) && + ( rNewProperties.getURL() != getURL() ) ) + { + setGraphic(); + maMediaProperties.setURL( rNewProperties.getURL() ); + } + + if( AVMEDIA_SETMASK_LOOP & nMaskSet ) + maMediaProperties.setLoop( rNewProperties.isLoop() ); + + if( AVMEDIA_SETMASK_MUTE & nMaskSet ) + maMediaProperties.setMute( rNewProperties.isMute() ); + + if( AVMEDIA_SETMASK_VOLUMEDB & nMaskSet ) + maMediaProperties.setVolumeDB( rNewProperties.getVolumeDB() ); + + if( AVMEDIA_SETMASK_ZOOM & nMaskSet ) + maMediaProperties.setZoom( rNewProperties.getZoom() ); +} diff --git a/svx/source/svdraw/svdoole2.cxx b/svx/source/svdraw/svdoole2.cxx new file mode 100644 index 000000000000..483c247c064f --- /dev/null +++ b/svx/source/svdraw/svdoole2.cxx @@ -0,0 +1,2242 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdoole2.hxx> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/EmbedMisc.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/embed/XInplaceClient.hpp> +#include <com/sun/star/embed/XInplaceObject.hpp> +#include <com/sun/star/embed/XLinkageSupport.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/embed/XWindowSupplier.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/container/XChild.hpp> +#include "com/sun/star/document/XStorageBasedDocument.hpp" + +#include <comphelper/processfactory.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <unotools/ucbstreamhelper.hxx> + +#include <toolkit/helper/vclunohelper.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <toolkit/helper/convert.hxx> + +#include <svtools/filter.hxx> +#include <svtools/embedhlp.hxx> + +#include <sfx2/objsh.hxx> +#include <sfx2/ipclient.hxx> +#include <sfx2/lnkbase.hxx> +#include <tools/stream.hxx> +#include <comphelper/anytostring.hxx> +#include <svx/svdpagv.hxx> +#include <tools/globname.hxx> +#include <vcl/jobset.hxx> +#include <sot/clsids.hxx> + +#include <sot/formats.hxx> +#include <sfx2/linkmgr.hxx> +#include <svtools/transfer.hxx> +#include <cppuhelper/implbase5.hxx> + +#include <svl/solar.hrc> +#include <svl/urihelper.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> + +#include <svx/svdpagv.hxx> +#include <svx/svdmodel.hxx> +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname +#include <svx/svdetc.hxx> +#include <svx/svdview.hxx> +#include "unomlstr.hxx" +#include <svtools/chartprettypainter.hxx> +#include <svx/sdr/contact/viewcontactofsdrole2obj.hxx> +#include <svx/svdograf.hxx> +#include <svx/sdr/properties/oleproperties.hxx> + +// #i100710# +#include <svx/xlnclit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xflbstit.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star; + +uno::Reference < beans::XPropertySet > lcl_getFrame_throw(const SdrOle2Obj* _pObject) +{ + uno::Reference < beans::XPropertySet > xFrame; + if ( _pObject ) + { + uno::Reference< frame::XController> xController = _pObject->GetParentXModel()->getCurrentController(); + if ( xController.is() ) + { + xFrame.set( xController->getFrame(),uno::UNO_QUERY_THROW); + } + } // if ( _pObject ) + return xFrame; +} + +class SdrLightEmbeddedClient_Impl : public ::cppu::WeakImplHelper5 + < embed::XStateChangeListener + , document::XEventListener + , embed::XInplaceClient + , embed::XEmbeddedClient + , embed::XWindowSupplier + > +{ + uno::Reference< awt::XWindow > m_xWindow; + SdrOle2Obj* mpObj; + + Fraction m_aScaleWidth; + Fraction m_aScaleHeight; + + +public: + SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj ); + void Release(); + + void SetSizeScale( const Fraction& aScaleWidth, const Fraction& aScaleHeight ) + { + m_aScaleWidth = aScaleWidth; + m_aScaleHeight = aScaleHeight; + } + + Fraction GetScaleWidth() const { return m_aScaleWidth; } + Fraction GetScaleHeight() const { return m_aScaleHeight; } + + void setWindow(const uno::Reference< awt::XWindow >& _xWindow); + +private: + Rectangle impl_getScaledRect_nothrow() const; + // XStateChangeListener + virtual void SAL_CALL changingState( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL stateChanged( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); + + // document::XEventListener + virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ); + + // XEmbeddedClient + virtual void SAL_CALL saveObject() throw ( embed::ObjectSaveVetoException, uno::Exception, uno::RuntimeException ); + virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) throw ( embed::WrongStateException, uno::RuntimeException ); + + // XComponentSupplier + virtual uno::Reference< util::XCloseable > SAL_CALL getComponent() throw ( uno::RuntimeException ); + + // XInplaceClient + virtual sal_Bool SAL_CALL canInplaceActivate() throw ( uno::RuntimeException ); + virtual void SAL_CALL activatingInplace() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL activatingUI() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL deactivatedInplace() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL deactivatedUI() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL getLayoutManager() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual awt::Rectangle SAL_CALL getPlacement() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual awt::Rectangle SAL_CALL getClipRectangle() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys ) throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL scrollObject( const awt::Size& aOffset ) throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect ) throw ( embed::WrongStateException, uno::Exception, uno::RuntimeException ); + + // XWindowSupplier + virtual uno::Reference< awt::XWindow > SAL_CALL getWindow() throw ( uno::RuntimeException ); +}; + +//-------------------------------------------------------------------- +SdrLightEmbeddedClient_Impl::SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj ) +: mpObj( pObj ) +{ +} +Rectangle SdrLightEmbeddedClient_Impl::impl_getScaledRect_nothrow() const +{ + MapUnit aContainerMapUnit( MAP_100TH_MM ); + uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); + if ( xParentVis.is() ) + aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); + Rectangle aLogicRect( mpObj->GetLogicRect() ); + // apply scaling to object area and convert to pixels + aLogicRect.SetSize( Size( Fraction( aLogicRect.GetWidth() ) * m_aScaleWidth, + Fraction( aLogicRect.GetHeight() ) * m_aScaleHeight ) ); + return aLogicRect; +} +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::changingState( const ::com::sun::star::lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ ) throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException) +{ +} + +//-------------------------------------------------------------------- +void SdrLightEmbeddedClient_Impl::Release() +{ + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + mpObj = NULL; + } + + release(); +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::stateChanged( const ::com::sun::star::lang::EventObject& /*aEvent*/, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if ( mpObj && nOldState == embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING ) + { + mpObj->ObjectLoaded(); + GetSdrGlobalData().GetOLEObjCache().InsertObj(mpObj); + } + else if ( mpObj && nNewState == embed::EmbedStates::LOADED && nOldState == embed::EmbedStates::RUNNING ) + { + GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj); + } +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::disposing( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj); +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ) +{ + // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // the code currently makes sence only in case there is no other client + if ( mpObj && mpObj->GetAspect() != embed::Aspects::MSOLE_ICON && aEvent.EventName.equalsAscii("OnVisAreaChanged") + && mpObj->GetObjRef().is() && mpObj->GetObjRef()->getClientSite() == uno::Reference< embed::XEmbeddedClient >( this ) ) + { + try + { + MapUnit aContainerMapUnit( MAP_100TH_MM ); + uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); + if ( xParentVis.is() ) + aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); + + MapUnit aObjMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpObj->GetObjRef()->getMapUnit( mpObj->GetAspect() ) ); + + Rectangle aVisArea; + awt::Size aSz; + try + { + aSz = mpObj->GetObjRef()->getVisualAreaSize( mpObj->GetAspect() ); + } + catch( embed::NoVisualAreaSizeException& ) + { + OSL_ENSURE( sal_False, "No visual area size!\n" ); + aSz.Width = 5000; + aSz.Height = 5000; + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Unexpected exception!\n" ); + aSz.Width = 5000; + aSz.Height = 5000; + } + + aVisArea.SetSize( Size( aSz.Width, aSz.Height ) ); + aVisArea = OutputDevice::LogicToLogic( aVisArea, aObjMapUnit, aContainerMapUnit ); + Size aScaledSize( static_cast< long >( m_aScaleWidth * Fraction( aVisArea.GetWidth() ) ), + static_cast< long >( m_aScaleHeight * Fraction( aVisArea.GetHeight() ) ) ); + Rectangle aLogicRect( mpObj->GetLogicRect() ); + + // react to the change if the difference is bigger than one pixel + Size aPixelDiff = + Application::GetDefaultDevice()->LogicToPixel( + Size( aLogicRect.GetWidth() - aScaledSize.Width(), + aLogicRect.GetHeight() - aScaledSize.Height() ), + aContainerMapUnit ); + if( aPixelDiff.Width() || aPixelDiff.Height() ) + { + mpObj->SetLogicRect( Rectangle( aLogicRect.TopLeft(), aScaledSize ) ); + mpObj->BroadcastObjectChange(); + } + else + mpObj->ActionChanged(); + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Unexpected exception!\n" ); + } + } +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::saveObject() + throw ( embed::ObjectSaveVetoException, + uno::Exception, + uno::RuntimeException ) +{ + // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl + uno::Reference< embed::XCommonEmbedPersist > xPersist; + uno::Reference< util::XModifiable > xModifiable; + + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if ( !mpObj ) + throw embed::ObjectSaveVetoException(); + + // the common persistance is supported by objects and links + xPersist = uno::Reference< embed::XCommonEmbedPersist >( mpObj->GetObjRef(), uno::UNO_QUERY_THROW ); + xModifiable = uno::Reference< util::XModifiable >( mpObj->GetParentXModel(), uno::UNO_QUERY ); + } + + xPersist->storeOwn(); + + if ( xModifiable.is() ) + xModifiable->setModified( sal_True ); +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::visibilityChanged( sal_Bool /*bVisible*/ ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // nothing to do currently + // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl + if ( mpObj ) + { + Rectangle aLogicRect( mpObj->GetLogicRect() ); + Size aLogicSize( aLogicRect.GetWidth(), aLogicRect.GetHeight() ); + + if( mpObj->IsChart() ) + { + //charts never should be stretched see #i84323# for example + mpObj->SetLogicRect( Rectangle( aLogicRect.TopLeft(), aLogicSize ) ); + mpObj->BroadcastObjectChange(); + } // if( mpObj->IsChart() ) + } +} + +//-------------------------------------------------------------------- +uno::Reference< util::XCloseable > SAL_CALL SdrLightEmbeddedClient_Impl::getComponent() + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XCloseable > xResult; + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( mpObj ) + xResult = uno::Reference< util::XCloseable >( mpObj->GetParentXModel(), uno::UNO_QUERY ); + + return xResult; +} +// XInplaceClient +//-------------------------------------------------------------------- +sal_Bool SAL_CALL SdrLightEmbeddedClient_Impl::canInplaceActivate() + throw ( uno::RuntimeException ) +{ + sal_Bool bRet = sal_False; + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( mpObj ) + { + uno::Reference< embed::XEmbeddedObject > xObject = mpObj->GetObjRef(); + if ( !xObject.is() ) + throw uno::RuntimeException(); + // we don't want to switch directly from outplace to inplace mode + bRet = !( xObject->getCurrentState() == embed::EmbedStates::ACTIVE || mpObj->GetAspect() == embed::Aspects::MSOLE_ICON ); + } // if ( mpObj ) + return bRet; +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::activatingInplace() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::activatingUI() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj)); + uno::Reference < frame::XFrame > xOwnFrame( xFrame,uno::UNO_QUERY); + uno::Reference < frame::XFramesSupplier > xParentFrame( xOwnFrame->getCreator(), uno::UNO_QUERY ); + if ( xParentFrame.is() ) + xParentFrame->setActiveFrame( xOwnFrame ); + + OLEObjCache& rObjCache = GetSdrGlobalData().GetOLEObjCache(); + const ULONG nCount = rObjCache.Count(); + for(sal_Int32 i = nCount-1 ; i >= 0;--i) + { + SdrOle2Obj* pObj = reinterpret_cast<SdrOle2Obj*>(rObjCache.GetObject(i)); + if ( pObj != mpObj ) + { + // only deactivate ole objects which belongs to the same frame + if ( xFrame == lcl_getFrame_throw(pObj) ) + { + uno::Reference< embed::XEmbeddedObject > xObject = pObj->GetObjRef(); + try + { + if ( xObject->getStatus( pObj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE ) + xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE ); + else + { + // the links should not stay in running state for long time because of locking + uno::Reference< embed::XLinkageSupport > xLink( xObject, uno::UNO_QUERY ); + if ( xLink.is() && xLink->isLink() ) + xObject->changeState( embed::EmbedStates::LOADED ); + else + xObject->changeState( embed::EmbedStates::RUNNING ); + } + } + catch (com::sun::star::uno::Exception& ) + {} + } + } + } // for(sal_Int32 i = nCount-1 ; i >= 0;--i) + + //m_pClient->GetViewShell()->UIActivating( m_pClient ); +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedInplace() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedUI() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager(getLayoutManager()); + if ( xLayoutManager.is() ) + { + const static rtl::OUString aMenuBarURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )); + if ( !xLayoutManager->isElementVisible( aMenuBarURL ) ) + xLayoutManager->createElement( aMenuBarURL ); + } +} + +//-------------------------------------------------------------------- +uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL SdrLightEmbeddedClient_Impl::getLayoutManager() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + uno::Reference< ::com::sun::star::frame::XLayoutManager > xMan; + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj)); + try + { + xMan.set(xFrame->getPropertyValue( ::rtl::OUString::createFromAscii("LayoutManager") ),uno::UNO_QUERY); + } + catch ( uno::Exception& ) + { + throw uno::RuntimeException(); + } + + return xMan; +} + +//-------------------------------------------------------------------- +uno::Reference< frame::XDispatchProvider > SAL_CALL SdrLightEmbeddedClient_Impl::getInplaceDispatchProvider() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + return uno::Reference < frame::XDispatchProvider >( lcl_getFrame_throw(mpObj), uno::UNO_QUERY_THROW ); +} + +//-------------------------------------------------------------------- +awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getPlacement() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( !mpObj ) + throw uno::RuntimeException(); + + Rectangle aLogicRect = impl_getScaledRect_nothrow(); + MapUnit aContainerMapUnit( MAP_100TH_MM ); + uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); + if ( xParentVis.is() ) + aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); + + aLogicRect = Application::GetDefaultDevice()->LogicToPixel(aLogicRect,aContainerMapUnit); + return AWTRectangle( aLogicRect ); +} + +//-------------------------------------------------------------------- +awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getClipRectangle() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + return getPlacement(); +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::scrollObject( const awt::Size& /*aOffset*/ ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ +} + +//-------------------------------------------------------------------- +void SAL_CALL SdrLightEmbeddedClient_Impl::changedPlacement( const awt::Rectangle& aPosRect ) + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( !mpObj ) + throw uno::RuntimeException(); + + uno::Reference< embed::XInplaceObject > xInplace( mpObj->GetObjRef(), uno::UNO_QUERY ); + if ( !xInplace.is() ) + throw uno::RuntimeException(); + + // check if the change is at least one pixel in size + awt::Rectangle aOldRect = getPlacement(); + Rectangle aNewPixelRect = VCLRectangle( aPosRect ); + Rectangle aOldPixelRect = VCLRectangle( aOldRect ); + if ( aOldPixelRect == aNewPixelRect ) + // nothing has changed + return; + + // new scaled object area + MapUnit aContainerMapUnit( MAP_100TH_MM ); + uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); + if ( xParentVis.is() ) + aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); + + Rectangle aNewLogicRect = Application::GetDefaultDevice()->PixelToLogic(aNewPixelRect,aContainerMapUnit); + Rectangle aLogicRect = impl_getScaledRect_nothrow(); + + if ( aNewLogicRect != aLogicRect ) + { + // the calculation of the object area has not changed the object size + // it should be done here then + //SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True ); + + // new size of the object area without scaling + Size aNewObjSize( Fraction( aNewLogicRect.GetWidth() ) / m_aScaleWidth, + Fraction( aNewLogicRect.GetHeight() ) / m_aScaleHeight ); + + // now remove scaling from new placement and keep this a the new object area + aNewLogicRect.SetSize( aNewObjSize ); + // react to the change if the difference is bigger than one pixel + Size aPixelDiff = + Application::GetDefaultDevice()->LogicToPixel( + Size( aLogicRect.GetWidth() - aNewObjSize.Width(), + aLogicRect.GetHeight() - aNewObjSize.Height() ), + aContainerMapUnit ); + if( aPixelDiff.Width() || aPixelDiff.Height() ) + { + mpObj->SetLogicRect( Rectangle( aLogicRect.TopLeft(), aNewObjSize ) ); + mpObj->BroadcastObjectChange(); + } + else + mpObj->ActionChanged(); + + // let the window size be recalculated + //SizeHasChanged(); // TODO: OJ + } +} +// XWindowSupplier +//-------------------------------------------------------------------- +uno::Reference< awt::XWindow > SAL_CALL SdrLightEmbeddedClient_Impl::getWindow() + throw ( uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + uno::Reference< awt::XWindow > xCurrent = m_xWindow; + if ( !xCurrent.is() ) + { + if ( !mpObj ) + throw uno::RuntimeException(); + uno::Reference< frame::XFrame> xFrame(lcl_getFrame_throw(mpObj),uno::UNO_QUERY_THROW); + xCurrent = xFrame->getComponentWindow(); + } // if ( !xCurrent.is() ) + return xCurrent; +} +void SdrLightEmbeddedClient_Impl::setWindow(const uno::Reference< awt::XWindow >& _xWindow) +{ + m_xWindow = _xWindow; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class SdrEmbedObjectLink : public sfx2::SvBaseLink +{ + SdrOle2Obj* pObj; + +public: + SdrEmbedObjectLink(SdrOle2Obj* pObj); + virtual ~SdrEmbedObjectLink(); + + virtual void Closed(); + virtual void DataChanged( const String& rMimeType, + const ::com::sun::star::uno::Any & rValue ); + + sal_Bool Connect() { return GetRealObject() != NULL; } +}; + +// ----------------------------------------------------------------------------- + +SdrEmbedObjectLink::SdrEmbedObjectLink(SdrOle2Obj* pObject): + ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, SOT_FORMATSTR_ID_SVXB ), + pObj(pObject) +{ + SetSynchron( FALSE ); +} + +// ----------------------------------------------------------------------------- + +SdrEmbedObjectLink::~SdrEmbedObjectLink() +{ +} + +// ----------------------------------------------------------------------------- + +void SdrEmbedObjectLink::DataChanged( const String& /*rMimeType*/, + const ::com::sun::star::uno::Any & /*rValue*/ ) +{ + if ( !pObj->UpdateLinkURL_Impl() ) + { + // the link URL was not changed + uno::Reference< embed::XEmbeddedObject > xObject = pObj->GetObjRef(); + OSL_ENSURE( xObject.is(), "The object must exist always!\n" ); + if ( xObject.is() ) + { + // let the object reload the link + // TODO/LATER: reload call could be used for this case + + try + { + sal_Int32 nState = xObject->getCurrentState(); + if ( nState != embed::EmbedStates::LOADED ) + { + // in some cases the linked file probably is not locked so it could be changed + xObject->changeState( embed::EmbedStates::LOADED ); + xObject->changeState( nState ); + } + } + catch ( uno::Exception& ) + { + } + } + } + + pObj->GetNewReplacement(); + pObj->SetChanged(); +} + +// ----------------------------------------------------------------------------- + +void SdrEmbedObjectLink::Closed() +{ + pObj->BreakFileLink_Impl(); + SvBaseLink::Closed(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class SdrOle2ObjImpl +{ +public: + // TODO/LATER: do we really need this pointer? + GraphicObject* pGraphicObject; + String aPersistName; // name of object in persist + SdrLightEmbeddedClient_Impl* pLightClient; // must be registered as client only using AddOwnLightClient() call + + // #107645# + // New local var to avoid repeated loading if load of OLE2 fails + sal_Bool mbLoadingOLEObjectFailed; + sal_Bool mbConnected; + + SdrEmbedObjectLink* mpObjectLink; + String maLinkURL; + + SdrOle2ObjImpl() + : pGraphicObject( NULL ) + // #107645# + // init to start situation, loading did not fail + , mbLoadingOLEObjectFailed( sal_False ) + , mbConnected( sal_False ) + , mpObjectLink( NULL ) + { + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// Predicate determining whether the given OLE is an internal math +// object +static bool ImplIsMathObj( const uno::Reference < embed::XEmbeddedObject >& rObjRef ) +{ + if ( !rObjRef.is() ) + return false; + + SvGlobalName aClassName( rObjRef->getClassID() ); + if( aClassName == SvGlobalName(SO3_SM_CLASSID_30) || + aClassName == SvGlobalName(SO3_SM_CLASSID_40) || + aClassName == SvGlobalName(SO3_SM_CLASSID_50) || + aClassName == SvGlobalName(SO3_SM_CLASSID_60) || + aClassName == SvGlobalName(SO3_SM_CLASSID) ) + { + return true; + } + else + { + return false; + } +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrOle2Obj::CreateObjectSpecificProperties() +{ + return new sdr::properties::OleProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrOle2Obj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrOle2Obj(*this); +} + +// ----------------------------------------------------------------------------- + +TYPEINIT1(SdrOle2Obj,SdrRectObj); +DBG_NAME(SdrOle2Obj) +SdrOle2Obj::SdrOle2Obj(FASTBOOL bFrame_) : m_bTypeAsked(false) +,m_bChart(false) +{ + DBG_CTOR( SdrOle2Obj,NULL); + bInDestruction = FALSE; + Init(); + bFrame=bFrame_; +} + +// ----------------------------------------------------------------------------- +SdrOle2Obj::SdrOle2Obj( const svt::EmbeddedObjectRef& rNewObjRef, FASTBOOL bFrame_) + : xObjRef( rNewObjRef ) + , m_bTypeAsked(false) + , m_bChart(false) +{ + DBG_CTOR( SdrOle2Obj,NULL); + bInDestruction = FALSE; + Init(); + + bFrame=bFrame_; + + if ( xObjRef.is() && (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) + SetResizeProtect(TRUE); + + // #108759# For math objects, set closed state to transparent + if( ImplIsMathObj( xObjRef.GetObject() ) ) + SetClosedObj( false ); +} + +// ----------------------------------------------------------------------------- + +SdrOle2Obj::SdrOle2Obj( const svt::EmbeddedObjectRef& rNewObjRef, const XubString& rNewObjName, FASTBOOL bFrame_) + : xObjRef( rNewObjRef ) + , m_bTypeAsked(false) + , m_bChart(false) +{ + DBG_CTOR( SdrOle2Obj,NULL); + bInDestruction = FALSE; + Init(); + + mpImpl->aPersistName = rNewObjName; + bFrame=bFrame_; + + if ( xObjRef.is() && (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) + SetResizeProtect(TRUE); + + // #108759# For math objects, set closed state to transparent + if( ImplIsMathObj( xObjRef.GetObject() ) ) + SetClosedObj( false ); +} + +// ----------------------------------------------------------------------------- + +SdrOle2Obj::SdrOle2Obj( const svt::EmbeddedObjectRef& rNewObjRef, const XubString& rNewObjName, const Rectangle& rNewRect, FASTBOOL bFrame_) + : SdrRectObj(rNewRect) + , xObjRef( rNewObjRef ) + , m_bTypeAsked(false) + , m_bChart(false) +{ + DBG_CTOR( SdrOle2Obj,NULL); + bInDestruction = FALSE; + Init(); + + mpImpl->aPersistName = rNewObjName; + bFrame=bFrame_; + + if ( xObjRef.is() && (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) + SetResizeProtect(TRUE); + + // #108759# For math objects, set closed state to transparent + if( ImplIsMathObj( xObjRef.GetObject() ) ) + SetClosedObj( false ); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::Init() +{ + mpImpl = new SdrOle2ObjImpl; + pModifyListener = NULL; + pGraphic=NULL; + mpImpl->pGraphicObject=NULL; + mpImpl->pLightClient = 0; + + xObjRef.Lock( TRUE ); +} + +// ----------------------------------------------------------------------------- + +SdrOle2Obj::~SdrOle2Obj() +{ + DBG_DTOR( SdrOle2Obj,NULL); + bInDestruction = TRUE; + + if ( mpImpl->mbConnected ) + Disconnect(); + + if( pGraphic!=NULL ) + delete pGraphic; + + if(mpImpl->pGraphicObject!=NULL) + delete mpImpl->pGraphicObject; + + if(pModifyListener) + { + pModifyListener->invalidate(); + pModifyListener->release(); + } + + DisconnectFileLink_Impl(); + + if ( mpImpl->pLightClient ) + { + mpImpl->pLightClient->Release(); + mpImpl->pLightClient = NULL; + } + + delete mpImpl; +} + +// ----------------------------------------------------------------------------- +void SdrOle2Obj::SetAspect( sal_Int64 nAspect ) +{ + xObjRef.SetViewAspect( nAspect ); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::SetGraphic_Impl(const Graphic* pGrf) +{ + if ( pGraphic ) + { + delete pGraphic; + pGraphic = NULL; + delete mpImpl->pGraphicObject; + mpImpl->pGraphicObject = NULL; + } + + if (pGrf!=NULL) + { + pGraphic = new Graphic(*pGrf); + mpImpl->pGraphicObject = new GraphicObject( *pGraphic ); + } + + SetChanged(); + BroadcastObjectChange(); + + //if ( ppObjRef->Is() && pGrf ) + // BroadcastObjectChange(); +} + +void SdrOle2Obj::SetGraphic(const Graphic* pGrf) +{ + // only for setting a preview graphic + SetGraphic_Impl( pGrf ); +} + +// ----------------------------------------------------------------------------- + +FASTBOOL SdrOle2Obj::IsEmpty() const +{ + return !(xObjRef.is()); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::Connect() +{ + if( IsEmptyPresObj() ) + return; + + if( mpImpl->mbConnected ) + { + // mba: currently there are situations where it seems to be unavoidable to have multiple connects + // changing this would need a larger code rewrite, so for now I remove the assertion + // DBG_ERROR("Connect() called on connected object!"); + return; + } + + Connect_Impl(); + AddListeners_Impl(); +} + +// ----------------------------------------------------------------------------- + +sal_Bool SdrOle2Obj::UpdateLinkURL_Impl() +{ + sal_Bool bResult = sal_False; + + if ( mpImpl->mpObjectLink ) + { + sfx2::LinkManager* pLinkManager = pModel ? pModel->GetLinkManager() : NULL; + if ( pLinkManager ) + { + String aNewLinkURL; + pLinkManager->GetDisplayNames( mpImpl->mpObjectLink, 0, &aNewLinkURL, 0, 0 ); + if ( !aNewLinkURL.EqualsIgnoreCaseAscii( mpImpl->maLinkURL ) ) + { + const_cast<SdrOle2Obj*>(this)->GetObjRef_Impl(); + uno::Reference< embed::XCommonEmbedPersist > xPersObj( xObjRef.GetObject(), uno::UNO_QUERY ); + OSL_ENSURE( xPersObj.is(), "The object must exist!\n" ); + if ( xPersObj.is() ) + { + try + { + sal_Int32 nCurState = xObjRef->getCurrentState(); + if ( nCurState != embed::EmbedStates::LOADED ) + xObjRef->changeState( embed::EmbedStates::LOADED ); + + // TODO/LATER: there should be possible to get current mediadescriptor settings from the object + uno::Sequence< beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); + aArgs[0].Value <<= ::rtl::OUString( aNewLinkURL ); + xPersObj->reload( aArgs, uno::Sequence< beans::PropertyValue >() ); + + mpImpl->maLinkURL = aNewLinkURL; + bResult = sal_True; + + if ( nCurState != embed::EmbedStates::LOADED ) + xObjRef->changeState( nCurState ); + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::UpdateLinkURL_Impl(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } + + if ( !bResult ) + { + // TODO/LATER: return the old name to the link manager, is it possible? + } + } + } + } + + return bResult; +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::BreakFileLink_Impl() +{ + uno::Reference<document::XStorageBasedDocument> xDoc; + if ( pModel ) + xDoc.set( pModel->getUnoModel(),uno::UNO_QUERY); + + if ( xDoc.is() ) + { + uno::Reference< embed::XStorage > xStorage = xDoc->getDocumentStorage(); + if ( xStorage.is() ) + { + try + { + uno::Reference< embed::XLinkageSupport > xLinkSupport( xObjRef.GetObject(), uno::UNO_QUERY_THROW ); + xLinkSupport->breakLink( xStorage, mpImpl->aPersistName ); + DisconnectFileLink_Impl(); + mpImpl->maLinkURL = String(); + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::BreakFileLink_Impl(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::DisconnectFileLink_Impl() +{ + sfx2::LinkManager* pLinkManager = pModel ? pModel->GetLinkManager() : NULL; + if ( pLinkManager && mpImpl->mpObjectLink ) + { + pLinkManager->Remove( mpImpl->mpObjectLink ); + mpImpl->mpObjectLink = NULL; + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::CheckFileLink_Impl() +{ + if ( pModel && xObjRef.GetObject().is() && !mpImpl->mpObjectLink ) + { + try + { + uno::Reference< embed::XLinkageSupport > xLinkSupport( xObjRef.GetObject(), uno::UNO_QUERY ); + if ( xLinkSupport.is() && xLinkSupport->isLink() ) + { + String aLinkURL = xLinkSupport->getLinkURL(); + if ( aLinkURL.Len() ) + { + // this is a file link so the model link manager should handle it + sfx2::LinkManager* pLinkManager = pModel->GetLinkManager(); + if ( pLinkManager ) + { + mpImpl->mpObjectLink = new SdrEmbedObjectLink( this ); + mpImpl->maLinkURL = aLinkURL; + pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL, NULL, NULL ); + mpImpl->mpObjectLink->Connect(); + } + } + } + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::CheckFileLink_Impl(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::Reconnect_Impl() +{ + DBG_ASSERT( mpImpl->mbConnected, "Assigned unconnected object?!" ); + Connect_Impl(); +} + +void SdrOle2Obj::Connect_Impl() +{ + if( pModel && mpImpl->aPersistName.Len() ) + { + try + { + ::comphelper::IEmbeddedHelper* pPers = pModel->GetPersist(); + if ( pPers ) + { + comphelper::EmbeddedObjectContainer& rContainer = pPers->getEmbeddedObjectContainer(); + if ( !rContainer.HasEmbeddedObject( mpImpl->aPersistName ) + || ( xObjRef.is() && !rContainer.HasEmbeddedObject( xObjRef.GetObject() ) ) ) + { + // object not known to container document + // No object -> disaster! + DBG_ASSERT( xObjRef.is(), "No object in connect!"); + if ( xObjRef.is() ) + { + // object came from the outside, now add it to the container + ::rtl::OUString aTmp; + rContainer.InsertEmbeddedObject( xObjRef.GetObject(), aTmp ); + mpImpl->aPersistName = aTmp; + } + } + else if ( !xObjRef.is() ) + { + xObjRef.Assign( rContainer.GetEmbeddedObject( mpImpl->aPersistName ), xObjRef.GetViewAspect() ); + m_bTypeAsked = false; + } + + if ( xObjRef.GetObject().is() ) + { + xObjRef.AssignToContainer( &rContainer, mpImpl->aPersistName ); + mpImpl->mbConnected = true; + xObjRef.Lock( TRUE ); + } + } + + if ( xObjRef.is() ) + { + if ( !mpImpl->pLightClient ) + { + mpImpl->pLightClient = new SdrLightEmbeddedClient_Impl( this ); + mpImpl->pLightClient->acquire(); + } + + xObjRef->addStateChangeListener( mpImpl->pLightClient ); + xObjRef->addEventListener( uno::Reference< document::XEventListener >( mpImpl->pLightClient ) ); + + if ( xObjRef->getCurrentState() != embed::EmbedStates::LOADED ) + GetSdrGlobalData().GetOLEObjCache().InsertObj(this); + + CheckFileLink_Impl(); + + uno::Reference< container::XChild > xChild( xObjRef.GetObject(), uno::UNO_QUERY ); + if( xChild.is() ) + { + uno::Reference< uno::XInterface > xParent( pModel->getUnoModel()); + if( xParent.is()) + xChild->setParent( pModel->getUnoModel() ); + } + + } + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::Connect_Impl(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } + + //TODO/LATER: wait for definition of MiscStatus RESIZEONPRINTERCHANGE + //if ( xObjRef.is() && (*ppObjRef)->GetMiscStatus() & SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE ) + { + //TODO/LATER: needs a new handling for OnPrinterChanged + /* + if (pModel && pModel->GetRefDevice() && + pModel->GetRefDevice()->GetOutDevType() == OUTDEV_PRINTER) + { + // Kein RefDevice oder RefDevice kein Printer + BOOL bModified = (*ppObjRef)->IsModified(); + Printer* pPrinter = (Printer*) pModel->GetRefDevice(); + (*ppObjRef)->OnDocumentPrinterChanged( pPrinter ); + (*ppObjRef)->SetModified( bModified ); + }*/ + } +} + +void SdrOle2Obj::ObjectLoaded() +{ + AddListeners_Impl(); +} + +void SdrOle2Obj::AddListeners_Impl() +{ + if( xObjRef.is() && xObjRef->getCurrentState() != embed::EmbedStates::LOADED ) + { + // register modify listener + if( !pModifyListener ) + { + ((SdrOle2Obj*)this)->pModifyListener = new SvxUnoShapeModifyListener( (SdrOle2Obj*)this ); + pModifyListener->acquire(); + } + + uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY ); + if( xBC.is() && pModifyListener ) + { + uno::Reference< util::XModifyListener > xListener( pModifyListener ); + xBC->addModifyListener( xListener ); + } + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::Disconnect() +{ + if( IsEmptyPresObj() ) + return; + + if( !mpImpl->mbConnected ) + { + DBG_ERROR("Disconnect() called on disconnected object!"); + return; + } + + RemoveListeners_Impl(); + Disconnect_Impl(); +} + +void SdrOle2Obj::RemoveListeners_Impl() +{ + if( xObjRef.is() && mpImpl->aPersistName.Len() ) + { + try + { + sal_Int32 nState = xObjRef->getCurrentState(); + if ( nState != embed::EmbedStates::LOADED ) + { + uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY ); + if( xBC.is() && pModifyListener ) + { + uno::Reference< util::XModifyListener > xListener( pModifyListener ); + xBC->removeModifyListener( xListener ); + } + } + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::RemoveListeners_Impl(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } +} + +void SdrOle2Obj::Disconnect_Impl() +{ + try + { + if ( pModel && mpImpl->aPersistName.Len() ) + { + if( pModel->IsInDestruction() ) + { + // TODO/LATER: here we must assume that the destruction of the model is enough to make clear that we will not + // remove the object from the container, even if the DrawingObject itself is not destroyed (unfortunately this + // There is no real need to do the following removing of the object from the container + // in case the model has correct persistance, but in case of problems such a removing + // would make the behaviour of the office more stable + + comphelper::EmbeddedObjectContainer* pContainer = xObjRef.GetContainer(); + if ( pContainer ) + { + pContainer->CloseEmbeddedObject( xObjRef.GetObject() ); + xObjRef.AssignToContainer( NULL, mpImpl->aPersistName ); + } + + // happens later than the destruction of the model, so we can't assert that). + //DBG_ASSERT( bInDestruction, "Model is destroyed, but not me?!" ); + //TODO/LATER: should be make sure that the ObjectShell also forgets the object, because we will close it soon? + /* + uno::Reference < util::XCloseable > xClose( xObjRef, uno::UNO_QUERY ); + if ( xClose.is() ) + { + try + { + xClose->close( sal_True ); + } + catch ( util::CloseVetoException& ) + { + // there's still someone who needs the object! + } + } + + xObjRef = NULL;*/ + } + else if ( xObjRef.is() ) + { + if ( pModel->getUnoModel().is() ) + { + // remove object, but don't close it (that's up to someone else) + comphelper::EmbeddedObjectContainer* pContainer = xObjRef.GetContainer(); + if ( pContainer ) + { + pContainer->RemoveEmbeddedObject( xObjRef.GetObject(), sal_False); + + // TODO/LATER: mpImpl->aPersistName contains outdated information, to have it uptodate + // it should be returned from RemoveEmbeddedObject call. Currently it is no problem, + // since no container is adjusted, actually the empty string could be provided as a name here + xObjRef.AssignToContainer( NULL, mpImpl->aPersistName ); + } + + DisconnectFileLink_Impl(); + } + } + } + + if ( xObjRef.is() && mpImpl->pLightClient ) + { + xObjRef->removeStateChangeListener ( mpImpl->pLightClient ); + xObjRef->removeEventListener( uno::Reference< document::XEventListener >( mpImpl->pLightClient ) ); + xObjRef->setClientSite( NULL ); + + GetSdrGlobalData().GetOLEObjCache().RemoveObj(this); + } + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::Disconnect_Impl(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + + mpImpl->mbConnected = false; +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::SetModel(SdrModel* pNewModel) +{ + ::comphelper::IEmbeddedHelper* pDestPers = pNewModel ? pNewModel->GetPersist() : 0; + ::comphelper::IEmbeddedHelper* pSrcPers = pModel ? pModel->GetPersist() : 0; + + if ( pNewModel == pModel ) + { + // don't know if this is necessary or if it will ever happen, but who know?! + SdrRectObj::SetModel( pNewModel ); + return; + } + + // assignment to model has changed + DBG_ASSERT( pSrcPers || !mpImpl->mbConnected, "Connected object without a model?!" ); + + DBG_ASSERT( pDestPers, "The destination model must have a persistence! Please submit an issue!" ); + DBG_ASSERT( pDestPers != pSrcPers, "The source and the destination models should have different persistences! Problems are possible!" ); + + // this is a bug if the target model has no persistence + // no error handling is possible so just do nothing in this method + if ( !pDestPers ) + return; + + RemoveListeners_Impl(); + + if( pDestPers && pSrcPers && !IsEmptyPresObj() ) + { + try + { + // move the objects' storage; ObjectRef remains the same, but PersistName may change + ::rtl::OUString aTmp; + comphelper::EmbeddedObjectContainer& rContainer = pSrcPers->getEmbeddedObjectContainer(); + uno::Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( mpImpl->aPersistName ); + DBG_ASSERT( !xObjRef.is() || xObjRef.GetObject() == xObj, "Wrong object identity!" ); + if ( xObj.is() ) + { + pDestPers->getEmbeddedObjectContainer().MoveEmbeddedObject( rContainer, xObj, aTmp ); + mpImpl->aPersistName = aTmp; + xObjRef.AssignToContainer( &pDestPers->getEmbeddedObjectContainer(), aTmp ); + } + DBG_ASSERT( aTmp.getLength(), "Copying embedded object failed!" ); + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::SetModel(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } + + SdrRectObj::SetModel( pNewModel ); + + // #i43086# + // #i85304 redo the change for charts for the above bugfix, as #i43086# does not ocur anymore + //so maybe the ImpSetVisAreaSize call can be removed here completely + //Nevertheless I leave it in for other objects as I am not sure about the side effects when removing now + if( pModel && !pModel->isLocked() && !IsChart() ) + ImpSetVisAreaSize(); + + if( pDestPers && !IsEmptyPresObj() ) + { + if ( !pSrcPers || IsEmptyPresObj() ) + // object wasn't connected, now it should + Connect_Impl(); + else + Reconnect_Impl(); + } + + AddListeners_Impl(); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::SetPage(SdrPage* pNewPage) +{ + FASTBOOL bRemove=pNewPage==NULL && pPage!=NULL; + FASTBOOL bInsert=pNewPage!=NULL && pPage==NULL; + + if (bRemove && mpImpl->mbConnected ) + Disconnect(); + + SdrRectObj::SetPage(pNewPage); + + if (bInsert && !mpImpl->mbConnected ) + Connect(); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::SetObjRef( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& rNewObjRef ) +{ + DBG_ASSERT( !rNewObjRef.is() || !xObjRef.GetObject().is(), "SetObjRef called on already initialized object!"); + if( rNewObjRef == xObjRef.GetObject() ) + return; + + // MBA: the caller of the method is responsible to control the old object, it will not be closed here + // Otherwise WW8 import crashes because it tranfers control to OLENode by this method + if ( xObjRef.GetObject().is() ) + xObjRef.Lock( FALSE ); + + // MBA: avoid removal of object in Disconnect! It is definitely a HACK to call SetObjRef(0)! + // This call will try to close the objects; so if anybody else wants to keep it, it must be locked by a CloseListener + xObjRef.Clear(); + + if ( mpImpl->mbConnected ) + Disconnect(); + + xObjRef.Assign( rNewObjRef, GetAspect() ); + m_bTypeAsked = false; + + if ( xObjRef.is() ) + { + DELETEZ( pGraphic ); + + if ( (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) + SetResizeProtect(TRUE); + + // #108759# For math objects, set closed state to transparent + if( ImplIsMathObj( rNewObjRef ) ) + SetClosedObj( false ); + + Connect(); + } + + SetChanged(); + BroadcastObjectChange(); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::SetClosedObj( bool bIsClosed ) +{ + // TODO/LATER: do we still need this hack? + // #108759# Allow changes to the closed state of OLE objects + bClosedObj = bIsClosed; +} + +// ----------------------------------------------------------------------------- + +SdrObject* SdrOle2Obj::getFullDragClone() const +{ + // special handling for OLE. The default handling works, but is too + // slow when the whole OLE needs to be cloned. Get the Metafile and + // create a graphic object with it + Graphic* pOLEGraphic = GetGraphic(); + SdrObject* pClone = 0; + + if(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + pOLEGraphic = getEmbeddedObjectRef().GetHCGraphic(); + } + + if(pOLEGraphic) + { + pClone = new SdrGrafObj(*pOLEGraphic, GetSnapRect()); + + // this would be the place where to copy all attributes + // when OLE will support fill and line style + // pClone->SetMergedItem(pOleObject->GetMergedItemSet()); + } + else + { + // #i100710# pOLEGraphic may be zero (no visualisation available), + // so we need to use the OLE replacement graphic + pClone = new SdrRectObj(GetSnapRect()); + + // gray outline + pClone->SetMergedItem(XLineStyleItem(XLINE_SOLID)); + const svtools::ColorConfig aColorConfig; + const svtools::ColorConfigValue aColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES)); + pClone->SetMergedItem(XLineColorItem(String(), aColor.nColor)); + + // bitmap fill + pClone->SetMergedItem(XFillStyleItem(XFILL_BITMAP)); + pClone->SetMergedItem(XFillBitmapItem(String(), GetEmtyOLEReplacementBitmap())); + pClone->SetMergedItem(XFillBmpTileItem(false)); + pClone->SetMergedItem(XFillBmpStretchItem(false)); + } + + return pClone; +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::SetPersistName( const String& rPersistName ) +{ + DBG_ASSERT( !mpImpl->aPersistName.Len(), "Persist name changed!"); + + mpImpl->aPersistName = rPersistName; + mpImpl->mbLoadingOLEObjectFailed = false; + + Connect(); + SetChanged(); +} + +void SdrOle2Obj::AbandonObject() +{ + mpImpl->aPersistName.Erase(); + mpImpl->mbLoadingOLEObjectFailed = false; + SetObjRef(0); +} + +// ----------------------------------------------------------------------------- + +String SdrOle2Obj::GetPersistName() const +{ + return mpImpl->aPersistName; +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bRotateFreeAllowed=FALSE; + rInfo.bRotate90Allowed =FALSE; + rInfo.bMirrorFreeAllowed=FALSE; + rInfo.bMirror45Allowed =FALSE; + rInfo.bMirror90Allowed =FALSE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =FALSE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bNoOrthoDesired =FALSE; + rInfo.bCanConvToPath =FALSE; + rInfo.bCanConvToPoly =FALSE; + rInfo.bCanConvToPathLineToArea=FALSE; + rInfo.bCanConvToPolyLineToArea=FALSE; + rInfo.bCanConvToContour = FALSE; +} + +// ----------------------------------------------------------------------------- + +UINT16 SdrOle2Obj::GetObjIdentifier() const +{ + return bFrame ? UINT16(OBJ_FRAME) : UINT16(OBJ_OLE2); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::TakeObjNameSingul(XubString& rName) const +{ + rName = ImpGetResStr(bFrame ? STR_ObjNameSingulFrame : STR_ObjNameSingulOLE2); + + const String aName(GetName()); + + if( aName.Len() ) + { + rName.AppendAscii(" '"); + rName += aName; + rName += sal_Unicode('\''); + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(bFrame ? STR_ObjNamePluralFrame : STR_ObjNamePluralOLE2); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::operator=(const SdrObject& rObj) +{ + //TODO/LATER: who takes over control of my old object?! + if( &rObj != this ) + { + // #116235# + // ImpAssign( rObj ); + const SdrOle2Obj& rOle2Obj = static_cast< const SdrOle2Obj& >( rObj ); + + uno::Reference < util::XCloseable > xClose( xObjRef.GetObject(), uno::UNO_QUERY ); + + if( pModel && mpImpl->mbConnected ) + Disconnect(); + + SdrRectObj::operator=( rObj ); + + // #108867# Manually copying bClosedObj attribute + SetClosedObj( rObj.IsClosedObj() ); + + mpImpl->aPersistName = rOle2Obj.mpImpl->aPersistName; + aProgName = rOle2Obj.aProgName; + bFrame = rOle2Obj.bFrame; + + if( rOle2Obj.pGraphic ) + { + if( pGraphic ) + { + delete pGraphic; + delete mpImpl->pGraphicObject; + } + + pGraphic = new Graphic( *rOle2Obj.pGraphic ); + mpImpl->pGraphicObject = new GraphicObject( *pGraphic ); + } + + if( pModel && rObj.GetModel() && !IsEmptyPresObj() ) + { + ::comphelper::IEmbeddedHelper* pDestPers = pModel->GetPersist(); + ::comphelper::IEmbeddedHelper* pSrcPers = rObj.GetModel()->GetPersist(); + if( pDestPers && pSrcPers ) + { + DBG_ASSERT( !xObjRef.is(), "Object already existing!" ); + comphelper::EmbeddedObjectContainer& rContainer = pSrcPers->getEmbeddedObjectContainer(); + uno::Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( mpImpl->aPersistName ); + if ( xObj.is() ) + { + ::rtl::OUString aTmp; + xObjRef.Assign( pDestPers->getEmbeddedObjectContainer().CopyAndGetEmbeddedObject( rContainer, xObj, aTmp ), rOle2Obj.GetAspect() ); + m_bTypeAsked = false; + mpImpl->aPersistName = aTmp; + CheckFileLink_Impl(); + } + + Connect(); + + /* only needed for MSOLE-Objects, now handled inside implementation of Object + if ( xObjRef.is() && rOle2Obj.xObjRef.is() && rOle2Obj.GetAspect() != embed::Aspects::MSOLE_ICON ) + { + try + { + awt::Size aVisSize = rOle2Obj.xObjRef->getVisualAreaSize( rOle2Obj.GetAspect() ); + if( rOle2Obj.xObjRef->getMapUnit( rOle2Obj.GetAspect() ) == xObjRef->getMapUnit( GetAspect() ) ) + xObjRef->setVisualAreaSize( GetAspect(), aVisSize ); + } + catch ( embed::WrongStateException& ) + { + // setting of VisArea not necessary for objects that don't cache it in loaded state + } + catch( embed::NoVisualAreaSizeException& ) + { + // objects my not have visual areas + } + catch( uno::Exception& e ) + { + (void)e; + DBG_ERROR( "SdrOle2Obj::operator=(), unexcpected exception caught!" ); + } + } */ + } + } + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::ImpSetVisAreaSize() +{ + // currently there is no need to recalculate scaling for iconified objects + // TODO/LATER: it might be needed in future when it is possible to change the icon + if ( GetAspect() == embed::Aspects::MSOLE_ICON ) + return; + + // the object area of an embedded object was changed, e.g. by user interaction an a selected object + GetObjRef(); + if ( xObjRef.is() ) + { + OSL_ASSERT( pModel ); + sal_Int64 nMiscStatus = xObjRef->getStatus( GetAspect() ); + + // the client is required to get access to scaling + SfxInPlaceClient* pClient = SfxInPlaceClient::GetClient( dynamic_cast<SfxObjectShell*>(pModel->GetPersist()), xObjRef.GetObject() ); + sal_Bool bHasOwnClient = + ( mpImpl->pLightClient + && xObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->pLightClient ) ); + + if ( pClient || bHasOwnClient ) + { + // TODO/LATER: IMHO we need to do similar things when object is UIActive or OutplaceActive?! (MBA) + if ( ((nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) && + svt::EmbeddedObjectRef::TryRunningState( xObjRef.GetObject() )) + || xObjRef->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE + ) + { + Fraction aScaleWidth; + Fraction aScaleHeight; + if ( pClient ) + { + aScaleWidth = pClient->GetScaleWidth(); + aScaleHeight = pClient->GetScaleHeight(); + } + else + { + aScaleWidth = mpImpl->pLightClient->GetScaleWidth(); + aScaleHeight = mpImpl->pLightClient->GetScaleHeight(); + } + + // The object wants to resize itself (f.e. Chart wants to recalculate the layout) + // or object is inplace active and so has a window that must be resized also + // In these cases the change in the object area size will be reflected in a change of the + // objects' visual area. The scaling will not change, but it might exist already and must + // be used in calculations + MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObjRef->getMapUnit( GetAspect() ) ); + Size aVisSize( (long)( Fraction( aRect.GetWidth() ) / aScaleWidth ), + (long)( Fraction( aRect.GetHeight() ) / aScaleHeight ) ); + + aVisSize = OutputDevice::LogicToLogic( aVisSize, pModel->GetScaleUnit(), aMapUnit); + awt::Size aSz; + aSz.Width = aVisSize.Width(); + aSz.Height = aVisSize.Height(); + xObjRef->setVisualAreaSize( GetAspect(), aSz ); + + try + { + aSz = xObjRef->getVisualAreaSize( GetAspect() ); + } + catch( embed::NoVisualAreaSizeException& ) + {} + + Rectangle aAcceptedVisArea; + aAcceptedVisArea.SetSize( Size( (long)( Fraction( long( aSz.Width ) ) * aScaleWidth ), + (long)( Fraction( long( aSz.Height ) ) * aScaleHeight ) ) ); + if (aVisSize != aAcceptedVisArea.GetSize()) + { + // server changed VisArea to its liking and the VisArea is different than the suggested one + // store the new value as given by the object + MapUnit aNewMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObjRef->getMapUnit( GetAspect() ) ); + aRect.SetSize(OutputDevice::LogicToLogic( aAcceptedVisArea.GetSize(), aNewMapUnit, pModel->GetScaleUnit())); + } + + // make the new object area known to the client + // compared to the "else" branch aRect might have been changed by the object and no additional scaling was applied + // OJ: WHY this -> OSL_ASSERT( pClient ); + if( pClient ) + pClient->SetObjArea(aRect); + + // we need a new replacement image as the object has resized itself + + //#i79578# don't request a new replacement image for charts to often + //a chart sends a modified call to the framework if it was changed + //thus the replacement update is already handled there + if( !IsChart() ) + xObjRef.UpdateReplacement(); + } + else + { + // The object isn't active and does not want to resize itself so the changed object area size + // will be reflected in a changed object scaling + Fraction aScaleWidth; + Fraction aScaleHeight; + Size aObjAreaSize; + if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) ) + { + if ( pClient ) + { + Rectangle aScaleRect(aRect.TopLeft(), aObjAreaSize); + pClient->SetObjAreaAndScale( aScaleRect, aScaleWidth, aScaleHeight); + } + else + { + mpImpl->pLightClient->SetSizeScale( aScaleWidth, aScaleHeight ); + } + } + } + } + else if( (nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) && + svt::EmbeddedObjectRef::TryRunningState( xObjRef.GetObject() ) ) + { + //also handle not sfx based ole objects e.g. charts + //#i83860# resizing charts in impress distorts fonts + uno::Reference< embed::XVisualObject > xVisualObject( this->getXModel(), uno::UNO_QUERY ); + if( xVisualObject.is() ) + { + MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObjRef->getMapUnit( GetAspect() ) ); + Point aTL( aRect.TopLeft() ); + Point aBR( aRect.BottomRight() ); + Point aTL2( OutputDevice::LogicToLogic( aTL, pModel->GetScaleUnit(), aMapUnit) ); + Point aBR2( OutputDevice::LogicToLogic( aBR, pModel->GetScaleUnit(), aMapUnit) ); + Rectangle aNewRect( aTL2, aBR2 ); + xVisualObject->setVisualAreaSize( GetAspect(), awt::Size( aNewRect.GetWidth(), aNewRect.GetHeight() ) ); + } + } + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + if( pModel && !pModel->isLocked() ) + { + GetObjRef(); + if ( xObjRef.is() && ( xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) ) + { + // if the object needs recompose on resize + // the client site should be created before the resize will take place + // check whether there is no client site and create it if necessary + AddOwnLightClient(); + } + } + + SdrRectObj::NbcResize(rRef,xFact,yFact); + if (aGeo.nShearWink!=0 || aGeo.nDrehWink!=0) { // kleine Korrekturen + if (aGeo.nDrehWink>=9000 && aGeo.nDrehWink<27000) { + aRect.Move(aRect.Left()-aRect.Right(),aRect.Top()-aRect.Bottom()); + } + aGeo.nDrehWink=0; + aGeo.nShearWink=0; + aGeo.nSin=0.0; + aGeo.nCos=1.0; + aGeo.nTan=0.0; + SetRectsDirty(); + } + if( pModel && !pModel->isLocked() ) + ImpSetVisAreaSize(); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::SetGeoData(const SdrObjGeoData& rGeo) +{ + SdrRectObj::SetGeoData(rGeo); + if( pModel && !pModel->isLocked() ) + ImpSetVisAreaSize(); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::NbcSetSnapRect(const Rectangle& rRect) +{ + SdrRectObj::NbcSetSnapRect(rRect); + if( pModel && !pModel->isLocked() ) + ImpSetVisAreaSize(); + + if ( xObjRef.is() && IsChart() ) + { + //#i103460# charts do not necessaryly have an own size within ODF files, + //for this case they need to use the size settings from the surrounding frame, + //which is made available with this method as there is no other way + xObjRef.SetDefaultSizeForChart( Size( rRect.GetWidth(), rRect.GetHeight() ) ); + } +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::NbcSetLogicRect(const Rectangle& rRect) +{ + SdrRectObj::NbcSetLogicRect(rRect); + if( pModel && !pModel->isLocked() ) + ImpSetVisAreaSize(); +} + +Graphic* SdrOle2Obj::GetGraphic() const +{ + if ( xObjRef.is() ) + return xObjRef.GetGraphic(); + return pGraphic; +} + +void SdrOle2Obj::GetNewReplacement() +{ + if ( xObjRef.is() ) + xObjRef.UpdateReplacement(); +} + +// ----------------------------------------------------------------------------- + +Size SdrOle2Obj::GetOrigObjSize( MapMode* pTargetMapMode ) const +{ + return xObjRef.GetSize( pTargetMapMode ); +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::NbcMove(const Size& rSize) +{ + SdrRectObj::NbcMove(rSize); + if( pModel && !pModel->isLocked() ) + ImpSetVisAreaSize(); +} + +// ----------------------------------------------------------------------------- + +sal_Bool SdrOle2Obj::CanUnloadRunningObj( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ) +{ + sal_Bool bResult = sal_False; + + sal_Int32 nState = xObj->getCurrentState(); + if ( nState == embed::EmbedStates::LOADED ) + { + // the object is already unloaded + bResult = sal_True; + } + else + { + uno::Reference < util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); + if ( !xModifiable.is() ) + bResult = sal_True; + else + { + sal_Int64 nMiscStatus = xObj->getStatus( nAspect ); + + if ( embed::EmbedMisc::MS_EMBED_ALWAYSRUN != ( nMiscStatus & embed::EmbedMisc::MS_EMBED_ALWAYSRUN ) && + embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY != ( nMiscStatus & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) && + !( xModifiable.is() && xModifiable->isModified() ) && + !( nState == embed::EmbedStates::INPLACE_ACTIVE || nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::ACTIVE ) ) + { + bResult = sal_True; + } + } + } + + return bResult; +} + +// ----------------------------------------------------------------------------- + +sal_Bool SdrOle2Obj::Unload( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ) +{ + sal_Bool bResult = sal_False; + + if ( CanUnloadRunningObj( xObj, nAspect ) ) + { + try + { + xObj->changeState( embed::EmbedStates::LOADED ); + bResult = sal_True; + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("SdrOle2Obj::Unload=(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } + + return bResult; +} + +// ----------------------------------------------------------------------------- + +BOOL SdrOle2Obj::Unload() +{ + BOOL bUnloaded = FALSE; + + if( xObjRef.is() ) + { + //TODO/LATER: no refcounting tricks anymore! + //"customers" must register as state change listeners + //Nicht notwendig im Doc DTor (MM) + //ULONG nRefCount = (*ppObjRef)->GetRefCount(); + // prevent Unload if there are external references + //if( nRefCount > 2 ) + // return FALSE; + //DBG_ASSERT( nRefCount == 2, "Wrong RefCount for unload" ); + } + else + bUnloaded = TRUE; + + if ( pModel && xObjRef.is() ) + { + bUnloaded = Unload( xObjRef.GetObject(), GetAspect() ); + } + + return bUnloaded; +} + +// ----------------------------------------------------------------------------- + +void SdrOle2Obj::GetObjRef_Impl() +{ + if ( !xObjRef.is() && mpImpl->aPersistName.Len() && pModel && pModel->GetPersist() ) + { + // #107645# + // Only try loading if it did not went wrong up to now + if(!mpImpl->mbLoadingOLEObjectFailed) + { + xObjRef.Assign( pModel->GetPersist()->getEmbeddedObjectContainer().GetEmbeddedObject( mpImpl->aPersistName ), GetAspect() ); + m_bTypeAsked = false; + CheckFileLink_Impl(); + + // #107645# + // If loading of OLE object failed, remember that to not invoke a endless + // loop trying to load it again and again. + if( xObjRef.is() ) + { + mpImpl->mbLoadingOLEObjectFailed = sal_True; + } + + // #108759# For math objects, set closed state to transparent + if( ImplIsMathObj( xObjRef.GetObject() ) ) + SetClosedObj( false ); + } + + if ( xObjRef.is() ) + { + if( !IsEmptyPresObj() ) + { + // #75637# remember modified status of model + const sal_Bool bWasChanged(pModel ? pModel->IsChanged() : sal_False); + + // perhaps preview not valid anymore + // #75637# This line changes the modified state of the model + SetGraphic_Impl( NULL ); + + // #75637# if status was not set before, force it back + // to not set, so that SetGraphic(0L) above does not + // set the modified state of the model. + if(!bWasChanged && pModel && pModel->IsChanged()) + { + pModel->SetChanged( sal_False ); + } + } + + sal_Int64 nMiscStatus = xObjRef->getStatus( GetAspect() ); + (void)nMiscStatus; + //TODO/LATER: wait until ResizeOnPrinterChange is defined + //if ( nMiscStatus & SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE ) + { + if (pModel && pModel->GetRefDevice() && + pModel->GetRefDevice()->GetOutDevType() == OUTDEV_PRINTER) + { + if(!bInDestruction) + { + //TODO/LATER: printerchange notification + /* + // prevent SetModified (don't want no update here) + sal_Bool bWasEnabled = (*ppObjRef)->IsEnableSetModified(); + if ( bWasEnabled ) + (*ppObjRef)->EnableSetModified( sal_False ); + + // Kein RefDevice oder RefDevice kein Printer + Printer* pPrinter = (Printer*) pModel->GetRefDevice(); + (*ppObjRef)->OnDocumentPrinterChanged( pPrinter ); + + // reset state + (*ppObjRef)->EnableSetModified( bWasEnabled );*/ + } + } + } + } + + if ( xObjRef.is() ) + Connect(); + } + + if ( mpImpl->mbConnected ) + // move object to first position in cache + GetSdrGlobalData().GetOLEObjCache().InsertObj(this); +} + +uno::Reference < embed::XEmbeddedObject > SdrOle2Obj::GetObjRef() const +{ + const_cast<SdrOle2Obj*>(this)->GetObjRef_Impl(); + return xObjRef.GetObject(); +} + +uno::Reference < embed::XEmbeddedObject > SdrOle2Obj::GetObjRef_NoInit() const +{ + return xObjRef.GetObject(); +} + +// ----------------------------------------------------------------------------- + +uno::Reference< frame::XModel > SdrOle2Obj::getXModel() const +{ + GetObjRef(); + if ( svt::EmbeddedObjectRef::TryRunningState(xObjRef.GetObject()) ) + return uno::Reference< frame::XModel >( xObjRef->getComponent(), uno::UNO_QUERY ); + else + return uno::Reference< frame::XModel >(); +} + +// ----------------------------------------------------------------------------- + +// #109985# +sal_Bool SdrOle2Obj::IsChart() const +{ + if ( !m_bTypeAsked ) + { + m_bChart = ChartPrettyPainter::IsChart(xObjRef); + m_bTypeAsked = true; + } + return m_bChart; +} + +// ----------------------------------------------------------------------------- +void SdrOle2Obj::SetGraphicToObj( const Graphic& aGraphic, const ::rtl::OUString& aMediaType ) +{ + xObjRef.SetGraphic( aGraphic, aMediaType ); +} + +// ----------------------------------------------------------------------------- +void SdrOle2Obj::SetGraphicToObj( const uno::Reference< io::XInputStream >& xGrStream, const ::rtl::OUString& aMediaType ) +{ + xObjRef.SetGraphicStream( xGrStream, aMediaType ); +} + +// ----------------------------------------------------------------------------- +sal_Bool SdrOle2Obj::IsCalc() const +{ + if ( !xObjRef.is() ) + return false; + + SvGlobalName aObjClsId( xObjRef->getClassID() ); + if( SvGlobalName(SO3_SC_CLASSID_30) == aObjClsId + || SvGlobalName(SO3_SC_CLASSID_40) == aObjClsId + || SvGlobalName(SO3_SC_CLASSID_50) == aObjClsId + || SvGlobalName(SO3_SC_CLASSID_60) == aObjClsId + || SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_60) == aObjClsId + || SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_8) == aObjClsId + || SvGlobalName(SO3_SC_CLASSID) == aObjClsId ) + { + return sal_True; + } + + return sal_False; +} + +// ----------------------------------------------------------------------------- +uno::Reference< frame::XModel > SdrOle2Obj::GetParentXModel() const +{ + uno::Reference< frame::XModel > xDoc; + if ( pModel ) + xDoc.set( pModel->getUnoModel(),uno::UNO_QUERY); + return xDoc; +} + +// ----------------------------------------------------------------------------- +sal_Bool SdrOle2Obj::CalculateNewScaling( Fraction& aScaleWidth, Fraction& aScaleHeight, Size& aObjAreaSize ) +{ + // TODO/LEAN: to avoid rounding errors scaling always uses the VisArea. + // If we don't cache it for own objects also we must load the object here + if ( !xObjRef.is() || !pModel ) + return sal_False; + + MapMode aMapMode( pModel->GetScaleUnit() ); + aObjAreaSize = xObjRef.GetSize( &aMapMode ); + + Size aSize = aRect.GetSize(); + aScaleWidth = Fraction(aSize.Width(), aObjAreaSize.Width() ); + aScaleHeight = Fraction(aSize.Height(), aObjAreaSize.Height() ); + + // reduce to 10 binary digits + Kuerzen(aScaleHeight, 10); + Kuerzen(aScaleWidth, 10); + + return sal_True; +} + +// ----------------------------------------------------------------------------- +sal_Bool SdrOle2Obj::AddOwnLightClient() +{ + // The Own Light Client must be registered in object only using this method! + if ( !SfxInPlaceClient::GetClient( dynamic_cast<SfxObjectShell*>(pModel->GetPersist()), xObjRef.GetObject() ) + && !( mpImpl->pLightClient && xObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->pLightClient ) ) ) + { + Connect(); + + if ( xObjRef.is() && mpImpl->pLightClient ) + { + Fraction aScaleWidth; + Fraction aScaleHeight; + Size aObjAreaSize; + if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) ) + { + mpImpl->pLightClient->SetSizeScale( aScaleWidth, aScaleHeight ); + try { + xObjRef->setClientSite( mpImpl->pLightClient ); + return sal_True; + } catch( uno::Exception& ) + {} + } + + } + + return sal_False; + } + + return sal_True; +} + +////////////////////////////////////////////////////////////////////////////// + +Bitmap SdrOle2Obj::GetEmtyOLEReplacementBitmap() +{ + return Bitmap(ResId(BMP_SVXOLEOBJ, *ImpGetResMgr())); +} + +////////////////////////////////////////////////////////////////////////////// + +void SdrOle2Obj::SetWindow(const com::sun::star::uno::Reference < com::sun::star::awt::XWindow >& _xWindow) +{ + if ( xObjRef.is() && mpImpl->pLightClient ) + { + mpImpl->pLightClient->setWindow(_xWindow); + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdopage.cxx b/svx/source/svdraw/svdopage.cxx new file mode 100644 index 000000000000..a2d21e6e2269 --- /dev/null +++ b/svx/source/svdraw/svdopage.cxx @@ -0,0 +1,195 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdopage.hxx> +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdoutl.hxx> +#include <svtools/colorcfg.hxx> +#include <svl/itemset.hxx> +#include <svx/sdr/properties/pageproperties.hxx> + +// #111111# +#include <svx/sdr/contact/viewcontactofpageobj.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrPageObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::PageProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrPageObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfPageObj(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// this method is called form the destructor of the referenced page. +// do all necessary action to forget the page. It is not necessary to call +// RemovePageUser(), that is done form the destructor. +void SdrPageObj::PageInDestruction(const SdrPage& rPage) +{ + if(mpShownPage && mpShownPage == &rPage) + { + // #i58769# Do not call ActionChanged() here, because that would + // lead to the construction of a view contact object for a page that + // is being destroyed. + + mpShownPage = 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrPageObj,SdrObject); + +SdrPageObj::SdrPageObj(SdrPage* pNewPage) +: mpShownPage(pNewPage) +{ + if(mpShownPage) + { + mpShownPage->AddPageUser(*this); + } +} + +SdrPageObj::SdrPageObj(const Rectangle& rRect, SdrPage* pNewPage) +: mpShownPage(pNewPage) +{ + if(mpShownPage) + { + mpShownPage->AddPageUser(*this); + } + + aOutRect = rRect; +} + +SdrPageObj::~SdrPageObj() +{ + // #111111# + if(mpShownPage) + { + mpShownPage->RemovePageUser(*this); + } +} + +// #111111# +SdrPage* SdrPageObj::GetReferencedPage() const +{ + return mpShownPage; +} + +// #111111# +void SdrPageObj::SetReferencedPage(SdrPage* pNewPage) +{ + if(mpShownPage != pNewPage) + { + if(mpShownPage) + { + mpShownPage->RemovePageUser(*this); + } + + mpShownPage = pNewPage; + + if(mpShownPage) + { + mpShownPage->AddPageUser(*this); + } + + SetChanged(); + BroadcastObjectChange(); + } +} + +// #i96598# +void SdrPageObj::SetBoundRectDirty() +{ + // avoid resetting aOutRect which in case of this object is model data, + // not re-creatable view data +} + +UINT16 SdrPageObj::GetObjIdentifier() const +{ + return UINT16(OBJ_PAGE); +} + +void SdrPageObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bRotateFreeAllowed=FALSE; + rInfo.bRotate90Allowed =FALSE; + rInfo.bMirrorFreeAllowed=FALSE; + rInfo.bMirror45Allowed =FALSE; + rInfo.bMirror90Allowed =FALSE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =FALSE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bNoOrthoDesired =FALSE; + rInfo.bCanConvToPath =FALSE; + rInfo.bCanConvToPoly =FALSE; + rInfo.bCanConvToPathLineToArea=FALSE; + rInfo.bCanConvToPolyLineToArea=FALSE; +} + +void SdrPageObj::operator=(const SdrObject& rObj) +{ + SdrObject::operator=(rObj); + SetReferencedPage(((const SdrPageObj&)rObj).GetReferencedPage()); +} + +void SdrPageObj::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulPAGE); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrPageObj::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralPAGE); +} + +// eof diff --git a/svx/source/svdraw/svdopath.cxx b/svx/source/svdraw/svdopath.cxx new file mode 100644 index 000000000000..2b495725c006 --- /dev/null +++ b/svx/source/svdraw/svdopath.cxx @@ -0,0 +1,3117 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <tools/bigint.hxx> +#include <svx/svdopath.hxx> +#include <math.h> +#include <svx/xpool.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svddrag.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdhdl.hxx> +#include <svx/svdview.hxx> // fuer MovCreate bei Freihandlinien +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname + +#ifdef _MSC_VER +#pragma optimize ("",off) +#pragma warning(disable: 4748) // "... because optimizations are disabled ..." +#endif + +#include <svx/xlnwtit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xflclit.hxx> +#include <svx/svdogrp.hxx> +#include <svx/polypolygoneditor.hxx> +#include <svx/xlntrit.hxx> +#include <vcl/salbtype.hxx> // FRound +#include "svdoimp.hxx" +#include <svx/sdr/contact/viewcontactofsdrpathobj.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> + +// #104018# replace macros above with type-safe methods +inline sal_Int32 ImplTwipsToMM(sal_Int32 nVal) { return ((nVal * 127 + 36) / 72); } +inline sal_Int32 ImplMMToTwips(sal_Int32 nVal) { return ((nVal * 72 + 63) / 127); } +inline sal_Int64 ImplTwipsToMM(sal_Int64 nVal) { return ((nVal * 127 + 36) / 72); } +inline sal_Int64 ImplMMToTwips(sal_Int64 nVal) { return ((nVal * 72 + 63) / 127); } +inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } +inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/curve/b2dcubicbezier.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <svx/sdr/attribute/sdrtextattribute.hxx> +#include <svx/sdr/primitive2d/sdrattributecreator.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <svx/sdr/attribute/sdrformtextattribute.hxx> + +using namespace sdr; + +inline USHORT GetPrevPnt(USHORT nPnt, USHORT nPntMax, FASTBOOL bClosed) +{ + if (nPnt>0) { + nPnt--; + } else { + nPnt=nPntMax; + if (bClosed) nPnt--; + } + return nPnt; +} + +inline USHORT GetNextPnt(USHORT nPnt, USHORT nPntMax, FASTBOOL bClosed) +{ + nPnt++; + if (nPnt>nPntMax || (bClosed && nPnt>=nPntMax)) nPnt=0; + return nPnt; +} + +struct ImpSdrPathDragData : public SdrDragStatUserData +{ + XPolygon aXP; // Ausschnitt aud dem Originalpolygon + FASTBOOL bValid; // FALSE = zu wenig Punkte + FASTBOOL bClosed; // geschlossenes Objekt? + USHORT nPoly; // Nummer des Polygons im PolyPolygon + USHORT nPnt; // Punktnummer innerhalb des obigen Polygons + USHORT nPntAnz; // Punktanzahl des Polygons + USHORT nPntMax; // Maximaler Index + FASTBOOL bBegPnt; // Gedraggter Punkt ist der Anfangspunkt einer Polyline + FASTBOOL bEndPnt; // Gedraggter Punkt ist der Endpunkt einer Polyline + USHORT nPrevPnt; // Index des vorherigen Punkts + USHORT nNextPnt; // Index des naechsten Punkts + FASTBOOL bPrevIsBegPnt; // Vorheriger Punkt ist Anfangspunkt einer Polyline + FASTBOOL bNextIsEndPnt; // Folgepunkt ist Endpunkt einer Polyline + USHORT nPrevPrevPnt; // Index des vorvorherigen Punkts + USHORT nNextNextPnt; // Index des uebernaechsten Punkts + FASTBOOL bControl; // Punkt ist ein Kontrollpunkt + FASTBOOL bIsPrevControl; // Punkt ist Kontrollpunkt vor einem Stuetzpunkt + FASTBOOL bIsNextControl; // Punkt ist Kontrollpunkt hinter einem Stuetzpunkt + FASTBOOL bPrevIsControl; // Falls nPnt ein StPnt: Davor ist ein Kontrollpunkt + FASTBOOL bNextIsControl; // Falls nPnt ein StPnt: Dahinter ist ein Kontrollpunkt + USHORT nPrevPrevPnt0; + USHORT nPrevPnt0; + USHORT nPnt0; + USHORT nNextPnt0; + USHORT nNextNextPnt0; + FASTBOOL bEliminate; // Punkt loeschen? (wird von MovDrag gesetzt) + + // ## + BOOL mbMultiPointDrag; + const XPolyPolygon maOrig; + XPolyPolygon maMove; + Container maHandles; + +public: + ImpSdrPathDragData(const SdrPathObj& rPO, const SdrHdl& rHdl, BOOL bMuPoDr, const SdrDragStat& rDrag); + void ResetPoly(const SdrPathObj& rPO); + BOOL IsMultiPointDrag() const { return mbMultiPointDrag; } +}; + +ImpSdrPathDragData::ImpSdrPathDragData(const SdrPathObj& rPO, const SdrHdl& rHdl, BOOL bMuPoDr, const SdrDragStat& rDrag) +: aXP(5), + mbMultiPointDrag(bMuPoDr), + maOrig(rPO.GetPathPoly()), + maHandles(0) +{ + if(mbMultiPointDrag) + { + const SdrMarkView& rMarkView = *rDrag.GetView(); + const SdrHdlList& rHdlList = rMarkView.GetHdlList(); + const sal_uInt32 nHdlCount = rHdlList.GetHdlCount(); + const SdrObject* pInteractionObject(nHdlCount && rHdlList.GetHdl(0) ? rHdlList.GetHdl(0)->GetObj() : 0); + + for(sal_uInt32 a(0); a < nHdlCount; a++) + { + SdrHdl* pTestHdl = rHdlList.GetHdl(a); + + if(pTestHdl && pTestHdl->IsSelected() && pTestHdl->GetObj() == pInteractionObject) + { + maHandles.Insert(pTestHdl, CONTAINER_APPEND); + } + } + + maMove = maOrig; + bValid = TRUE; + } + else + { + bValid=FALSE; + bClosed=rPO.IsClosed(); // geschlossenes Objekt? + nPoly=(sal_uInt16)rHdl.GetPolyNum(); // Nummer des Polygons im PolyPolygon + nPnt=(sal_uInt16)rHdl.GetPointNum(); // Punktnummer innerhalb des obigen Polygons + const XPolygon aTmpXP(rPO.GetPathPoly().getB2DPolygon(nPoly)); + nPntAnz=aTmpXP.GetPointCount(); // Punktanzahl des Polygons + if (nPntAnz==0 || (bClosed && nPntAnz==1)) return; // min. 1Pt bei Line, min. 2 bei Polygon + nPntMax=nPntAnz-1; // Maximaler Index + bBegPnt=!bClosed && nPnt==0; // Gedraggter Punkt ist der Anfangspunkt einer Polyline + bEndPnt=!bClosed && nPnt==nPntMax; // Gedraggter Punkt ist der Endpunkt einer Polyline + if (bClosed && nPntAnz<=3) { // Falls Polygon auch nur eine Linie ist + bBegPnt=(nPntAnz<3) || nPnt==0; + bEndPnt=(nPntAnz<3) || nPnt==nPntMax-1; + } + nPrevPnt=nPnt; // Index des vorherigen Punkts + nNextPnt=nPnt; // Index des naechsten Punkts + if (!bBegPnt) nPrevPnt=GetPrevPnt(nPnt,nPntMax,bClosed); + if (!bEndPnt) nNextPnt=GetNextPnt(nPnt,nPntMax,bClosed); + bPrevIsBegPnt=bBegPnt || (!bClosed && nPrevPnt==0); + bNextIsEndPnt=bEndPnt || (!bClosed && nNextPnt==nPntMax); + nPrevPrevPnt=nPnt; // Index des vorvorherigen Punkts + nNextNextPnt=nPnt; // Index des uebernaechsten Punkts + if (!bPrevIsBegPnt) nPrevPrevPnt=GetPrevPnt(nPrevPnt,nPntMax,bClosed); + if (!bNextIsEndPnt) nNextNextPnt=GetNextPnt(nNextPnt,nPntMax,bClosed); + bControl=rHdl.IsPlusHdl(); // Punkt ist ein Kontrollpunkt + bIsPrevControl=FALSE; // Punkt ist Kontrollpunkt vor einem Stuetzpunkt + bIsNextControl=FALSE; // Punkt ist Kontrollpunkt hinter einem Stuetzpunkt + bPrevIsControl=FALSE; // Falls nPnt ein StPnt: Davor ist ein Kontrollpunkt + bNextIsControl=FALSE; // Falls nPnt ein StPnt: Dahinter ist ein Kontrollpunkt + if (bControl) { + bIsPrevControl=aTmpXP.IsControl(nPrevPnt); + bIsNextControl=!bIsPrevControl; + } else { + bPrevIsControl=!bBegPnt && !bPrevIsBegPnt && aTmpXP.GetFlags(nPrevPnt)==XPOLY_CONTROL; + bNextIsControl=!bEndPnt && !bNextIsEndPnt && aTmpXP.GetFlags(nNextPnt)==XPOLY_CONTROL; + } + nPrevPrevPnt0=nPrevPrevPnt; + nPrevPnt0 =nPrevPnt; + nPnt0 =nPnt; + nNextPnt0 =nNextPnt; + nNextNextPnt0=nNextNextPnt; + nPrevPrevPnt=0; + nPrevPnt=1; + nPnt=2; + nNextPnt=3; + nNextNextPnt=4; + bEliminate=FALSE; + ResetPoly(rPO); + bValid=TRUE; + } +} + +void ImpSdrPathDragData::ResetPoly(const SdrPathObj& rPO) +{ + const XPolygon aTmpXP(rPO.GetPathPoly().getB2DPolygon(nPoly)); + aXP[0]=aTmpXP[nPrevPrevPnt0]; aXP.SetFlags(0,aTmpXP.GetFlags(nPrevPrevPnt0)); + aXP[1]=aTmpXP[nPrevPnt0]; aXP.SetFlags(1,aTmpXP.GetFlags(nPrevPnt0)); + aXP[2]=aTmpXP[nPnt0]; aXP.SetFlags(2,aTmpXP.GetFlags(nPnt0)); + aXP[3]=aTmpXP[nNextPnt0]; aXP.SetFlags(3,aTmpXP.GetFlags(nNextPnt0)); + aXP[4]=aTmpXP[nNextNextPnt0]; aXP.SetFlags(4,aTmpXP.GetFlags(nNextNextPnt0)); +} + +/*************************************************************************/ + +struct ImpPathCreateUser : public SdrDragStatUserData +{ + Point aBezControl0; + Point aBezStart; + Point aBezCtrl1; + Point aBezCtrl2; + Point aBezEnd; + Point aCircStart; + Point aCircEnd; + Point aCircCenter; + Point aLineStart; + Point aLineEnd; + Point aRectP1; + Point aRectP2; + Point aRectP3; + long nCircRadius; + long nCircStWink; + long nCircRelWink; + FASTBOOL bBezier; + FASTBOOL bBezHasCtrl0; + FASTBOOL bCurve; + FASTBOOL bCircle; + FASTBOOL bAngleSnap; + FASTBOOL bLine; + FASTBOOL bLine90; + FASTBOOL bRect; + FASTBOOL bMixedCreate; + USHORT nBezierStartPoint; + SdrObjKind eStartKind; + SdrObjKind eAktKind; + +public: + ImpPathCreateUser(): nCircRadius(0),nCircStWink(0),nCircRelWink(0), + bBezier(FALSE),bBezHasCtrl0(FALSE),bCurve(FALSE),bCircle(FALSE),bAngleSnap(FALSE),bLine(FALSE),bLine90(FALSE),bRect(FALSE), + bMixedCreate(FALSE),nBezierStartPoint(0),eStartKind(OBJ_NONE),eAktKind(OBJ_NONE) { } + + void ResetFormFlags() { bBezier=FALSE; bCurve=FALSE; bCircle=FALSE; bLine=FALSE; bRect=FALSE; } + FASTBOOL IsFormFlag() const { return bBezier || bCurve || bCircle || bLine || bRect; } + XPolygon GetFormPoly() const; + FASTBOOL CalcBezier(const Point& rP1, const Point& rP2, const Point& rDir, FASTBOOL bMouseDown); + XPolygon GetBezierPoly() const; + //FASTBOOL CalcCurve(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView) { return FALSE; } + XPolygon GetCurvePoly() const { return XPolygon(); } + FASTBOOL CalcCircle(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView); + XPolygon GetCirclePoly() const; + FASTBOOL CalcLine(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView); + Point CalcLine(const Point& rCsr, long nDirX, long nDirY, SdrView* pView) const; + XPolygon GetLinePoly() const; + FASTBOOL CalcRect(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView); + XPolygon GetRectPoly() const; +}; + +XPolygon ImpPathCreateUser::GetFormPoly() const +{ + if (bBezier) return GetBezierPoly(); + if (bCurve) return GetCurvePoly(); + if (bCircle) return GetCirclePoly(); + if (bLine) return GetLinePoly(); + if (bRect) return GetRectPoly(); + return XPolygon(); +} + +FASTBOOL ImpPathCreateUser::CalcBezier(const Point& rP1, const Point& rP2, const Point& rDir, FASTBOOL bMouseDown) +{ + FASTBOOL bRet=TRUE; + aBezStart=rP1; + aBezCtrl1=rP1+rDir; + aBezCtrl2=rP2; + + // #i21479# + // Also copy the end point when no end point is set yet + if (!bMouseDown || (0L == aBezEnd.X() && 0L == aBezEnd.Y())) aBezEnd=rP2; + + bBezier=bRet; + return bRet; +} + +XPolygon ImpPathCreateUser::GetBezierPoly() const +{ + XPolygon aXP(4); + aXP[0]=aBezStart; aXP.SetFlags(0,XPOLY_SMOOTH); + aXP[1]=aBezCtrl1; aXP.SetFlags(1,XPOLY_CONTROL); + aXP[2]=aBezCtrl2; aXP.SetFlags(2,XPOLY_CONTROL); + aXP[3]=aBezEnd; + return aXP; +} + +FASTBOOL ImpPathCreateUser::CalcCircle(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView) +{ + long nTangAngle=GetAngle(rDir); + aCircStart=rP1; + aCircEnd=rP2; + aCircCenter=rP1; + long dx=rP2.X()-rP1.X(); + long dy=rP2.Y()-rP1.Y(); + long dAngle=GetAngle(Point(dx,dy))-nTangAngle; + dAngle=NormAngle360(dAngle); + long nTmpAngle=NormAngle360(9000-dAngle); + FASTBOOL bRet=nTmpAngle!=9000 && nTmpAngle!=27000; + long nRad=0; + if (bRet) { + double cs=cos(nTmpAngle*nPi180); + double nR=(double)GetLen(Point(dx,dy))/cs/2; + nRad=Abs(Round(nR)); + } + if (dAngle<18000) { + nCircStWink=NormAngle360(nTangAngle-9000); + nCircRelWink=NormAngle360(2*dAngle); + aCircCenter.X()+=Round(nRad*cos((nTangAngle+9000)*nPi180)); + aCircCenter.Y()-=Round(nRad*sin((nTangAngle+9000)*nPi180)); + } else { + nCircStWink=NormAngle360(nTangAngle+9000); + nCircRelWink=-NormAngle360(36000-2*dAngle); + aCircCenter.X()+=Round(nRad*cos((nTangAngle-9000)*nPi180)); + aCircCenter.Y()-=Round(nRad*sin((nTangAngle-9000)*nPi180)); + } + bAngleSnap=pView!=NULL && pView->IsAngleSnapEnabled(); + if (bAngleSnap) { + long nSA=pView->GetSnapAngle(); + if (nSA!=0) { // Winkelfang + FASTBOOL bNeg=nCircRelWink<0; + if (bNeg) nCircRelWink=-nCircRelWink; + nCircRelWink+=nSA/2; + nCircRelWink/=nSA; + nCircRelWink*=nSA; + nCircRelWink=NormAngle360(nCircRelWink); + if (bNeg) nCircRelWink=-nCircRelWink; + } + } + nCircRadius=nRad; + if (nRad==0 || Abs(nCircRelWink)<5) bRet=FALSE; + bCircle=bRet; + return bRet; +} + +XPolygon ImpPathCreateUser::GetCirclePoly() const +{ + if (nCircRelWink>=0) { + XPolygon aXP(aCircCenter,nCircRadius,nCircRadius, + USHORT((nCircStWink+5)/10),USHORT((nCircStWink+nCircRelWink+5)/10),FALSE); + aXP[0]=aCircStart; aXP.SetFlags(0,XPOLY_SMOOTH); + if (!bAngleSnap) aXP[aXP.GetPointCount()-1]=aCircEnd; + return aXP; + } else { + XPolygon aXP(aCircCenter,nCircRadius,nCircRadius, + USHORT(NormAngle360(nCircStWink+nCircRelWink+5)/10),USHORT((nCircStWink+5)/10),FALSE); + USHORT nAnz=aXP.GetPointCount(); + for (USHORT nNum=nAnz/2; nNum>0;) { + nNum--; // XPoly Punktreihenfolge umkehren + USHORT n2=nAnz-nNum-1; + Point aPt(aXP[nNum]); + aXP[nNum]=aXP[n2]; + aXP[n2]=aPt; + } + aXP[0]=aCircStart; aXP.SetFlags(0,XPOLY_SMOOTH); + if (!bAngleSnap) aXP[aXP.GetPointCount()-1]=aCircEnd; + return aXP; + } +} + +Point ImpPathCreateUser::CalcLine(const Point& aCsr, long nDirX, long nDirY, SdrView* pView) const +{ + long x=aCsr.X(),x1=x,x2=x; + long y=aCsr.Y(),y1=y,y2=y; + FASTBOOL bHLin=nDirY==0; + FASTBOOL bVLin=nDirX==0; + if (bHLin) y=0; + else if (bVLin) x=0; + else { + x1=BigMulDiv(y,nDirX,nDirY); + y2=BigMulDiv(x,nDirY,nDirX); + long l1=Abs(x1)+Abs(y1); + long l2=Abs(x2)+Abs(y2); + if ((l1<=l2) != (pView!=NULL && pView->IsBigOrtho())) { + x=x1; y=y1; + } else { + x=x2; y=y2; + } + } + return Point(x,y); +} + +FASTBOOL ImpPathCreateUser::CalcLine(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView) +{ + aLineStart=rP1; + aLineEnd=rP2; + bLine90=FALSE; + if (rP1==rP2 || (rDir.X()==0 && rDir.Y()==0)) { bLine=FALSE; return FALSE; } + Point aTmpPt(rP2-rP1); + long nDirX=rDir.X(); + long nDirY=rDir.Y(); + Point aP1(CalcLine(aTmpPt, nDirX, nDirY,pView)); aP1-=aTmpPt; long nQ1=Abs(aP1.X())+Abs(aP1.Y()); + Point aP2(CalcLine(aTmpPt, nDirY,-nDirX,pView)); aP2-=aTmpPt; long nQ2=Abs(aP2.X())+Abs(aP2.Y()); + if (pView!=NULL && pView->IsOrtho()) nQ1=0; // Ortho schaltet rechtwinklig aus + bLine90=nQ1>2*nQ2; + if (!bLine90) { // glatter Uebergang + aLineEnd+=aP1; + } else { // rechtwinkliger Uebergang + aLineEnd+=aP2; + } + bLine=TRUE; + return TRUE; +} + +XPolygon ImpPathCreateUser::GetLinePoly() const +{ + XPolygon aXP(2); + aXP[0]=aLineStart; if (!bLine90) aXP.SetFlags(0,XPOLY_SMOOTH); + aXP[1]=aLineEnd; + return aXP; +} + +FASTBOOL ImpPathCreateUser::CalcRect(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView) +{ + aRectP1=rP1; + aRectP2=rP1; + aRectP3=rP2; + if (rP1==rP2 || (rDir.X()==0 && rDir.Y()==0)) { bRect=FALSE; return FALSE; } + Point aTmpPt(rP2-rP1); + long nDirX=rDir.X(); + long nDirY=rDir.Y(); + long x=aTmpPt.X(); + long y=aTmpPt.Y(); + FASTBOOL bHLin=nDirY==0; + FASTBOOL bVLin=nDirX==0; + if (bHLin) y=0; + else if (bVLin) x=0; + else { + y=BigMulDiv(x,nDirY,nDirX); + long nHypLen=aTmpPt.Y()-y; + long nTangAngle=-GetAngle(rDir); + // sin=g/h, g=h*sin + double a=nTangAngle*nPi180; + double sn=sin(a); + double cs=cos(a); + double nGKathLen=nHypLen*sn; + y+=Round(nGKathLen*sn); + x+=Round(nGKathLen*cs); + } + aRectP2.X()+=x; + aRectP2.Y()+=y; + if (pView!=NULL && pView->IsOrtho()) { + long dx1=aRectP2.X()-aRectP1.X(); long dx1a=Abs(dx1); + long dy1=aRectP2.Y()-aRectP1.Y(); long dy1a=Abs(dy1); + long dx2=aRectP3.X()-aRectP2.X(); long dx2a=Abs(dx2); + long dy2=aRectP3.Y()-aRectP2.Y(); long dy2a=Abs(dy2); + FASTBOOL b1MoreThan2=dx1a+dy1a>dx2a+dy2a; + if (b1MoreThan2 != pView->IsBigOrtho()) { + long xtemp=dy2a-dx1a; if (dx1<0) xtemp=-xtemp; + long ytemp=dx2a-dy1a; if (dy1<0) ytemp=-ytemp; + aRectP2.X()+=xtemp; + aRectP2.Y()+=ytemp; + aRectP3.X()+=xtemp; + aRectP3.Y()+=ytemp; + } else { + long xtemp=dy1a-dx2a; if (dx2<0) xtemp=-xtemp; + long ytemp=dx1a-dy2a; if (dy2<0) ytemp=-ytemp; + aRectP3.X()+=xtemp; + aRectP3.Y()+=ytemp; + } + } + bRect=TRUE; + return TRUE; +} + +XPolygon ImpPathCreateUser::GetRectPoly() const +{ + XPolygon aXP(3); + aXP[0]=aRectP1; aXP.SetFlags(0,XPOLY_SMOOTH); + aXP[1]=aRectP2; + if (aRectP3!=aRectP2) aXP[2]=aRectP3; + return aXP; +} + +/*************************************************************************/ + +class ImpPathForDragAndCreate +{ + SdrPathObj& mrSdrPathObject; + XPolyPolygon aPathPolygon; + SdrObjKind meObjectKind; + ImpSdrPathDragData* mpSdrPathDragData; + bool mbCreating; + +public: + ImpPathForDragAndCreate(SdrPathObj& rSdrPathObject); + ~ImpPathForDragAndCreate(); + + // drag stuff + bool beginPathDrag( SdrDragStat& rDrag ) const; + bool movePathDrag( SdrDragStat& rDrag ) const; + bool endPathDrag( SdrDragStat& rDrag ); + //void cancelSpecialDrag( SdrDragStat& rDrag ) const; + String getSpecialDragComment(const SdrDragStat& rDrag) const; + basegfx::B2DPolyPolygon getSpecialDragPoly(const SdrDragStat& rDrag) const; + + // create stuff + FASTBOOL BegCreate(SdrDragStat& rStat); + FASTBOOL MovCreate(SdrDragStat& rStat); + FASTBOOL EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd); + FASTBOOL BckCreate(SdrDragStat& rStat); + void BrkCreate(SdrDragStat& rStat); + Pointer GetCreatePointer() const; + + // helping stuff + bool IsClosed(SdrObjKind eKind) const { return eKind==OBJ_POLY || eKind==OBJ_PATHPOLY || eKind==OBJ_PATHFILL || eKind==OBJ_FREEFILL || eKind==OBJ_SPLNFILL; } + bool IsFreeHand(SdrObjKind eKind) const { return eKind==OBJ_FREELINE || eKind==OBJ_FREEFILL; } + bool IsBezier(SdrObjKind eKind) const { return eKind==OBJ_PATHLINE || eKind==OBJ_PATHFILL; } + bool IsCreating() const { return mbCreating; } + + // get the polygon + basegfx::B2DPolyPolygon TakeObjectPolyPolygon(const SdrDragStat& rDrag) const; + basegfx::B2DPolyPolygon TakeDragPolyPolygon(const SdrDragStat& rDrag) const; + basegfx::B2DPolyPolygon getModifiedPolyPolygon() const { return aPathPolygon.getB2DPolyPolygon(); } +}; + +ImpPathForDragAndCreate::ImpPathForDragAndCreate(SdrPathObj& rSdrPathObject) +: mrSdrPathObject(rSdrPathObject), + aPathPolygon(rSdrPathObject.GetPathPoly()), + meObjectKind(mrSdrPathObject.meKind), + mpSdrPathDragData(0), + mbCreating(false) +{ +} + +ImpPathForDragAndCreate::~ImpPathForDragAndCreate() +{ + if(mpSdrPathDragData) + { + delete mpSdrPathDragData; + } +} + +bool ImpPathForDragAndCreate::beginPathDrag( SdrDragStat& rDrag ) const +{ + const SdrHdl* pHdl=rDrag.GetHdl(); + if(!pHdl) + return FALSE; + + BOOL bMultiPointDrag(TRUE); + + if(aPathPolygon[(sal_uInt16)pHdl->GetPolyNum()].IsControl((sal_uInt16)pHdl->GetPointNum())) + bMultiPointDrag = FALSE; + + if(bMultiPointDrag) + { + const SdrMarkView& rMarkView = *rDrag.GetView(); + const SdrHdlList& rHdlList = rMarkView.GetHdlList(); + const sal_uInt32 nHdlCount = rHdlList.GetHdlCount(); + const SdrObject* pInteractionObject(nHdlCount && rHdlList.GetHdl(0) ? rHdlList.GetHdl(0)->GetObj() : 0); + sal_uInt32 nSelectedPoints(0); + + for(sal_uInt32 a(0); a < nHdlCount; a++) + { + SdrHdl* pTestHdl = rHdlList.GetHdl(a); + + if(pTestHdl && pTestHdl->IsSelected() && pTestHdl->GetObj() == pInteractionObject) + { + nSelectedPoints++; + } + } + + if(nSelectedPoints <= 1) + bMultiPointDrag = FALSE; + } + + ((ImpPathForDragAndCreate*)this)->mpSdrPathDragData = new ImpSdrPathDragData(mrSdrPathObject,*pHdl,bMultiPointDrag,rDrag); + + if(!mpSdrPathDragData || !mpSdrPathDragData->bValid) + { + DBG_ERROR("ImpPathForDragAndCreate::BegDrag(): ImpSdrPathDragData ist ungueltig"); + delete mpSdrPathDragData; + ((ImpPathForDragAndCreate*)this)->mpSdrPathDragData = 0; + return false; + } + + return true; +} + +bool ImpPathForDragAndCreate::movePathDrag( SdrDragStat& rDrag ) const +{ + if(!mpSdrPathDragData || !mpSdrPathDragData->bValid) + { + DBG_ERROR("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData ist ungueltig"); + return false; + } + + if(mpSdrPathDragData->IsMultiPointDrag()) + { + Point aDelta(rDrag.GetNow() - rDrag.GetStart()); + + if(aDelta.X() || aDelta.Y()) + { + for(sal_uInt32 a(0); a < mpSdrPathDragData->maHandles.Count(); a++) + { + SdrHdl* pHandle = (SdrHdl*)mpSdrPathDragData->maHandles.GetObject(a); + const sal_uInt16 nPolyIndex((sal_uInt16)pHandle->GetPolyNum()); + const sal_uInt16 nPointIndex((sal_uInt16)pHandle->GetPointNum()); + const XPolygon& rOrig = mpSdrPathDragData->maOrig[nPolyIndex]; + XPolygon& rMove = mpSdrPathDragData->maMove[nPolyIndex]; + const sal_uInt16 nPointCount(rOrig.GetPointCount()); + BOOL bClosed(rOrig[0] == rOrig[nPointCount-1]); + + // move point itself + rMove[nPointIndex] = rOrig[nPointIndex] + aDelta; + + // when point is first and poly closed, move close point, too. + if(nPointCount > 0 && !nPointIndex && bClosed) + { + rMove[nPointCount - 1] = rOrig[nPointCount - 1] + aDelta; + + // when moving the last point it may be necessary to move the + // control point in front of this one, too. + if(nPointCount > 1 && rOrig.IsControl(nPointCount - 2)) + rMove[nPointCount - 2] = rOrig[nPointCount - 2] + aDelta; + } + + // is a control point before this? + if(nPointIndex > 0 && rOrig.IsControl(nPointIndex - 1)) + { + // Yes, move it, too + rMove[nPointIndex - 1] = rOrig[nPointIndex - 1] + aDelta; + } + + // is a control point after this? + if(nPointIndex + 1 < nPointCount && rOrig.IsControl(nPointIndex + 1)) + { + // Yes, move it, too + rMove[nPointIndex + 1] = rOrig[nPointIndex + 1] + aDelta; + } + } + } + } + else + { + mpSdrPathDragData->ResetPoly(mrSdrPathObject); + + // Div. Daten lokal Kopieren fuer weniger Code und schnelleren Zugriff + FASTBOOL bClosed =mpSdrPathDragData->bClosed ; // geschlossenes Objekt? + USHORT nPnt =mpSdrPathDragData->nPnt ; // Punktnummer innerhalb des obigen Polygons + FASTBOOL bBegPnt =mpSdrPathDragData->bBegPnt ; // Gedraggter Punkt ist der Anfangspunkt einer Polyline + FASTBOOL bEndPnt =mpSdrPathDragData->bEndPnt ; // Gedraggter Punkt ist der Endpunkt einer Polyline + USHORT nPrevPnt =mpSdrPathDragData->nPrevPnt ; // Index des vorherigen Punkts + USHORT nNextPnt =mpSdrPathDragData->nNextPnt ; // Index des naechsten Punkts + FASTBOOL bPrevIsBegPnt =mpSdrPathDragData->bPrevIsBegPnt ; // Vorheriger Punkt ist Anfangspunkt einer Polyline + FASTBOOL bNextIsEndPnt =mpSdrPathDragData->bNextIsEndPnt ; // Folgepunkt ist Endpunkt einer Polyline + USHORT nPrevPrevPnt =mpSdrPathDragData->nPrevPrevPnt ; // Index des vorvorherigen Punkts + USHORT nNextNextPnt =mpSdrPathDragData->nNextNextPnt ; // Index des uebernaechsten Punkts + FASTBOOL bControl =mpSdrPathDragData->bControl ; // Punkt ist ein Kontrollpunkt + //FASTBOOL bIsPrevControl=mpSdrPathDragData->bIsPrevControl; // Punkt ist Kontrollpunkt vor einem Stuetzpunkt + FASTBOOL bIsNextControl=mpSdrPathDragData->bIsNextControl; // Punkt ist Kontrollpunkt hinter einem Stuetzpunkt + FASTBOOL bPrevIsControl=mpSdrPathDragData->bPrevIsControl; // Falls nPnt ein StPnt: Davor ist ein Kontrollpunkt + FASTBOOL bNextIsControl=mpSdrPathDragData->bNextIsControl; // Falls nPnt ein StPnt: Dahinter ist ein Kontrollpunkt + + // Ortho bei Linien/Polygonen = Winkel beibehalten + if (!bControl && rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho()) { + FASTBOOL bBigOrtho=rDrag.GetView()->IsBigOrtho(); + Point aPos(rDrag.GetNow()); // die aktuelle Position + Point aPnt(mpSdrPathDragData->aXP[nPnt]); // der gedraggte Punkt + USHORT nPnt1=0xFFFF,nPnt2=0xFFFF; // seine Nachbarpunkte + Point aNeuPos1,aNeuPos2; // die neuen Alternativen fuer aPos + FASTBOOL bPnt1=FALSE,bPnt2=FALSE; // die neuen Alternativen gueltig? + if (!bClosed && mpSdrPathDragData->nPntAnz>=2) { // Mind. 2 Pt bei Linien + if (!bBegPnt) nPnt1=nPrevPnt; + if (!bEndPnt) nPnt2=nNextPnt; + } + if (bClosed && mpSdrPathDragData->nPntAnz>=3) { // Mind. 3 Pt bei Polygon + nPnt1=nPrevPnt; + nPnt2=nNextPnt; + } + if (nPnt1!=0xFFFF && !bPrevIsControl) { + Point aPnt1=mpSdrPathDragData->aXP[nPnt1]; + long ndx0=aPnt.X()-aPnt1.X(); + long ndy0=aPnt.Y()-aPnt1.Y(); + FASTBOOL bHLin=ndy0==0; + FASTBOOL bVLin=ndx0==0; + if (!bHLin || !bVLin) { + long ndx=aPos.X()-aPnt1.X(); + long ndy=aPos.Y()-aPnt1.Y(); + bPnt1=TRUE; + double nXFact=0; if (!bVLin) nXFact=(double)ndx/(double)ndx0; + double nYFact=0; if (!bHLin) nYFact=(double)ndy/(double)ndy0; + FASTBOOL bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho); + FASTBOOL bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho); + if (bHor) ndy=long(ndy0*nXFact); + if (bVer) ndx=long(ndx0*nYFact); + aNeuPos1=aPnt1; + aNeuPos1.X()+=ndx; + aNeuPos1.Y()+=ndy; + } + } + if (nPnt2!=0xFFFF && !bNextIsControl) { + Point aPnt2=mpSdrPathDragData->aXP[nPnt2]; + long ndx0=aPnt.X()-aPnt2.X(); + long ndy0=aPnt.Y()-aPnt2.Y(); + FASTBOOL bHLin=ndy0==0; + FASTBOOL bVLin=ndx0==0; + if (!bHLin || !bVLin) { + long ndx=aPos.X()-aPnt2.X(); + long ndy=aPos.Y()-aPnt2.Y(); + bPnt2=TRUE; + double nXFact=0; if (!bVLin) nXFact=(double)ndx/(double)ndx0; + double nYFact=0; if (!bHLin) nYFact=(double)ndy/(double)ndy0; + FASTBOOL bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho); + FASTBOOL bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho); + if (bHor) ndy=long(ndy0*nXFact); + if (bVer) ndx=long(ndx0*nYFact); + aNeuPos2=aPnt2; + aNeuPos2.X()+=ndx; + aNeuPos2.Y()+=ndy; + } + } + if (bPnt1 && bPnt2) { // beide Alternativen vorhanden (Konkurenz) + BigInt nX1(aNeuPos1.X()-aPos.X()); nX1*=nX1; + BigInt nY1(aNeuPos1.Y()-aPos.Y()); nY1*=nY1; + BigInt nX2(aNeuPos2.X()-aPos.X()); nX2*=nX2; + BigInt nY2(aNeuPos2.Y()-aPos.Y()); nY2*=nY2; + nX1+=nY1; // Korrekturabstand zum Quadrat + nX2+=nY2; // Korrekturabstand zum Quadrat + // Die Alternative mit dem geringeren Korrekturbedarf gewinnt + if (nX1<nX2) bPnt2=FALSE; else bPnt1=FALSE; + } + if (bPnt1) rDrag.Now()=aNeuPos1; + if (bPnt2) rDrag.Now()=aNeuPos2; + } + rDrag.SetActionRect(Rectangle(rDrag.GetNow(),rDrag.GetNow())); + + // IBM Special: Punkte eliminieren, wenn die beiden angrenzenden + // Linien eh' fast 180 deg sind. + if (!bControl && rDrag.GetView()!=NULL && rDrag.GetView()->IsEliminatePolyPoints() && + !bBegPnt && !bEndPnt && !bPrevIsControl && !bNextIsControl) + { + Point aPt(mpSdrPathDragData->aXP[nNextPnt]); + aPt-=rDrag.GetNow(); + long nWink1=GetAngle(aPt); + aPt=rDrag.GetNow(); + aPt-=mpSdrPathDragData->aXP[nPrevPnt]; + long nWink2=GetAngle(aPt); + long nDiff=nWink1-nWink2; + nDiff=Abs(nDiff); + mpSdrPathDragData->bEliminate=nDiff<=rDrag.GetView()->GetEliminatePolyPointLimitAngle(); + if (mpSdrPathDragData->bEliminate) { // Position anpassen, damit Smooth an den Enden stimmt + aPt=mpSdrPathDragData->aXP[nNextPnt]; + aPt+=mpSdrPathDragData->aXP[nPrevPnt]; + aPt/=2; + rDrag.Now()=aPt; + } + } + + // Um diese Entfernung wurde insgesamt gedraggd + Point aDiff(rDrag.GetNow()); aDiff-=mpSdrPathDragData->aXP[nPnt]; + + // Insgesamt sind 8 Faelle moeglich: + // X 1. Weder rechts noch links Ctrl. + // o--X--o 2. Rechts und links Ctrl, gedraggd wird St. + // o--X 3. Nur links Ctrl, gedraggd wird St. + // X--o 4. Nur rechts Ctrl, gedraggd wird St. + // x--O--o 5. Rechts und links Ctrl, gedraggd wird links. + // x--O 6. Nur links Ctrl, gedraggd wird links. + // o--O--x 7. Rechts und links Ctrl, gedraggd wird rechts. + // O--x 8. Nur rechts Ctrl, gedraggd wird rechts. + // Zusaetzlich ist zu beachten, dass das Veraendern einer Linie (keine Kurve) + // eine evtl. Kurve am anderen Ende der Linie bewirkt, falls dort Smooth + // gesetzt ist (Kontrollpunktausrichtung an Gerade). + + mpSdrPathDragData->aXP[nPnt]+=aDiff; + + // Nun symmetrische PlusHandles etc. checken + if (bControl) { // Faelle 5,6,7,8 + USHORT nSt=nPnt; // der zugehoerige Stuetzpunkt + USHORT nFix=nPnt; // der gegenueberliegende Kontrollpunkt + if (bIsNextControl) { // Wenn der naechste ein Kontrollpunkt ist, muss der vorh. der Stuetzpunkt sein + nSt=nPrevPnt; + nFix=nPrevPrevPnt; + } else { + nSt=nNextPnt; + nFix=nNextNextPnt; + } + if (mpSdrPathDragData->aXP.IsSmooth(nSt)) { + mpSdrPathDragData->aXP.CalcSmoothJoin(nSt,nPnt,nFix); + } + } + + if (!bControl) { // Faelle 1,2,3,4 wobei bei 1 nix passiert und bei 3+4 unten noch mehr folgt + // die beiden Kontrollpunkte mit verschieben + if (bPrevIsControl) mpSdrPathDragData->aXP[nPrevPnt]+=aDiff; + if (bNextIsControl) mpSdrPathDragData->aXP[nNextPnt]+=aDiff; + // Kontrollpunkt ggf. an Gerade ausrichten + if (mpSdrPathDragData->aXP.IsSmooth(nPnt)) { + if (bPrevIsControl && !bNextIsControl && !bEndPnt) { // Fall 3 + mpSdrPathDragData->aXP.CalcSmoothJoin(nPnt,nNextPnt,nPrevPnt); + } + if (bNextIsControl && !bPrevIsControl && !bBegPnt) { // Fall 4 + mpSdrPathDragData->aXP.CalcSmoothJoin(nPnt,nPrevPnt,nNextPnt); + } + } + // Und nun noch die anderen Enden der Strecken ueberpruefen (nPnt+-1). + // Ist dort eine Kurve (IsControl(nPnt+-2)) mit SmoothJoin (nPnt+-1), + // so muss der entsprechende Kontrollpunkt (nPnt+-2) angepasst werden. + if (!bBegPnt && !bPrevIsControl && !bPrevIsBegPnt && mpSdrPathDragData->aXP.IsSmooth(nPrevPnt)) { + if (mpSdrPathDragData->aXP.IsControl(nPrevPrevPnt)) { + mpSdrPathDragData->aXP.CalcSmoothJoin(nPrevPnt,nPnt,nPrevPrevPnt); + } + } + if (!bEndPnt && !bNextIsControl && !bNextIsEndPnt && mpSdrPathDragData->aXP.IsSmooth(nNextPnt)) { + if (mpSdrPathDragData->aXP.IsControl(nNextNextPnt)) { + mpSdrPathDragData->aXP.CalcSmoothJoin(nNextPnt,nPnt,nNextNextPnt); + } + } + } + } + + return true; +} + +bool ImpPathForDragAndCreate::endPathDrag(SdrDragStat& rDrag) +{ + Point aLinePt1; + Point aLinePt2; + bool bLineGlueMirror(OBJ_LINE == meObjectKind); + if (bLineGlueMirror) { // #40549# + XPolygon& rXP=aPathPolygon[0]; + aLinePt1=rXP[0]; + aLinePt2=rXP[1]; + } + + if(!mpSdrPathDragData || !mpSdrPathDragData->bValid) + { + DBG_ERROR("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData ist ungueltig"); + return false; + } + + if(mpSdrPathDragData->IsMultiPointDrag()) + { + aPathPolygon = mpSdrPathDragData->maMove; + } + else + { + const SdrHdl* pHdl=rDrag.GetHdl(); + + // Referenz auf das Polygon + XPolygon& rXP=aPathPolygon[(sal_uInt16)pHdl->GetPolyNum()]; + + // Die 5 Punkte die sich evtl. geaendert haben + if (!mpSdrPathDragData->bPrevIsBegPnt) rXP[mpSdrPathDragData->nPrevPrevPnt0]=mpSdrPathDragData->aXP[mpSdrPathDragData->nPrevPrevPnt]; + if (!mpSdrPathDragData->bNextIsEndPnt) rXP[mpSdrPathDragData->nNextNextPnt0]=mpSdrPathDragData->aXP[mpSdrPathDragData->nNextNextPnt]; + if (!mpSdrPathDragData->bBegPnt) rXP[mpSdrPathDragData->nPrevPnt0] =mpSdrPathDragData->aXP[mpSdrPathDragData->nPrevPnt]; + if (!mpSdrPathDragData->bEndPnt) rXP[mpSdrPathDragData->nNextPnt0] =mpSdrPathDragData->aXP[mpSdrPathDragData->nNextPnt]; + rXP[mpSdrPathDragData->nPnt0] =mpSdrPathDragData->aXP[mpSdrPathDragData->nPnt]; + + // Letzter Punkt muss beim Geschlossenen immer gleich dem Ersten sein + if (mpSdrPathDragData->bClosed) rXP[rXP.GetPointCount()-1]=rXP[0]; + + if (mpSdrPathDragData->bEliminate) + { + basegfx::B2DPolyPolygon aTempPolyPolygon(aPathPolygon.getB2DPolyPolygon()); + sal_uInt32 nPoly,nPnt; + + if(PolyPolygonEditor::GetRelativePolyPoint(aTempPolyPolygon, rDrag.GetHdl()->GetSourceHdlNum(), nPoly, nPnt)) + { + basegfx::B2DPolygon aCandidate(aTempPolyPolygon.getB2DPolygon(nPoly)); + aCandidate.remove(nPnt); + + if((IsClosed(meObjectKind) && aCandidate.count() < 3L) || aCandidate.count() < 2L) + { + aTempPolyPolygon.remove(nPoly); + } + else + { + aTempPolyPolygon.setB2DPolygon(nPoly, aCandidate); + } + } + + aPathPolygon = XPolyPolygon(aTempPolyPolygon); + } + + // Winkel anpassen fuer Text an einfacher Linie + if (bLineGlueMirror) + { // #40549# + Point aLinePt1_(aPathPolygon[0][0]); + Point aLinePt2_(aPathPolygon[0][1]); + FASTBOOL bXMirr=(aLinePt1_.X()>aLinePt2_.X())!=(aLinePt1.X()>aLinePt2.X()); + FASTBOOL bYMirr=(aLinePt1_.Y()>aLinePt2_.Y())!=(aLinePt1.Y()>aLinePt2.Y()); + if (bXMirr || bYMirr) { + Point aRef1(mrSdrPathObject.GetSnapRect().Center()); + if (bXMirr) { + Point aRef2(aRef1); + aRef2.Y()++; + mrSdrPathObject.NbcMirrorGluePoints(aRef1,aRef2); + } + if (bYMirr) { + Point aRef2(aRef1); + aRef2.X()++; + mrSdrPathObject.NbcMirrorGluePoints(aRef1,aRef2); + } + } + } + } + + delete mpSdrPathDragData; + mpSdrPathDragData = 0; + + return true; +} + +/*void ImpPathForDragAndCreate::cancelSpecialDrag( SdrDragStat& rDrag ) const +{ + ImpSdrPathDragData* pID=(ImpSdrPathDragData*)rDrag.GetUser(); + if (pID!=NULL) { + delete pID; + rDrag.SetUser(NULL); + } +}*/ + +String ImpPathForDragAndCreate::getSpecialDragComment(const SdrDragStat& rDrag) const +{ + XubString aStr; + const SdrHdl* pHdl = rDrag.GetHdl(); + const bool bCreateComment(rDrag.GetView() && &mrSdrPathObject == rDrag.GetView()->GetCreateObj()); + + if(bCreateComment && rDrag.GetUser()) + { + // #i103058# re-add old creation comment mode + ImpPathCreateUser* pU = (ImpPathCreateUser*)rDrag.GetUser(); + const SdrObjKind eKindMerk(meObjectKind); + mrSdrPathObject.meKind = pU->eAktKind; + mrSdrPathObject.ImpTakeDescriptionStr(STR_ViewCreateObj, aStr); + mrSdrPathObject.meKind = eKindMerk; + + Point aPrev(rDrag.GetPrev()); + Point aNow(rDrag.GetNow()); + + if(pU->bLine) + aNow = pU->aLineEnd; + + aNow -= aPrev; + aStr.AppendAscii(" ("); + + XubString aMetr; + + if(pU->bCircle) + { + mrSdrPathObject.GetModel()->TakeWinkStr(Abs(pU->nCircRelWink), aMetr); + aStr += aMetr; + aStr.AppendAscii(" r="); + mrSdrPathObject.GetModel()->TakeMetricStr(pU->nCircRadius, aMetr, TRUE); + aStr += aMetr; + } + + aStr.AppendAscii("dx="); + mrSdrPathObject.GetModel()->TakeMetricStr(aNow.X(), aMetr, TRUE); + aStr += aMetr; + + aStr.AppendAscii(" dy="); + mrSdrPathObject.GetModel()->TakeMetricStr(aNow.Y(), aMetr, TRUE); + aStr += aMetr; + + if(!IsFreeHand(meObjectKind)) + { + INT32 nLen(GetLen(aNow)); + aStr.AppendAscii(" l="); + mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, TRUE); + aStr += aMetr; + + INT32 nWink(GetAngle(aNow)); + aStr += sal_Unicode(' '); + mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr); + aStr += aMetr; + } + + aStr += sal_Unicode(')'); + } + else if(!mrSdrPathObject.GetModel() || !pHdl) + { + // #i103058# fallback when no model and/or Handle, both needed + // for else-path + mrSdrPathObject.ImpTakeDescriptionStr(STR_DragPathObj, aStr); + } + else + { + // #i103058# standard for modification; model and handle needed + ImpSdrPathDragData* pDragData = mpSdrPathDragData; + + if(!pDragData) + { + // getSpecialDragComment is also used from create, so fallback to GetUser() + // when mpSdrPathDragData is not set + pDragData = (ImpSdrPathDragData*)rDrag.GetUser(); + } + + if(!pDragData) + { + DBG_ERROR("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData ist ungueltig"); + return String(); + } + + if(!pDragData->IsMultiPointDrag() && pDragData->bEliminate) + { + // Punkt von ... + mrSdrPathObject.ImpTakeDescriptionStr(STR_ViewMarkedPoint, aStr); + + // %O loeschen + XubString aStr2(ImpGetResStr(STR_EditDelete)); + + // UNICODE: Punkt von ... loeschen + aStr2.SearchAndReplaceAscii("%1", aStr); + + return aStr2; + } + + // dx=0.00 dy=0.00 // Beide Seiten Bezier + // dx=0.00 dy=0.00 l=0.00 0.00ø // Anfang oder Ende oder eine Seite Bezier bzw. Hebel + // dx=0.00 dy=0.00 l=0.00 0.00ø / l=0.00 0.00ø // Mittendrin + XubString aMetr; + Point aBeg(rDrag.GetStart()); + Point aNow(rDrag.GetNow()); + + aStr = String(); + aStr.AppendAscii("dx="); + mrSdrPathObject.GetModel()->TakeMetricStr(aNow.X() - aBeg.X(), aMetr, TRUE); + aStr += aMetr; + + aStr.AppendAscii(" dy="); + mrSdrPathObject.GetModel()->TakeMetricStr(aNow.Y() - aBeg.Y(), aMetr, TRUE); + aStr += aMetr; + + if(!pDragData->IsMultiPointDrag()) + { + UINT16 nPntNum((sal_uInt16)pHdl->GetPointNum()); + const XPolygon& rXPoly = aPathPolygon[(sal_uInt16)rDrag.GetHdl()->GetPolyNum()]; + UINT16 nPntAnz((sal_uInt16)rXPoly.GetPointCount()); + BOOL bClose(IsClosed(meObjectKind)); + + if(bClose) + nPntAnz--; + + if(pHdl->IsPlusHdl()) + { + // Hebel + UINT16 nRef(nPntNum); + + if(rXPoly.IsControl(nPntNum + 1)) + nRef--; + else + nRef++; + + aNow -= rXPoly[nRef]; + + INT32 nLen(GetLen(aNow)); + aStr.AppendAscii(" l="); + mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, TRUE); + aStr += aMetr; + + INT32 nWink(GetAngle(aNow)); + aStr += sal_Unicode(' '); + mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr); + aStr += aMetr; + } + else if(nPntAnz > 1) + { + UINT16 nPntMax(nPntAnz - 1); + Point aPt1,aPt2; + BOOL bIsClosed(IsClosed(meObjectKind)); + BOOL bPt1(nPntNum > 0); + BOOL bPt2(nPntNum < nPntMax); + + if(bIsClosed && nPntAnz > 2) + { + bPt1 = TRUE; + bPt2 = TRUE; + } + + UINT16 nPt1,nPt2; + + if(nPntNum > 0) + nPt1 = nPntNum - 1; + else + nPt1 = nPntMax; + + if(nPntNum < nPntMax) + nPt2 = nPntNum + 1; + else + nPt2 = 0; + + if(bPt1 && rXPoly.IsControl(nPt1)) + bPt1 = FALSE; // Keine Anzeige + + if(bPt2 && rXPoly.IsControl(nPt2)) + bPt2 = FALSE; // von Bezierdaten + + if(bPt1) + { + Point aPt(aNow); + aPt -= rXPoly[nPt1]; + + INT32 nLen(GetLen(aPt)); + aStr.AppendAscii(" l="); + mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, TRUE); + aStr += aMetr; + + INT32 nWink(GetAngle(aPt)); + aStr += sal_Unicode(' '); + mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr); + aStr += aMetr; + } + + if(bPt2) + { + if(bPt1) + aStr.AppendAscii(" / "); + else + aStr.AppendAscii(" "); + + Point aPt(aNow); + aPt -= rXPoly[nPt2]; + + INT32 nLen(GetLen(aPt)); + aStr.AppendAscii("l="); + mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, TRUE); + aStr += aMetr; + + INT32 nWink(GetAngle(aPt)); + aStr += sal_Unicode(' '); + mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr); + aStr += aMetr; + } + } + } + } + + return aStr; +} + +basegfx::B2DPolyPolygon ImpPathForDragAndCreate::getSpecialDragPoly(const SdrDragStat& rDrag) const +{ + if(!mpSdrPathDragData || !mpSdrPathDragData->bValid) + { + DBG_ERROR("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData ist ungueltig"); + return basegfx::B2DPolyPolygon(); + } + + XPolyPolygon aRetval; + + if(mpSdrPathDragData->IsMultiPointDrag()) + { + aRetval.Insert(mpSdrPathDragData->maMove); + } + else + { + const XPolygon& rXP=aPathPolygon[(sal_uInt16)rDrag.GetHdl()->GetPolyNum()]; + if (rXP.GetPointCount()<=2) { //|| rXPoly.GetFlags(1)==XPOLY_CONTROL && rXPoly.GetPointCount()<=4 + XPolygon aXPoly(rXP); + aXPoly[(sal_uInt16)rDrag.GetHdl()->GetPointNum()]=rDrag.GetNow(); + aRetval.Insert(aXPoly); + return aRetval.getB2DPolyPolygon(); + } + // Div. Daten lokal Kopieren fuer weniger Code und schnelleren Zugriff + FASTBOOL bClosed =mpSdrPathDragData->bClosed ; // geschlossenes Objekt? + USHORT nPntAnz =mpSdrPathDragData->nPntAnz ; // Punktanzahl + USHORT nPnt =mpSdrPathDragData->nPnt ; // Punktnummer innerhalb des Polygons + FASTBOOL bBegPnt =mpSdrPathDragData->bBegPnt ; // Gedraggter Punkt ist der Anfangspunkt einer Polyline + FASTBOOL bEndPnt =mpSdrPathDragData->bEndPnt ; // Gedraggter Punkt ist der Endpunkt einer Polyline + USHORT nPrevPnt =mpSdrPathDragData->nPrevPnt ; // Index des vorherigen Punkts + USHORT nNextPnt =mpSdrPathDragData->nNextPnt ; // Index des naechsten Punkts + FASTBOOL bPrevIsBegPnt =mpSdrPathDragData->bPrevIsBegPnt ; // Vorheriger Punkt ist Anfangspunkt einer Polyline + FASTBOOL bNextIsEndPnt =mpSdrPathDragData->bNextIsEndPnt ; // Folgepunkt ist Endpunkt einer Polyline + USHORT nPrevPrevPnt =mpSdrPathDragData->nPrevPrevPnt ; // Index des vorvorherigen Punkts + USHORT nNextNextPnt =mpSdrPathDragData->nNextNextPnt ; // Index des uebernaechsten Punkts + FASTBOOL bControl =mpSdrPathDragData->bControl ; // Punkt ist ein Kontrollpunkt + //FASTBOOL bIsPrevControl=mpSdrPathDragData->bIsPrevControl; // Punkt ist Kontrollpunkt vor einem Stuetzpunkt + FASTBOOL bIsNextControl=mpSdrPathDragData->bIsNextControl; // Punkt ist Kontrollpunkt hinter einem Stuetzpunkt + FASTBOOL bPrevIsControl=mpSdrPathDragData->bPrevIsControl; // Falls nPnt ein StPnt: Davor ist ein Kontrollpunkt + FASTBOOL bNextIsControl=mpSdrPathDragData->bNextIsControl; // Falls nPnt ein StPnt: Dahinter ist ein Kontrollpunkt + XPolygon aXPoly(mpSdrPathDragData->aXP); + XPolygon aLine1(2); + XPolygon aLine2(2); + XPolygon aLine3(2); + XPolygon aLine4(2); + if (bControl) { + aLine1[1]=mpSdrPathDragData->aXP[nPnt]; + if (bIsNextControl) { // bin ich Kontrollpunkt hinter der Stuetzstelle? + aLine1[0]=mpSdrPathDragData->aXP[nPrevPnt]; + aLine2[0]=mpSdrPathDragData->aXP[nNextNextPnt]; + aLine2[1]=mpSdrPathDragData->aXP[nNextPnt]; + if (mpSdrPathDragData->aXP.IsSmooth(nPrevPnt) && !bPrevIsBegPnt && mpSdrPathDragData->aXP.IsControl(nPrevPrevPnt)) { + aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-1],XPOLY_CONTROL); + aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-2],XPOLY_NORMAL); + // Hebellienien fuer das gegenueberliegende Kurvensegment + aLine3[0]=mpSdrPathDragData->aXP[nPrevPnt]; + aLine3[1]=mpSdrPathDragData->aXP[nPrevPrevPnt]; + aLine4[0]=rXP[mpSdrPathDragData->nPrevPrevPnt0-2]; + aLine4[1]=rXP[mpSdrPathDragData->nPrevPrevPnt0-1]; + } else { + aXPoly.Remove(0,1); + } + } else { // ansonsten bin ich Kontrollpunkt vor der Stuetzstelle + aLine1[0]=mpSdrPathDragData->aXP[nNextPnt]; + aLine2[0]=mpSdrPathDragData->aXP[nPrevPrevPnt]; + aLine2[1]=mpSdrPathDragData->aXP[nPrevPnt]; + if (mpSdrPathDragData->aXP.IsSmooth(nNextPnt) && !bNextIsEndPnt && mpSdrPathDragData->aXP.IsControl(nNextNextPnt)) { + aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+1],XPOLY_CONTROL); + aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+2],XPOLY_NORMAL); + // Hebellinien fuer das gegenueberliegende Kurvensegment + aLine3[0]=mpSdrPathDragData->aXP[nNextPnt]; + aLine3[1]=mpSdrPathDragData->aXP[nNextNextPnt]; + aLine4[0]=rXP[mpSdrPathDragData->nNextNextPnt0+2]; + aLine4[1]=rXP[mpSdrPathDragData->nNextNextPnt0+1]; + } else { + aXPoly.Remove(aXPoly.GetPointCount()-1,1); + } + } + } else { // ansonsten kein Kontrollpunkt + if (mpSdrPathDragData->bEliminate) { + aXPoly.Remove(2,1); + } + if (bPrevIsControl) aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-1],XPOLY_NORMAL); + else if (!bBegPnt && !bPrevIsBegPnt && mpSdrPathDragData->aXP.IsControl(nPrevPrevPnt)) { + aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-1],XPOLY_CONTROL); + aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-2],XPOLY_NORMAL); + } else { + aXPoly.Remove(0,1); + if (bBegPnt) aXPoly.Remove(0,1); + } + if (bNextIsControl) aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+1],XPOLY_NORMAL); + else if (!bEndPnt && !bNextIsEndPnt && mpSdrPathDragData->aXP.IsControl(nNextNextPnt)) { + aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+1],XPOLY_CONTROL); + aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+2],XPOLY_NORMAL); + } else { + aXPoly.Remove(aXPoly.GetPointCount()-1,1); + if (bEndPnt) aXPoly.Remove(aXPoly.GetPointCount()-1,1); + } + if (bClosed) { // "Birnenproblem": 2 Linien, 1 Kurve, alles Smooth, Punkt zw. beiden Linien wird gedraggt + if (aXPoly.GetPointCount()>nPntAnz && aXPoly.IsControl(1)) { + USHORT a=aXPoly.GetPointCount(); + aXPoly[a-2]=aXPoly[2]; aXPoly.SetFlags(a-2,aXPoly.GetFlags(2)); + aXPoly[a-1]=aXPoly[3]; aXPoly.SetFlags(a-1,aXPoly.GetFlags(3)); + aXPoly.Remove(0,3); + } + } + } + aRetval.Insert(aXPoly); + if (aLine1.GetPointCount()>1) aRetval.Insert(aLine1); + if (aLine2.GetPointCount()>1) aRetval.Insert(aLine2); + if (aLine3.GetPointCount()>1) aRetval.Insert(aLine3); + if (aLine4.GetPointCount()>1) aRetval.Insert(aLine4); + } + + return aRetval.getB2DPolyPolygon(); +} + +FASTBOOL ImpPathForDragAndCreate::BegCreate(SdrDragStat& rStat) +{ + bool bFreeHand(IsFreeHand(meObjectKind)); + rStat.SetNoSnap(bFreeHand); + rStat.SetOrtho8Possible(); + aPathPolygon.Clear(); + mbCreating=TRUE; + FASTBOOL bMakeStartPoint=TRUE; + SdrView* pView=rStat.GetView(); + if (pView!=NULL && pView->IsUseIncompatiblePathCreateInterface() && + (meObjectKind==OBJ_POLY || meObjectKind==OBJ_PLIN || meObjectKind==OBJ_PATHLINE || meObjectKind==OBJ_PATHFILL)) { + bMakeStartPoint=FALSE; + } + aPathPolygon.Insert(XPolygon()); + aPathPolygon[0][0]=rStat.GetStart(); + if (bMakeStartPoint) { + aPathPolygon[0][1]=rStat.GetNow(); + } + ImpPathCreateUser* pU=new ImpPathCreateUser; + pU->eStartKind=meObjectKind; + pU->eAktKind=meObjectKind; + rStat.SetUser(pU); + return TRUE; +} + +FASTBOOL ImpPathForDragAndCreate::MovCreate(SdrDragStat& rStat) +{ + ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser(); + SdrView* pView=rStat.GetView(); + XPolygon& rXPoly=aPathPolygon[aPathPolygon.Count()-1]; + if (pView!=NULL && pView->IsCreateMode()) { + // ggf. auf anderes CreateTool umschalten + UINT16 nIdent; + UINT32 nInvent; + pView->TakeCurrentObj(nIdent,nInvent); + if (nInvent==SdrInventor && pU->eAktKind!=(SdrObjKind)nIdent) { + SdrObjKind eNewKind=(SdrObjKind)nIdent; + switch (eNewKind) { + case OBJ_CARC: case OBJ_CIRC: case OBJ_CCUT: case OBJ_SECT: eNewKind=OBJ_CARC; + case OBJ_RECT: + case OBJ_LINE: case OBJ_PLIN: case OBJ_POLY: + case OBJ_PATHLINE: case OBJ_PATHFILL: + case OBJ_FREELINE: case OBJ_FREEFILL: + case OBJ_SPLNLINE: case OBJ_SPLNFILL: { + pU->eAktKind=eNewKind; + pU->bMixedCreate=TRUE; + pU->nBezierStartPoint=rXPoly.GetPointCount(); + if (pU->nBezierStartPoint>0) pU->nBezierStartPoint--; + } break; + default: break; + } // switch + } + } + USHORT nActPoint=rXPoly.GetPointCount(); + if (aPathPolygon.Count()>1 && rStat.IsMouseDown() && nActPoint<2) { + rXPoly[0]=rStat.GetPos0(); + rXPoly[1]=rStat.GetNow(); + nActPoint=2; + } + if (nActPoint==0) { + rXPoly[0]=rStat.GetPos0(); + } else nActPoint--; + FASTBOOL bFreeHand=IsFreeHand(pU->eAktKind); + rStat.SetNoSnap(bFreeHand /*|| (pU->bMixed && pU->eAktKind==OBJ_LINE)*/); + rStat.SetOrtho8Possible(pU->eAktKind!=OBJ_CARC && pU->eAktKind!=OBJ_RECT && (!pU->bMixedCreate || pU->eAktKind!=OBJ_LINE)); + Point aActMerk(rXPoly[nActPoint]); + rXPoly[nActPoint]=rStat.Now(); + if (!pU->bMixedCreate && pU->eStartKind==OBJ_LINE && rXPoly.GetPointCount()>=1) { + Point aPt(rStat.Start()); + if (pView!=NULL && pView->IsCreate1stPointAsCenter()) { + aPt+=aPt; + aPt-=rStat.Now(); + } + rXPoly[0]=aPt; + } + OutputDevice* pOut=pView==NULL ? NULL : pView->GetFirstOutputDevice(); // GetWin(0); + if (bFreeHand) { + if (pU->nBezierStartPoint>nActPoint) pU->nBezierStartPoint=nActPoint; + if (rStat.IsMouseDown() && nActPoint>0) { + // keine aufeinanderfolgenden Punkte an zu Nahe gelegenen Positionen zulassen + long nMinDist=1; + if (pView!=NULL) nMinDist=pView->GetFreeHandMinDistPix(); + if (pOut!=NULL) nMinDist=pOut->PixelToLogic(Size(nMinDist,0)).Width(); + if (nMinDist<1) nMinDist=1; + + Point aPt0(rXPoly[nActPoint-1]); + Point aPt1(rStat.Now()); + long dx=aPt0.X()-aPt1.X(); if (dx<0) dx=-dx; + long dy=aPt0.Y()-aPt1.Y(); if (dy<0) dy=-dy; + if (dx<nMinDist && dy<nMinDist) return FALSE; + + // folgendes ist aus EndCreate kopiert (nur kleine Modifikationen) + // und sollte dann mal in eine Methode zusammengefasst werden: + + if (nActPoint-pU->nBezierStartPoint>=3 && ((nActPoint-pU->nBezierStartPoint)%3)==0) { + rXPoly.PointsToBezier(nActPoint-3); + rXPoly.SetFlags(nActPoint-1,XPOLY_CONTROL); + rXPoly.SetFlags(nActPoint-2,XPOLY_CONTROL); + + if (nActPoint>=6 && rXPoly.IsControl(nActPoint-4)) { + rXPoly.CalcTangent(nActPoint-3,nActPoint-4,nActPoint-2); + rXPoly.SetFlags(nActPoint-3,XPOLY_SMOOTH); + } + } + rXPoly[nActPoint+1]=rStat.Now(); + rStat.NextPoint(); + } else { + pU->nBezierStartPoint=nActPoint; + } + } + + pU->ResetFormFlags(); + if (IsBezier(pU->eAktKind)) { + if (nActPoint>=2) { + pU->CalcBezier(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],rStat.IsMouseDown()); + } else if (pU->bBezHasCtrl0) { + pU->CalcBezier(rXPoly[nActPoint-1],rXPoly[nActPoint],pU->aBezControl0-rXPoly[nActPoint-1],rStat.IsMouseDown()); + } + } + if (pU->eAktKind==OBJ_CARC && nActPoint>=2) { + pU->CalcCircle(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],pView); + } + if (pU->eAktKind==OBJ_LINE && nActPoint>=2) { + pU->CalcLine(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],pView); + } + if (pU->eAktKind==OBJ_RECT && nActPoint>=2) { + pU->CalcRect(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],pView); + } + + return TRUE; +} + +FASTBOOL ImpPathForDragAndCreate::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser(); + FASTBOOL bRet=FALSE; + SdrView* pView=rStat.GetView(); + FASTBOOL bIncomp=pView!=NULL && pView->IsUseIncompatiblePathCreateInterface(); + XPolygon& rXPoly=aPathPolygon[aPathPolygon.Count()-1]; + USHORT nActPoint=rXPoly.GetPointCount()-1; + Point aAktMerk(rXPoly[nActPoint]); + rXPoly[nActPoint]=rStat.Now(); + if (!pU->bMixedCreate && pU->eStartKind==OBJ_LINE) { + if (rStat.GetPointAnz()>=2) eCmd=SDRCREATE_FORCEEND; + bRet=eCmd==SDRCREATE_FORCEEND; + if (bRet) { + mbCreating=FALSE; + delete pU; + rStat.SetUser(NULL); + } + return bRet; + } + + if (!pU->bMixedCreate && IsFreeHand(pU->eStartKind)) { + if (rStat.GetPointAnz()>=2) eCmd=SDRCREATE_FORCEEND; + bRet=eCmd==SDRCREATE_FORCEEND; + if (bRet) { + mbCreating=FALSE; + delete pU; + rStat.SetUser(NULL); + } + return bRet; + } + if (eCmd==SDRCREATE_NEXTPOINT || eCmd==SDRCREATE_NEXTOBJECT) { + // keine aufeinanderfolgenden Punkte an identischer Position zulassen + if (nActPoint==0 || rStat.Now()!=rXPoly[nActPoint-1]) { + if (bIncomp) { + if (pU->nBezierStartPoint>nActPoint) pU->nBezierStartPoint=nActPoint; + if (IsBezier(pU->eAktKind) && nActPoint-pU->nBezierStartPoint>=3 && ((nActPoint-pU->nBezierStartPoint)%3)==0) { + rXPoly.PointsToBezier(nActPoint-3); + rXPoly.SetFlags(nActPoint-1,XPOLY_CONTROL); + rXPoly.SetFlags(nActPoint-2,XPOLY_CONTROL); + + if (nActPoint>=6 && rXPoly.IsControl(nActPoint-4)) { + rXPoly.CalcTangent(nActPoint-3,nActPoint-4,nActPoint-2); + rXPoly.SetFlags(nActPoint-3,XPOLY_SMOOTH); + } + } + } else { + if (nActPoint==1 && IsBezier(pU->eAktKind) && !pU->bBezHasCtrl0) { + pU->aBezControl0=rStat.GetNow();; + pU->bBezHasCtrl0=TRUE; + nActPoint--; + } + if (pU->IsFormFlag()) { + USHORT nPtAnz0=rXPoly.GetPointCount(); + rXPoly.Remove(nActPoint-1,2); // die letzten beiden Punkte entfernen und durch die Form ersetzen + rXPoly.Insert(XPOLY_APPEND,pU->GetFormPoly()); + USHORT nPtAnz1=rXPoly.GetPointCount(); + for (USHORT i=nPtAnz0+1; i<nPtAnz1-1; i++) { // Damit BckAction richtig funktioniert + if (!rXPoly.IsControl(i)) rStat.NextPoint(); + } + nActPoint=rXPoly.GetPointCount()-1; + } + } + nActPoint++; + rXPoly[nActPoint]=rStat.GetNow(); + } + if (eCmd==SDRCREATE_NEXTOBJECT) { + if (rXPoly.GetPointCount()>=2) { + pU->bBezHasCtrl0=FALSE; + // nur einzelnes Polygon kann offen sein, deshalb schliessen + rXPoly[nActPoint]=rXPoly[0]; + XPolygon aXP; + aXP[0]=rStat.GetNow(); + aPathPolygon.Insert(aXP); + } + } + } + + USHORT nPolyAnz=aPathPolygon.Count(); + if (nPolyAnz!=0) { + // den letzten Punkt ggf. wieder loeschen + if (eCmd==SDRCREATE_FORCEEND) { + XPolygon& rXP=aPathPolygon[nPolyAnz-1]; + USHORT nPtAnz=rXP.GetPointCount(); + if (nPtAnz>=2) { + if (!rXP.IsControl(nPtAnz-2)) { + if (rXP[nPtAnz-1]==rXP[nPtAnz-2]) { + rXP.Remove(nPtAnz-1,1); + } + } else { + if (rXP[nPtAnz-3]==rXP[nPtAnz-2]) { + rXP.Remove(nPtAnz-3,3); + } + } + } + } + for (USHORT nPolyNum=nPolyAnz; nPolyNum>0;) { + nPolyNum--; + XPolygon& rXP=aPathPolygon[nPolyNum]; + USHORT nPtAnz=rXP.GetPointCount(); + // Polygone mit zu wenig Punkten werden geloescht + if (nPolyNum<nPolyAnz-1 || eCmd==SDRCREATE_FORCEEND) { + if (nPtAnz<2) aPathPolygon.Remove(nPolyNum); + } + } + } + pU->ResetFormFlags(); + bRet=eCmd==SDRCREATE_FORCEEND; + if (bRet) { + mbCreating=FALSE; + delete pU; + rStat.SetUser(NULL); + } + return bRet; +} + +FASTBOOL ImpPathForDragAndCreate::BckCreate(SdrDragStat& rStat) +{ + ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser(); + if (aPathPolygon.Count()>0) { + XPolygon& rXPoly=aPathPolygon[aPathPolygon.Count()-1]; + USHORT nActPoint=rXPoly.GetPointCount(); + if (nActPoint>0) { + nActPoint--; + // Das letzte Stueck einer Bezierkurve wird erstmal zu 'ner Linie + rXPoly.Remove(nActPoint,1); + if (nActPoint>=3 && rXPoly.IsControl(nActPoint-1)) { + // Beziersegment am Ende sollte zwar nicht vorkommen, aber falls doch ... + rXPoly.Remove(nActPoint-1,1); + if (rXPoly.IsControl(nActPoint-2)) rXPoly.Remove(nActPoint-2,1); + } + } + nActPoint=rXPoly.GetPointCount(); + if (nActPoint>=4) { // Kein Beziersegment am Ende + nActPoint--; + if (rXPoly.IsControl(nActPoint-1)) { + rXPoly.Remove(nActPoint-1,1); + if (rXPoly.IsControl(nActPoint-2)) rXPoly.Remove(nActPoint-2,1); + } + } + if (rXPoly.GetPointCount()<2) { + aPathPolygon.Remove(aPathPolygon.Count()-1); + } + if (aPathPolygon.Count()>0) { + XPolygon& rLocalXPoly=aPathPolygon[aPathPolygon.Count()-1]; + USHORT nLocalActPoint=rLocalXPoly.GetPointCount(); + if (nLocalActPoint>0) { + nLocalActPoint--; + rLocalXPoly[nLocalActPoint]=rStat.Now(); + } + } + } + pU->ResetFormFlags(); + return aPathPolygon.Count()!=0; +} + +void ImpPathForDragAndCreate::BrkCreate(SdrDragStat& rStat) +{ + ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser(); + aPathPolygon.Clear(); + mbCreating=FALSE; + delete pU; + rStat.SetUser(NULL); +} + +basegfx::B2DPolyPolygon ImpPathForDragAndCreate::TakeObjectPolyPolygon(const SdrDragStat& rDrag) const +{ + basegfx::B2DPolyPolygon aRetval(aPathPolygon.getB2DPolyPolygon()); + SdrView* pView = rDrag.GetView(); + + if(pView && pView->IsUseIncompatiblePathCreateInterface()) + return aRetval; + + ImpPathCreateUser* pU = (ImpPathCreateUser*)rDrag.GetUser(); + basegfx::B2DPolygon aNewPolygon(aRetval.count() ? aRetval.getB2DPolygon(aRetval.count() - 1L) : basegfx::B2DPolygon()); + + if(pU->IsFormFlag() && aNewPolygon.count() > 1L) + { + // remove last segment and replace with current + // do not forget to rescue the previous control point which will be lost when + // the point it's associated with is removed + const sal_uInt32 nChangeIndex(aNewPolygon.count() - 2); + const basegfx::B2DPoint aSavedPrevCtrlPoint(aNewPolygon.getPrevControlPoint(nChangeIndex)); + + aNewPolygon.remove(nChangeIndex, 2L); + aNewPolygon.append(pU->GetFormPoly().getB2DPolygon()); + + if(nChangeIndex < aNewPolygon.count()) + { + // if really something was added, set the saved prev control point at the + // point where it belongs + aNewPolygon.setPrevControlPoint(nChangeIndex, aSavedPrevCtrlPoint); + } + } + + if(aRetval.count()) + { + aRetval.setB2DPolygon(aRetval.count() - 1L, aNewPolygon); + } + else + { + aRetval.append(aNewPolygon); + } + + return aRetval; +} + +basegfx::B2DPolyPolygon ImpPathForDragAndCreate::TakeDragPolyPolygon(const SdrDragStat& rDrag) const +{ + basegfx::B2DPolyPolygon aRetval; + SdrView* pView = rDrag.GetView(); + + if(pView && pView->IsUseIncompatiblePathCreateInterface()) + return aRetval; + + ImpPathCreateUser* pU = (ImpPathCreateUser*)rDrag.GetUser(); + + if(pU && pU->bBezier && rDrag.IsMouseDown()) + { + // no more XOR, no need for complicated helplines + basegfx::B2DPolygon aHelpline; + aHelpline.append(basegfx::B2DPoint(pU->aBezCtrl2.X(), pU->aBezCtrl2.Y())); + aHelpline.append(basegfx::B2DPoint(pU->aBezEnd.X(), pU->aBezEnd.Y())); + aRetval.append(aHelpline); + } + + return aRetval; +} + +Pointer ImpPathForDragAndCreate::GetCreatePointer() const +{ + switch (meObjectKind) { + case OBJ_LINE : return Pointer(POINTER_DRAW_LINE); + case OBJ_POLY : return Pointer(POINTER_DRAW_POLYGON); + case OBJ_PLIN : return Pointer(POINTER_DRAW_POLYGON); + case OBJ_PATHLINE: return Pointer(POINTER_DRAW_BEZIER); + case OBJ_PATHFILL: return Pointer(POINTER_DRAW_BEZIER); + case OBJ_FREELINE: return Pointer(POINTER_DRAW_FREEHAND); + case OBJ_FREEFILL: return Pointer(POINTER_DRAW_FREEHAND); + case OBJ_SPLNLINE: return Pointer(POINTER_DRAW_FREEHAND); + case OBJ_SPLNFILL: return Pointer(POINTER_DRAW_FREEHAND); + case OBJ_PATHPOLY: return Pointer(POINTER_DRAW_POLYGON); + case OBJ_PATHPLIN: return Pointer(POINTER_DRAW_POLYGON); + default: break; + } // switch + return Pointer(POINTER_CROSS); +} + +/*************************************************************************/ + +SdrPathObjGeoData::SdrPathObjGeoData() +{ +} + +SdrPathObjGeoData::~SdrPathObjGeoData() +{ +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrPathObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrPathObj(*this); +} + +/*************************************************************************/ + +TYPEINIT1(SdrPathObj,SdrTextObj); + +SdrPathObj::SdrPathObj(SdrObjKind eNewKind) +: meKind(eNewKind), + mpDAC(0L) +{ + bClosedObj = IsClosed(); +} + +SdrPathObj::SdrPathObj(SdrObjKind eNewKind, const basegfx::B2DPolyPolygon& rPathPoly) +: maPathPolygon(rPathPoly), + meKind(eNewKind), + mpDAC(0L) +{ + bClosedObj = IsClosed(); + ImpForceKind(); +} + +SdrPathObj::~SdrPathObj() +{ + impDeleteDAC(); +} + +sal_Bool ImpIsLine(const basegfx::B2DPolyPolygon& rPolyPolygon) +{ + return (1L == rPolyPolygon.count() && 2L == rPolyPolygon.getB2DPolygon(0L).count()); +} + +Rectangle ImpGetBoundRect(const basegfx::B2DPolyPolygon& rPolyPolygon) +{ + basegfx::B2DRange aRange(basegfx::tools::getRange(rPolyPolygon)); + + return Rectangle( + FRound(aRange.getMinX()), FRound(aRange.getMinY()), + FRound(aRange.getMaxX()), FRound(aRange.getMaxY())); +} + +void SdrPathObj::ImpForceLineWink() +{ + if(OBJ_LINE == meKind && ImpIsLine(GetPathPoly())) + { + const basegfx::B2DPolygon aPoly(GetPathPoly().getB2DPolygon(0L)); + const basegfx::B2DPoint aB2DPoint0(aPoly.getB2DPoint(0L)); + const basegfx::B2DPoint aB2DPoint1(aPoly.getB2DPoint(1L)); + const Point aPoint0(FRound(aB2DPoint0.getX()), FRound(aB2DPoint0.getY())); + const Point aPoint1(FRound(aB2DPoint1.getX()), FRound(aB2DPoint1.getY())); + const Point aDelt(aPoint1 - aPoint0); + + aGeo.nDrehWink=GetAngle(aDelt); + aGeo.nShearWink=0; + aGeo.RecalcSinCos(); + aGeo.RecalcTan(); + + // #101412# for SdrTextObj, keep aRect up to date + aRect = Rectangle(aPoint0, aPoint1); + aRect.Justify(); + } +} + +void SdrPathObj::ImpForceKind() +{ + if (meKind==OBJ_PATHPLIN) meKind=OBJ_PLIN; + if (meKind==OBJ_PATHPOLY) meKind=OBJ_POLY; + + if(GetPathPoly().areControlPointsUsed()) + { + switch (meKind) + { + case OBJ_LINE: meKind=OBJ_PATHLINE; break; + case OBJ_PLIN: meKind=OBJ_PATHLINE; break; + case OBJ_POLY: meKind=OBJ_PATHFILL; break; + default: break; + } + } + else + { + switch (meKind) + { + case OBJ_PATHLINE: meKind=OBJ_PLIN; break; + case OBJ_FREELINE: meKind=OBJ_PLIN; break; + case OBJ_PATHFILL: meKind=OBJ_POLY; break; + case OBJ_FREEFILL: meKind=OBJ_POLY; break; + default: break; + } + } + + if (meKind==OBJ_LINE && !ImpIsLine(GetPathPoly())) meKind=OBJ_PLIN; + if (meKind==OBJ_PLIN && ImpIsLine(GetPathPoly())) meKind=OBJ_LINE; + + bClosedObj=IsClosed(); + + if (meKind==OBJ_LINE) + { + ImpForceLineWink(); + } + else + { + // #i10659#, similar to #101412# but for polys with more than 2 points. + // + // Here i again need to fix something, because when Path-Polys are Copy-Pasted + // between Apps with different measurements (e.g. 100TH_MM and TWIPS) there is + // a scaling loop started from SdrExchangeView::Paste. This is principally nothing + // wrong, but aRect is wrong here and not even updated by RecalcSnapRect(). If + // this is the case, some size needs to be set here in aRect to avoid that the cyclus + // through Rect2Poly - Poly2Rect does something badly wrong since that cycle is + // BASED on aRect. That cycle is triggered in SdrTextObj::NbcResize() which is called + // from the local Resize() implementation. + // + // Basic problem is that the member aRect in SdrTextObj basically is a unrotated + // text rectangle for the text object itself and methods at SdrTextObj do handle it + // in that way. Many draw objects derived from SdrTextObj 'abuse' aRect as SnapRect + // which is basically wrong. To make the SdrText methods which deal with aRect directly + // work it is necessary to always keep aRect updated. This e.g. not done after a Clone() + // command for SdrPathObj. Since adding this update mechanism with #101412# to + // ImpForceLineWink() for lines was very successful, i add it to where ImpForceLineWink() + // was called, once here below and once on a 2nd place below. + + // #i10659# for SdrTextObj, keep aRect up to date + if(GetPathPoly().count()) + { + aRect = ImpGetBoundRect(GetPathPoly()); + } + } + + // #i75974# adapt polygon state to object type. This may include a reinterpretation + // of a closed geometry as open one, but with identical first and last point + for(sal_uInt32 a(0); a < maPathPolygon.count(); a++) + { + basegfx::B2DPolygon aCandidate(maPathPolygon.getB2DPolygon(a)); + + if((bool)IsClosed() != aCandidate.isClosed()) + { + // #i80213# really change polygon geometry; else e.g. the last point which + // needs to be identical with the first one will be missing when opening + // due to OBJ_PATH type + if(aCandidate.isClosed()) + { + basegfx::tools::openWithGeometryChange(aCandidate); + } + else + { + basegfx::tools::closeWithGeometryChange(aCandidate); + } + + maPathPolygon.setB2DPolygon(a, aCandidate); + } + } +} + +void SdrPathObj::ImpSetClosed(sal_Bool bClose) +{ + if(bClose) + { + switch (meKind) + { + case OBJ_LINE : meKind=OBJ_POLY; break; + case OBJ_PLIN : meKind=OBJ_POLY; break; + case OBJ_PATHLINE: meKind=OBJ_PATHFILL; break; + case OBJ_FREELINE: meKind=OBJ_FREEFILL; break; + case OBJ_SPLNLINE: meKind=OBJ_SPLNFILL; break; + default: break; + } + + bClosedObj = TRUE; + } + else + { + switch (meKind) + { + case OBJ_POLY : meKind=OBJ_PLIN; break; + case OBJ_PATHFILL: meKind=OBJ_PATHLINE; break; + case OBJ_FREEFILL: meKind=OBJ_FREELINE; break; + case OBJ_SPLNFILL: meKind=OBJ_SPLNLINE; break; + default: break; + } + + bClosedObj = FALSE; + } + + ImpForceKind(); +} + +void SdrPathObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bNoContortion=FALSE; + + FASTBOOL bCanConv = !HasText() || ImpCanConvTextToCurve(); + FASTBOOL bIsPath = IsBezier() || IsSpline(); + + rInfo.bEdgeRadiusAllowed = FALSE; + rInfo.bCanConvToPath = bCanConv && !bIsPath; + rInfo.bCanConvToPoly = bCanConv && bIsPath; + rInfo.bCanConvToContour = !IsFontwork() && (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +UINT16 SdrPathObj::GetObjIdentifier() const +{ + return USHORT(meKind); +} + +void SdrPathObj::operator=(const SdrObject& rObj) +{ + SdrTextObj::operator=(rObj); + SdrPathObj& rPath=(SdrPathObj&)rObj; + maPathPolygon=rPath.GetPathPoly(); +} + +void SdrPathObj::TakeObjNameSingul(XubString& rName) const +{ + if(OBJ_LINE == meKind) + { + sal_uInt16 nId(STR_ObjNameSingulLINE); + + if(ImpIsLine(GetPathPoly())) + { + const basegfx::B2DPolygon aPoly(GetPathPoly().getB2DPolygon(0L)); + const basegfx::B2DPoint aB2DPoint0(aPoly.getB2DPoint(0L)); + const basegfx::B2DPoint aB2DPoint1(aPoly.getB2DPoint(1L)); + const Point aPoint0(FRound(aB2DPoint0.getX()), FRound(aB2DPoint0.getY())); + const Point aPoint1(FRound(aB2DPoint0.getX()), FRound(aB2DPoint0.getY())); + + if(aB2DPoint0 != aB2DPoint1) + { + if(aB2DPoint0.getY() == aB2DPoint1.getY()) + { + nId = STR_ObjNameSingulLINE_Hori; + } + else if(aB2DPoint0.getX() == aB2DPoint1.getX()) + { + nId = STR_ObjNameSingulLINE_Vert; + } + else + { + const double fDx(fabs(aB2DPoint0.getX() - aB2DPoint1.getX())); + const double fDy(fabs(aB2DPoint0.getY() - aB2DPoint1.getY())); + + if(fDx == fDy) + { + nId = STR_ObjNameSingulLINE_Diag; + } + } + } + } + + rName = ImpGetResStr(nId); + } + else if(OBJ_PLIN == meKind || OBJ_POLY == meKind) + { + const sal_Bool bClosed(OBJ_POLY == meKind); + sal_uInt16 nId(0); + + if(mpDAC && mpDAC->IsCreating()) + { + if(bClosed) + { + nId = STR_ObjNameSingulPOLY; + } + else + { + nId = STR_ObjNameSingulPLIN; + } + + rName = ImpGetResStr(nId); + } + else + { + // get point count + sal_uInt32 nPointCount(0L); + const sal_uInt32 nPolyCount(GetPathPoly().count()); + + for(sal_uInt32 a(0L); a < nPolyCount; a++) + { + nPointCount += GetPathPoly().getB2DPolygon(a).count(); + } + + if(bClosed) + { + nId = STR_ObjNameSingulPOLY_PntAnz; + } + else + { + nId = STR_ObjNameSingulPLIN_PntAnz; + } + + rName = ImpGetResStr(nId); + sal_uInt16 nPos(rName.SearchAscii("%2")); // #i96537# + + if(STRING_NOTFOUND != nPos) + { + rName.Erase(nPos, 2); + rName.Insert(UniString::CreateFromInt32(nPointCount), nPos); + } + } + } + else + { + switch (meKind) + { + case OBJ_PATHLINE: rName=ImpGetResStr(STR_ObjNameSingulPATHLINE); break; + case OBJ_FREELINE: rName=ImpGetResStr(STR_ObjNameSingulFREELINE); break; + case OBJ_SPLNLINE: rName=ImpGetResStr(STR_ObjNameSingulNATSPLN); break; + case OBJ_PATHFILL: rName=ImpGetResStr(STR_ObjNameSingulPATHFILL); break; + case OBJ_FREEFILL: rName=ImpGetResStr(STR_ObjNameSingulFREEFILL); break; + case OBJ_SPLNFILL: rName=ImpGetResStr(STR_ObjNameSingulPERSPLN); break; + default: break; + } + } + + String aName(GetName()); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrPathObj::TakeObjNamePlural(XubString& rName) const +{ + switch(meKind) + { + case OBJ_LINE : rName=ImpGetResStr(STR_ObjNamePluralLINE ); break; + case OBJ_PLIN : rName=ImpGetResStr(STR_ObjNamePluralPLIN ); break; + case OBJ_POLY : rName=ImpGetResStr(STR_ObjNamePluralPOLY ); break; + case OBJ_PATHLINE: rName=ImpGetResStr(STR_ObjNamePluralPATHLINE); break; + case OBJ_FREELINE: rName=ImpGetResStr(STR_ObjNamePluralFREELINE); break; + case OBJ_SPLNLINE: rName=ImpGetResStr(STR_ObjNamePluralNATSPLN); break; + case OBJ_PATHFILL: rName=ImpGetResStr(STR_ObjNamePluralPATHFILL); break; + case OBJ_FREEFILL: rName=ImpGetResStr(STR_ObjNamePluralFREEFILL); break; + case OBJ_SPLNFILL: rName=ImpGetResStr(STR_ObjNamePluralPERSPLN); break; + default: break; + } +} + +basegfx::B2DPolyPolygon SdrPathObj::TakeXorPoly() const +{ + return GetPathPoly(); +} + +sal_uInt32 SdrPathObj::GetHdlCount() const +{ + sal_uInt32 nRetval(0L); + const sal_uInt32 nPolyCount(GetPathPoly().count()); + + for(sal_uInt32 a(0L); a < nPolyCount; a++) + { + nRetval += GetPathPoly().getB2DPolygon(a).count(); + } + + return nRetval; +} + +SdrHdl* SdrPathObj::GetHdl(sal_uInt32 nHdlNum) const +{ + // #i73248# + // Warn the user that this is ineffective and show alternatives. Should not be used at all. + OSL_ENSURE(false, "SdrPathObj::GetHdl(): ineffective, use AddToHdlList instead (!)"); + + // to have an alternative, get single handle using the ineffective way + SdrHdl* pRetval = 0; + SdrHdlList aLocalList(0); + AddToHdlList(aLocalList); + const sal_uInt32 nHdlCount(aLocalList.GetHdlCount()); + + if(nHdlCount && nHdlNum < nHdlCount) + { + // remove and remember. The other created handles will be deleted again with the + // destruction of the local list + pRetval = aLocalList.RemoveHdl(nHdlNum); + } + + return pRetval; +} + +void SdrPathObj::AddToHdlList(SdrHdlList& rHdlList) const +{ + // keep old stuff to be able to keep old SdrHdl stuff, too + const XPolyPolygon aOldPathPolygon(GetPathPoly()); + USHORT nPolyCnt=aOldPathPolygon.Count(); + FASTBOOL bClosed=IsClosed(); + USHORT nIdx=0; + + for (USHORT i=0; i<nPolyCnt; i++) { + const XPolygon& rXPoly=aOldPathPolygon.GetObject(i); + USHORT nPntCnt=rXPoly.GetPointCount(); + if (bClosed && nPntCnt>1) nPntCnt--; + + for (USHORT j=0; j<nPntCnt; j++) { + if (rXPoly.GetFlags(j)!=XPOLY_CONTROL) { + const Point& rPnt=rXPoly[j]; + SdrHdl* pHdl=new SdrHdl(rPnt,HDL_POLY); + pHdl->SetPolyNum(i); + pHdl->SetPointNum(j); + pHdl->Set1PixMore(j==0); + pHdl->SetSourceHdlNum(nIdx); + nIdx++; + rHdlList.AddHdl(pHdl); + } + } + } +} + +sal_uInt32 SdrPathObj::GetPlusHdlCount(const SdrHdl& rHdl) const +{ + // keep old stuff to be able to keep old SdrHdl stuff, too + const XPolyPolygon aOldPathPolygon(GetPathPoly()); + sal_uInt16 nCnt = 0; + sal_uInt16 nPnt = (sal_uInt16)rHdl.GetPointNum(); + sal_uInt16 nPolyNum = (sal_uInt16)rHdl.GetPolyNum(); + + if(nPolyNum < aOldPathPolygon.Count()) + { + const XPolygon& rXPoly = aOldPathPolygon[nPolyNum]; + sal_uInt16 nPntMax = rXPoly.GetPointCount(); + if (nPntMax>0) + { + nPntMax--; + if (nPnt<=nPntMax) + { + if (rXPoly.GetFlags(nPnt)!=XPOLY_CONTROL) + { + if (nPnt==0 && IsClosed()) nPnt=nPntMax; + if (nPnt>0 && rXPoly.GetFlags(nPnt-1)==XPOLY_CONTROL) nCnt++; + if (nPnt==nPntMax && IsClosed()) nPnt=0; + if (nPnt<nPntMax && rXPoly.GetFlags(nPnt+1)==XPOLY_CONTROL) nCnt++; + } + } + } + } + + return nCnt; +} + +SdrHdl* SdrPathObj::GetPlusHdl(const SdrHdl& rHdl, sal_uInt32 nPlusNum) const +{ + // keep old stuff to be able to keep old SdrHdl stuff, too + const XPolyPolygon aOldPathPolygon(GetPathPoly()); + SdrHdl* pHdl = 0L; + sal_uInt16 nPnt = (sal_uInt16)rHdl.GetPointNum(); + sal_uInt16 nPolyNum = (sal_uInt16)rHdl.GetPolyNum(); + + if (nPolyNum<aOldPathPolygon.Count()) + { + const XPolygon& rXPoly = aOldPathPolygon[nPolyNum]; + sal_uInt16 nPntMax = rXPoly.GetPointCount(); + + if (nPntMax>0) + { + nPntMax--; + if (nPnt<=nPntMax) + { + pHdl=new SdrHdlBezWgt(&rHdl); + pHdl->SetPolyNum(rHdl.GetPolyNum()); + + if (nPnt==0 && IsClosed()) nPnt=nPntMax; + if (nPnt>0 && rXPoly.GetFlags(nPnt-1)==XPOLY_CONTROL && nPlusNum==0) + { + pHdl->SetPos(rXPoly[nPnt-1]); + pHdl->SetPointNum(nPnt-1); + } + else + { + if (nPnt==nPntMax && IsClosed()) nPnt=0; + if (nPnt<rXPoly.GetPointCount()-1 && rXPoly.GetFlags(nPnt+1)==XPOLY_CONTROL) + { + pHdl->SetPos(rXPoly[nPnt+1]); + pHdl->SetPointNum(nPnt+1); + } + } + + pHdl->SetSourceHdlNum(rHdl.GetSourceHdlNum()); + pHdl->SetPlusHdl(TRUE); + } + } + } + return pHdl; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrPathObj::hasSpecialDrag() const +{ + return true; +} + +bool SdrPathObj::beginSpecialDrag(SdrDragStat& rDrag) const +{ + ImpPathForDragAndCreate aDragAndCreate(*((SdrPathObj*)this)); + + return aDragAndCreate.beginPathDrag(rDrag); +} + +bool SdrPathObj::applySpecialDrag(SdrDragStat& rDrag) +{ + ImpPathForDragAndCreate aDragAndCreate(*this); + bool bRetval(aDragAndCreate.beginPathDrag(rDrag)); + + if(bRetval) + { + bRetval = aDragAndCreate.movePathDrag(rDrag); + } + + if(bRetval) + { + bRetval = aDragAndCreate.endPathDrag(rDrag); + } + + if(bRetval) + { + NbcSetPathPoly(aDragAndCreate.getModifiedPolyPolygon()); + } + + return bRetval; +} + +String SdrPathObj::getSpecialDragComment(const SdrDragStat& rDrag) const +{ + String aRetval; + + if(mpDAC) + { + // #i103058# also get a comment when in creation + const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj()); + + if(bCreateComment) + { + aRetval = mpDAC->getSpecialDragComment(rDrag); + } + } + else + { + ImpPathForDragAndCreate aDragAndCreate(*((SdrPathObj*)this)); + bool bDidWork(aDragAndCreate.beginPathDrag((SdrDragStat&)rDrag)); + + if(bDidWork) + { + aRetval = aDragAndCreate.getSpecialDragComment(rDrag); + } + } + + return aRetval; +} + +basegfx::B2DPolyPolygon SdrPathObj::getSpecialDragPoly(const SdrDragStat& rDrag) const +{ + basegfx::B2DPolyPolygon aRetval; + ImpPathForDragAndCreate aDragAndCreate(*((SdrPathObj*)this)); + bool bDidWork(aDragAndCreate.beginPathDrag((SdrDragStat&)rDrag)); + + if(bDidWork) + { + aRetval = aDragAndCreate.getSpecialDragPoly(rDrag); + } + + return aRetval; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrPathObj::BegCreate(SdrDragStat& rStat) +{ + impDeleteDAC(); + return impGetDAC().BegCreate(rStat); +} + +FASTBOOL SdrPathObj::MovCreate(SdrDragStat& rStat) +{ + return impGetDAC().MovCreate(rStat); +} + +FASTBOOL SdrPathObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + FASTBOOL bRetval(impGetDAC().EndCreate(rStat, eCmd)); + + if(bRetval && mpDAC) + { + SetPathPoly(mpDAC->getModifiedPolyPolygon()); + + // #i75974# Check for AutoClose feature. Moved here from ImpPathForDragAndCreate::EndCreate + // to be able to use the type-changing ImpSetClosed method + if(!IsClosedObj()) + { + SdrView* pView = rStat.GetView(); + + if(pView && pView->IsAutoClosePolys() && !pView->IsUseIncompatiblePathCreateInterface()) + { + OutputDevice* pOut = pView->GetFirstOutputDevice(); + + if(pOut) + { + if(GetPathPoly().count()) + { + const basegfx::B2DPolygon aCandidate(GetPathPoly().getB2DPolygon(0)); + + if(aCandidate.count() > 2) + { + // check distance of first and last point + const sal_Int32 nCloseDist(pOut->PixelToLogic(Size(pView->GetAutoCloseDistPix(), 0)).Width()); + const basegfx::B2DVector aDistVector(aCandidate.getB2DPoint(aCandidate.count() - 1) - aCandidate.getB2DPoint(0)); + + if(aDistVector.getLength() <= (double)nCloseDist) + { + // close it + ImpSetClosed(true); + } + } + } + } + } + } + + impDeleteDAC(); + } + + return bRetval; +} + +FASTBOOL SdrPathObj::BckCreate(SdrDragStat& rStat) +{ + return impGetDAC().BckCreate(rStat); +} + +void SdrPathObj::BrkCreate(SdrDragStat& rStat) +{ + impGetDAC().BrkCreate(rStat); + impDeleteDAC(); +} + +basegfx::B2DPolyPolygon SdrPathObj::TakeCreatePoly(const SdrDragStat& rDrag) const +{ + basegfx::B2DPolyPolygon aRetval; + + if(mpDAC) + { + aRetval = mpDAC->TakeObjectPolyPolygon(rDrag); + aRetval.append(mpDAC->TakeDragPolyPolygon(rDrag)); + } + + return aRetval; +} + +// during drag or create, allow accessing the so-far created/modified polyPolygon +basegfx::B2DPolyPolygon SdrPathObj::getObjectPolyPolygon(const SdrDragStat& rDrag) const +{ + basegfx::B2DPolyPolygon aRetval; + + if(mpDAC) + { + aRetval = mpDAC->TakeObjectPolyPolygon(rDrag); + } + + return aRetval; +} + +basegfx::B2DPolyPolygon SdrPathObj::getDragPolyPolygon(const SdrDragStat& rDrag) const +{ + basegfx::B2DPolyPolygon aRetval; + + if(mpDAC) + { + aRetval = mpDAC->TakeDragPolyPolygon(rDrag); + } + + return aRetval; +} + +Pointer SdrPathObj::GetCreatePointer() const +{ + return impGetDAC().GetCreatePointer(); +} + +void SdrPathObj::NbcMove(const Size& rSiz) +{ + maPathPolygon.transform(basegfx::tools::createTranslateB2DHomMatrix(rSiz.Width(), rSiz.Height())); + + // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints) + SdrTextObj::NbcMove(rSiz); +} + +void SdrPathObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-rRef.X(), -rRef.Y())); + aTrans = basegfx::tools::createScaleTranslateB2DHomMatrix( + double(xFact), double(yFact), rRef.X(), rRef.Y()) * aTrans; + maPathPolygon.transform(aTrans); + + // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints) + SdrTextObj::NbcResize(rRef,xFact,yFact); +} + +void SdrPathObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + // Thank JOE, the angles are defined mirrored to the mathematical meanings + const basegfx::B2DHomMatrix aTrans(basegfx::tools::createRotateAroundPoint(rRef.X(), rRef.Y(), -nWink * nPi180)); + maPathPolygon.transform(aTrans); + + // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints) + SdrTextObj::NbcRotate(rRef,nWink,sn,cs); +} + +void SdrPathObj::NbcShear(const Point& rRefPnt, long nAngle, double fTan, FASTBOOL bVShear) +{ + basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-rRefPnt.X(), -rRefPnt.Y())); + + if(bVShear) + { + // Thank JOE, the angles are defined mirrored to the mathematical meanings + aTrans.shearY(-fTan); + } + else + { + aTrans.shearX(-fTan); + } + + aTrans.translate(rRefPnt.X(), rRefPnt.Y()); + maPathPolygon.transform(aTrans); + + // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints) + SdrTextObj::NbcShear(rRefPnt,nAngle,fTan,bVShear); +} + +void SdrPathObj::NbcMirror(const Point& rRefPnt1, const Point& rRefPnt2) +{ + const double fDiffX(rRefPnt2.X() - rRefPnt1.X()); + const double fDiffY(rRefPnt2.Y() - rRefPnt1.Y()); + const double fRot(atan2(fDiffY, fDiffX)); + basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-rRefPnt1.X(), -rRefPnt1.Y())); + aTrans.rotate(-fRot); + aTrans.scale(1.0, -1.0); + aTrans.rotate(fRot); + aTrans.translate(rRefPnt1.X(), rRefPnt1.Y()); + maPathPolygon.transform(aTrans); + + // #97538# Do Joe's special handling for lines when mirroring, too + ImpForceKind(); + + // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints) + SdrTextObj::NbcMirror(rRefPnt1,rRefPnt2); +} + +void SdrPathObj::TakeUnrotatedSnapRect(Rectangle& rRect) const +{ + if(!aGeo.nDrehWink) + { + rRect = GetSnapRect(); + } + else + { + XPolyPolygon aXPP(GetPathPoly()); + RotateXPoly(aXPP,Point(),-aGeo.nSin,aGeo.nCos); + rRect=aXPP.GetBoundRect(); + Point aTmp(rRect.TopLeft()); + RotatePoint(aTmp,Point(),aGeo.nSin,aGeo.nCos); + aTmp-=rRect.TopLeft(); + rRect.Move(aTmp.X(),aTmp.Y()); + } +} + +void SdrPathObj::RecalcSnapRect() +{ + if(GetPathPoly().count()) + { + maSnapRect = ImpGetBoundRect(GetPathPoly()); + } +} + +void SdrPathObj::NbcSetSnapRect(const Rectangle& rRect) +{ + Rectangle aOld(GetSnapRect()); + + // #95736# Take RECT_EMPTY into account when calculating scale factors + long nMulX = (RECT_EMPTY == rRect.Right()) ? 0 : rRect.Right() - rRect.Left(); + + long nDivX = aOld.Right() - aOld.Left(); + + // #95736# Take RECT_EMPTY into account when calculating scale factors + long nMulY = (RECT_EMPTY == rRect.Bottom()) ? 0 : rRect.Bottom() - rRect.Top(); + + long nDivY = aOld.Bottom() - aOld.Top(); + if ( nDivX == 0 ) { nMulX = 1; nDivX = 1; } + if ( nDivY == 0 ) { nMulY = 1; nDivY = 1; } + Fraction aX(nMulX,nDivX); + Fraction aY(nMulY,nDivY); + NbcResize(aOld.TopLeft(), aX, aY); + NbcMove(Size(rRect.Left() - aOld.Left(), rRect.Top() - aOld.Top())); +} + +sal_uInt32 SdrPathObj::GetSnapPointCount() const +{ + return GetHdlCount(); +} + +Point SdrPathObj::GetSnapPoint(sal_uInt32 nSnapPnt) const +{ + sal_uInt32 nPoly,nPnt; + if(!PolyPolygonEditor::GetRelativePolyPoint(GetPathPoly(), nSnapPnt, nPoly, nPnt)) + { + DBG_ASSERT(FALSE,"SdrPathObj::GetSnapPoint: Punkt nSnapPnt nicht vorhanden!"); + } + + const basegfx::B2DPoint aB2DPoint(GetPathPoly().getB2DPolygon(nPoly).getB2DPoint(nPnt)); + return Point(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY())); +} + +sal_Bool SdrPathObj::IsPolyObj() const +{ + return sal_True; +} + +sal_uInt32 SdrPathObj::GetPointCount() const +{ + const sal_uInt32 nPolyCount(GetPathPoly().count()); + sal_uInt32 nRetval(0L); + + for(sal_uInt32 a(0L); a < nPolyCount; a++) + { + nRetval += GetPathPoly().getB2DPolygon(a).count(); + } + + return nRetval; +} + +Point SdrPathObj::GetPoint(sal_uInt32 nHdlNum) const +{ + Point aRetval; + sal_uInt32 nPoly,nPnt; + + if(PolyPolygonEditor::GetRelativePolyPoint(GetPathPoly(), nHdlNum, nPoly, nPnt)) + { + const basegfx::B2DPolygon aPoly(GetPathPoly().getB2DPolygon(nPoly)); + const basegfx::B2DPoint aPoint(aPoly.getB2DPoint(nPnt)); + aRetval = Point(FRound(aPoint.getX()), FRound(aPoint.getY())); + } + + return aRetval; +} + +void SdrPathObj::NbcSetPoint(const Point& rPnt, sal_uInt32 nHdlNum) +{ + sal_uInt32 nPoly,nPnt; + + if(PolyPolygonEditor::GetRelativePolyPoint(GetPathPoly(), nHdlNum, nPoly, nPnt)) + { + basegfx::B2DPolygon aNewPolygon(GetPathPoly().getB2DPolygon(nPoly)); + aNewPolygon.setB2DPoint(nPnt, basegfx::B2DPoint(rPnt.X(), rPnt.Y())); + maPathPolygon.setB2DPolygon(nPoly, aNewPolygon); + + if(meKind==OBJ_LINE) + { + ImpForceLineWink(); + } + else + { + if(GetPathPoly().count()) + { + // #i10659# for SdrTextObj, keep aRect up to date + aRect = ImpGetBoundRect(GetPathPoly()); // fuer SdrTextObj# + } + } + + SetRectsDirty(); + } +} + +sal_uInt32 SdrPathObj::NbcInsPointOld(const Point& rPos, sal_Bool bNewObj, sal_Bool bHideHim) +{ + sal_uInt32 nNewHdl; + + if(bNewObj) + { + nNewHdl = NbcInsPoint(0L, rPos, sal_True, bHideHim); + } + else + { + // look for smallest distance data + const basegfx::B2DPoint aTestPoint(rPos.X(), rPos.Y()); + sal_uInt32 nSmallestPolyIndex(0L); + sal_uInt32 nSmallestEdgeIndex(0L); + double fSmallestCut; + basegfx::tools::getSmallestDistancePointToPolyPolygon(GetPathPoly(), aTestPoint, nSmallestPolyIndex, nSmallestEdgeIndex, fSmallestCut); + + // create old polygon index from it + sal_uInt32 nPolyIndex(nSmallestEdgeIndex); + + for(sal_uInt32 a(0L); a < nSmallestPolyIndex; a++) + { + nPolyIndex += GetPathPoly().getB2DPolygon(a).count(); + } + + nNewHdl = NbcInsPoint(nPolyIndex, rPos, sal_False, bHideHim); + } + + ImpForceKind(); + return nNewHdl; +} + +sal_uInt32 SdrPathObj::NbcInsPoint(sal_uInt32 /*nHdlNum*/, const Point& rPos, sal_Bool bNewObj, sal_Bool /*bHideHim*/) +{ + sal_uInt32 nNewHdl; + + if(bNewObj) + { + basegfx::B2DPolygon aNewPoly; + const basegfx::B2DPoint aPoint(rPos.X(), rPos.Y()); + aNewPoly.append(aPoint); + aNewPoly.setClosed(IsClosed()); + maPathPolygon.append(aNewPoly); + SetRectsDirty(); + nNewHdl = GetHdlCount(); + } + else + { + // look for smallest distance data + const basegfx::B2DPoint aTestPoint(rPos.X(), rPos.Y()); + sal_uInt32 nSmallestPolyIndex(0L); + sal_uInt32 nSmallestEdgeIndex(0L); + double fSmallestCut; + basegfx::tools::getSmallestDistancePointToPolyPolygon(GetPathPoly(), aTestPoint, nSmallestPolyIndex, nSmallestEdgeIndex, fSmallestCut); + basegfx::B2DPolygon aCandidate(GetPathPoly().getB2DPolygon(nSmallestPolyIndex)); + const bool bBefore(!aCandidate.isClosed() && 0L == nSmallestEdgeIndex && 0.0 == fSmallestCut); + const bool bAfter(!aCandidate.isClosed() && aCandidate.count() == nSmallestEdgeIndex + 2L && 1.0 == fSmallestCut); + + if(bBefore) + { + // before first point + aCandidate.insert(0L, aTestPoint); + + if(aCandidate.areControlPointsUsed()) + { + if(aCandidate.isNextControlPointUsed(1)) + { + aCandidate.setNextControlPoint(0, interpolate(aTestPoint, aCandidate.getB2DPoint(1), (1.0 / 3.0))); + aCandidate.setPrevControlPoint(1, interpolate(aTestPoint, aCandidate.getB2DPoint(1), (2.0 / 3.0))); + } + } + + nNewHdl = 0L; + } + else if(bAfter) + { + // after last point + aCandidate.append(aTestPoint); + + if(aCandidate.areControlPointsUsed()) + { + if(aCandidate.isPrevControlPointUsed(aCandidate.count() - 2)) + { + aCandidate.setNextControlPoint(aCandidate.count() - 2, interpolate(aCandidate.getB2DPoint(aCandidate.count() - 2), aTestPoint, (1.0 / 3.0))); + aCandidate.setPrevControlPoint(aCandidate.count() - 1, interpolate(aCandidate.getB2DPoint(aCandidate.count() - 2), aTestPoint, (2.0 / 3.0))); + } + } + + nNewHdl = aCandidate.count() - 1L; + } + else + { + // in between + bool bSegmentSplit(false); + const sal_uInt32 nNextIndex((nSmallestEdgeIndex + 1) % aCandidate.count()); + + if(aCandidate.areControlPointsUsed()) + { + if(aCandidate.isNextControlPointUsed(nSmallestEdgeIndex) || aCandidate.isPrevControlPointUsed(nNextIndex)) + { + bSegmentSplit = true; + } + } + + if(bSegmentSplit) + { + // rebuild original segment to get the split data + basegfx::B2DCubicBezier aBezierA, aBezierB; + const basegfx::B2DCubicBezier aBezier( + aCandidate.getB2DPoint(nSmallestEdgeIndex), + aCandidate.getNextControlPoint(nSmallestEdgeIndex), + aCandidate.getPrevControlPoint(nNextIndex), + aCandidate.getB2DPoint(nNextIndex)); + + // split and insert hit point + aBezier.split(fSmallestCut, &aBezierA, &aBezierB); + aCandidate.insert(nSmallestEdgeIndex + 1, aTestPoint); + + // since we inserted hit point and not split point, we need to add an offset + // to the control points to get the C1 continuity we want to achieve + const basegfx::B2DVector aOffset(aTestPoint - aBezierA.getEndPoint()); + aCandidate.setNextControlPoint(nSmallestEdgeIndex, aBezierA.getControlPointA() + aOffset); + aCandidate.setPrevControlPoint(nSmallestEdgeIndex + 1, aBezierA.getControlPointB() + aOffset); + aCandidate.setNextControlPoint(nSmallestEdgeIndex + 1, aBezierB.getControlPointA() + aOffset); + aCandidate.setPrevControlPoint((nSmallestEdgeIndex + 2) % aCandidate.count(), aBezierB.getControlPointB() + aOffset); + } + else + { + aCandidate.insert(nSmallestEdgeIndex + 1L, aTestPoint); + } + + nNewHdl = nSmallestEdgeIndex + 1L; + } + + maPathPolygon.setB2DPolygon(nSmallestPolyIndex, aCandidate); + + // create old polygon index from it + for(sal_uInt32 a(0L); a < nSmallestPolyIndex; a++) + { + nNewHdl += GetPathPoly().getB2DPolygon(a).count(); + } + } + + ImpForceKind(); + return nNewHdl; +} + +SdrObject* SdrPathObj::RipPoint(sal_uInt32 nHdlNum, sal_uInt32& rNewPt0Index) +{ + SdrPathObj* pNewObj = 0L; + const basegfx::B2DPolyPolygon aLocalPolyPolygon(GetPathPoly()); + sal_uInt32 nPoly, nPnt; + + if(PolyPolygonEditor::GetRelativePolyPoint(aLocalPolyPolygon, nHdlNum, nPoly, nPnt)) + { + if(0L == nPoly) + { + const basegfx::B2DPolygon aCandidate(aLocalPolyPolygon.getB2DPolygon(nPoly)); + const sal_uInt32 nPointCount(aCandidate.count()); + + if(nPointCount) + { + if(IsClosed()) + { + // when closed, RipPoint means to open the polygon at the selected point. To + // be able to do that, it is necessary to make the selected point the first one + basegfx::B2DPolygon aNewPolygon(basegfx::tools::makeStartPoint(aCandidate, nPnt)); + SetPathPoly(basegfx::B2DPolyPolygon(aNewPolygon)); + ToggleClosed(); + + // give back new position of old start point (historical reasons) + rNewPt0Index = (nPointCount - nPnt) % nPointCount; + } + else + { + if(nPointCount >= 3L && nPnt != 0L && nPnt + 1L < nPointCount) + { + // split in two objects at point nPnt + basegfx::B2DPolygon aSplitPolyA(aCandidate, 0L, nPnt + 1L); + SetPathPoly(basegfx::B2DPolyPolygon(aSplitPolyA)); + + pNewObj = (SdrPathObj*)Clone(); + basegfx::B2DPolygon aSplitPolyB(aCandidate, nPnt, nPointCount - nPnt); + pNewObj->SetPathPoly(basegfx::B2DPolyPolygon(aSplitPolyB)); + } + } + } + } + } + + return pNewObj; +} + +SdrObject* SdrPathObj::DoConvertToPolyObj(BOOL bBezier) const +{ + // #i89784# check for FontWork with activated HideContour + const drawinglayer::attribute::SdrTextAttribute aText( + drawinglayer::primitive2d::createNewSdrTextAttribute(GetObjectItemSet(), *getText(0))); + const bool bHideContour( + !aText.isDefault() && !aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour()); + + SdrObject* pRet = bHideContour ? + 0 : + ImpConvertMakeObj(GetPathPoly(), IsClosed(), bBezier); + + SdrPathObj* pPath = PTR_CAST(SdrPathObj, pRet); + + if(pPath) + { + if(pPath->GetPathPoly().areControlPointsUsed()) + { + if(!bBezier) + { + // reduce all bezier curves + pPath->SetPathPoly(basegfx::tools::adaptiveSubdivideByAngle(pPath->GetPathPoly())); + } + } + else + { + if(bBezier) + { + // create bezier curves + pPath->SetPathPoly(basegfx::tools::expandToCurve(pPath->GetPathPoly())); + } + } + } + + pRet = ImpConvertAddText(pRet, bBezier); + + return pRet; +} + +SdrObjGeoData* SdrPathObj::NewGeoData() const +{ + return new SdrPathObjGeoData; +} + +void SdrPathObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrTextObj::SaveGeoData(rGeo); + SdrPathObjGeoData& rPGeo = (SdrPathObjGeoData&) rGeo; + rPGeo.maPathPolygon=GetPathPoly(); + rPGeo.meKind=meKind; +} + +void SdrPathObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrTextObj::RestGeoData(rGeo); + SdrPathObjGeoData& rPGeo=(SdrPathObjGeoData&)rGeo; + maPathPolygon=rPGeo.maPathPolygon; + meKind=rPGeo.meKind; + ImpForceKind(); // damit u.a. bClosed gesetzt wird +} + +void SdrPathObj::NbcSetPathPoly(const basegfx::B2DPolyPolygon& rPathPoly) +{ + if(GetPathPoly() != rPathPoly) + { + maPathPolygon=rPathPoly; + ImpForceKind(); + SetRectsDirty(); + } +} + +void SdrPathObj::SetPathPoly(const basegfx::B2DPolyPolygon& rPathPoly) +{ + if(GetPathPoly() != rPathPoly) + { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + NbcSetPathPoly(rPathPoly); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrPathObj::ToggleClosed() // long nOpenDistance) +{ + Rectangle aBoundRect0; + if(pUserCall != NULL) + aBoundRect0 = GetLastBoundRect(); + ImpSetClosed(!IsClosed()); // neuen ObjKind setzen + ImpForceKind(); // wg. Line->Poly->PolyLine statt Line->Poly->Line + SetRectsDirty(); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0); +} + +// fuer friend class SdrPolyEditView auf einigen Compilern: +void SdrPathObj::SetRectsDirty(sal_Bool bNotMyself) +{ + SdrTextObj::SetRectsDirty(bNotMyself); +} + +ImpPathForDragAndCreate& SdrPathObj::impGetDAC() const +{ + if(!mpDAC) + { + ((SdrPathObj*)this)->mpDAC = new ImpPathForDragAndCreate(*((SdrPathObj*)this)); + } + + return *mpDAC; +} + +void SdrPathObj::impDeleteDAC() const +{ + if(mpDAC) + { + delete mpDAC; + ((SdrPathObj*)this)->mpDAC = 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// transformation interface for StarOfficeAPI. This implements support for +// homogen 3x3 matrices containing the transformation of the SdrObject. At the +// moment it contains a shearX, rotation and translation, but for setting all linear +// transforms like Scale, ShearX, ShearY, Rotate and Translate are supported. +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon +// with the base geometry and returns TRUE. Otherwise it returns FALSE. +sal_Bool SdrPathObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon) const +{ + double fRotate(0.0); + double fShearX(0.0); + basegfx::B2DTuple aScale(1.0, 1.0); + basegfx::B2DTuple aTranslate(0.0, 0.0); + + if(GetPathPoly().count()) + { + // copy geometry + basegfx::B2DHomMatrix aMoveToZeroMatrix; + rPolyPolygon = GetPathPoly(); + + if(OBJ_LINE == meKind) + { + // ignore shear and rotate, just use scale and translate + OSL_ENSURE(GetPathPoly().count() > 0L && GetPathPoly().getB2DPolygon(0L).count() > 1L, "OBJ_LINE with too less polygons (!)"); + // #i72287# use polygon without control points for range calculation. Do not change rPolyPolygon + // itself, else this method will no longer return the full polygon information (curve will + // be lost) + const basegfx::B2DRange aPolyRangeNoCurve(basegfx::tools::getRange(rPolyPolygon)); + aScale = aPolyRangeNoCurve.getRange(); + aTranslate = aPolyRangeNoCurve.getMinimum(); + + // define matrix for move polygon to zero point + aMoveToZeroMatrix.translate(-aTranslate.getX(), -aTranslate.getY()); + } + else + { + if(aGeo.nShearWink || aGeo.nDrehWink) + { + // get rotate and shear in drawingLayer notation + fRotate = aGeo.nDrehWink * F_PI18000; + fShearX = aGeo.nShearWink * F_PI18000; + + // build mathematically correct (negative shear and rotate) object transform + // containing shear and rotate to extract unsheared, unrotated polygon + basegfx::B2DHomMatrix aObjectMatrix; + aObjectMatrix.shearX(tan((36000 - aGeo.nShearWink) * F_PI18000)); + aObjectMatrix.rotate((36000 - aGeo.nDrehWink) * F_PI18000); + + // create inverse from it and back-transform polygon + basegfx::B2DHomMatrix aInvObjectMatrix(aObjectMatrix); + aInvObjectMatrix.invert(); + rPolyPolygon.transform(aInvObjectMatrix); + + // get range from unsheared, unrotated polygon and extract scale and translate. + // transform topLeft from it back to transformed state to get original + // topLeft (rotation center) + // #i72287# use polygon without control points for range calculation. Do not change rPolyPolygon + // itself, else this method will no longer return the full polygon information (curve will + // be lost) + const basegfx::B2DRange aCorrectedRangeNoCurve(basegfx::tools::getRange(rPolyPolygon)); + aTranslate = aObjectMatrix * aCorrectedRangeNoCurve.getMinimum(); + aScale = aCorrectedRangeNoCurve.getRange(); + + // define matrix for move polygon to zero point + aMoveToZeroMatrix.translate(-aCorrectedRangeNoCurve.getMinX(), aCorrectedRangeNoCurve.getMinY()); + } + else + { + // get scale and translate from unsheared, unrotated polygon + // #i72287# use polygon without control points for range calculation. Do not change rPolyPolygon + // itself, else this method will no longer return the full polygon information (curve will + // be lost) + const basegfx::B2DRange aPolyRangeNoCurve(basegfx::tools::getRange(rPolyPolygon)); + aScale = aPolyRangeNoCurve.getRange(); + aTranslate = aPolyRangeNoCurve.getMinimum(); + + // define matrix for move polygon to zero point + aMoveToZeroMatrix.translate(-aTranslate.getX(), -aTranslate.getY()); + } + } + + // move polygon to zero point with pre-defined matrix + rPolyPolygon.transform(aMoveToZeroMatrix); + } + + // position maybe relative to anchorpos, convert + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // force MapUnit to 100th mm + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // postion + aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); + aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); + + // size + aScale.setX(ImplTwipsToMM(aScale.getX())); + aScale.setY(ImplTwipsToMM(aScale.getY())); + + // polygon + basegfx::B2DHomMatrix aTwipsToMM; + const double fFactorTwipsToMM(127.0 / 72.0); + aTwipsToMM.scale(fFactorTwipsToMM, fFactorTwipsToMM); + rPolyPolygon.transform(aTwipsToMM); + + break; + } + default: + { + DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); + } + } + } + + // build return value matrix + rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX), + basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate, + aTranslate); + + return sal_True; +} + +// sets the base geometry of the object using infos contained in the homogen 3x3 matrix. +// If it's an SdrPathObj it will use the provided geometry information. The Polygon has +// to use (0,0) as upper left and will be scaled to the given size in the matrix. +void SdrPathObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon) +{ + // break up matrix + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate, fShearX; + rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings + // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale.setX(fabs(aScale.getX())); + aScale.setY(fabs(aScale.getY())); + fRotate = fmod(fRotate + F_PI, F_2PI); + } + + // copy poly + basegfx::B2DPolyPolygon aNewPolyPolygon(rPolyPolygon); + + // reset object shear and rotations + aGeo.nDrehWink = 0; + aGeo.RecalcSinCos(); + aGeo.nShearWink = 0; + aGeo.RecalcTan(); + + // force metric to pool metric + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // position + aTranslate.setX(ImplMMToTwips(aTranslate.getX())); + aTranslate.setY(ImplMMToTwips(aTranslate.getY())); + + // size + aScale.setX(ImplMMToTwips(aScale.getX())); + aScale.setY(ImplMMToTwips(aScale.getY())); + + // polygon + basegfx::B2DHomMatrix aMMToTwips; + const double fFactorMMToTwips(72.0 / 127.0); + aMMToTwips.scale(fFactorMMToTwips, fFactorMMToTwips); + aNewPolyPolygon.transform(aMMToTwips); + + break; + } + default: + { + DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); + } + } + } + + if( pModel && pModel->IsWriter() ) + { + // if anchor is used, make position relative to it + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // create transformation for polygon, set values at aGeo direct + basegfx::B2DHomMatrix aTransform; + + // #i75086# + // Given polygon is already scaled (for historical reasons), but not mirrored yet. + // Thus, when scale is negative in X or Y, apply the needed mirroring accordingly. + if(basegfx::fTools::less(aScale.getX(), 0.0) || basegfx::fTools::less(aScale.getY(), 0.0)) + { + aTransform.scale( + basegfx::fTools::less(aScale.getX(), 0.0) ? -1.0 : 1.0, + basegfx::fTools::less(aScale.getY(), 0.0) ? -1.0 : 1.0); + } + + if(!basegfx::fTools::equalZero(fShearX)) + { + aTransform.shearX(tan(-atan(fShearX))); + aGeo.nShearWink = FRound(atan(fShearX) / F_PI18000); + aGeo.RecalcTan(); + } + + if(!basegfx::fTools::equalZero(fRotate)) + { + // #i78696# + // fRotate is matematically correct for linear transformations, so it's + // the one to use for the geometry change + aTransform.rotate(fRotate); + + // #i78696# + // fRotate is matematically correct, but aGeoStat.nDrehWink is + // mirrored -> mirror value here + aGeo.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000)); + aGeo.RecalcSinCos(); + } + + if(!aTranslate.equalZero()) + { + // #i39529# absolute positioning, so get current position (without control points (!)) + const basegfx::B2DRange aCurrentRange(basegfx::tools::getRange(aNewPolyPolygon)); + aTransform.translate(aTranslate.getX() - aCurrentRange.getMinX(), aTranslate.getY() - aCurrentRange.getMinY()); + } + + // transform polygon and trigger change + aNewPolyPolygon.transform(aTransform); + SetPathPoly(aNewPolyPolygon); +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdorect.cxx b/svx/source/svdraw/svdorect.cxx new file mode 100644 index 000000000000..b03dbf5b903a --- /dev/null +++ b/svx/source/svdraw/svdorect.cxx @@ -0,0 +1,620 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdorect.hxx> +#include <math.h> +#include <stdlib.h> +#include <svx/xpool.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svddrag.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdocapt.hxx> // fuer Import von SdrFileVersion 2 +#include <svx/svdpagv.hxx> // fuer +#include <svx/svdview.hxx> // das +#include <svx/svdundo.hxx> // Macro-Beispiel +#include <svx/svdopath.hxx> +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname +#include <svx/xflclit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnwtit.hxx> +#include "svdoimp.hxx" +#include <svx/sdr/properties/rectangleproperties.hxx> +#include <svx/sdr/contact/viewcontactofsdrrectobj.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrRectObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::RectangleProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrRectObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrRectObj(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrRectObj,SdrTextObj); + +SdrRectObj::SdrRectObj() +: mpXPoly(0L) +{ + bClosedObj=TRUE; +} + +SdrRectObj::SdrRectObj(const Rectangle& rRect) +: SdrTextObj(rRect), + mpXPoly(NULL) +{ + bClosedObj=TRUE; +} + +SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind) +: SdrTextObj(eNewTextKind), + mpXPoly(NULL) +{ + DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT || + eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT, + "SdrRectObj::SdrRectObj(SdrObjKind) ist nur fuer Textrahmen gedacht"); + bClosedObj=TRUE; +} + +SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rRect) +: SdrTextObj(eNewTextKind,rRect), + mpXPoly(NULL) +{ + DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT || + eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT, + "SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht"); + bClosedObj=TRUE; +} + +SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect, SvStream& rInput, const String& rBaseURL, USHORT eFormat) +: SdrTextObj(eNewTextKind,rNewRect,rInput,rBaseURL,eFormat), + mpXPoly(NULL) +{ + DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT || + eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT, + "SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht"); + bClosedObj=TRUE; +} + +SdrRectObj::~SdrRectObj() +{ + if(mpXPoly) + { + delete mpXPoly; + } +} + +void SdrRectObj::SetXPolyDirty() +{ + if(mpXPoly) + { + delete mpXPoly; + mpXPoly = 0L; + } +} + +FASTBOOL SdrRectObj::PaintNeedsXPoly(long nEckRad) const +{ + FASTBOOL bNeed=aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || nEckRad!=0; + return bNeed; +} + +XPolygon SdrRectObj::ImpCalcXPoly(const Rectangle& rRect1, long nRad1) const +{ + XPolygon aXPoly(rRect1,nRad1,nRad1); + const sal_uInt16 nPointAnz(aXPoly.GetPointCount()); + XPolygon aNeuPoly(nPointAnz+1); + sal_uInt16 nShift=nPointAnz-2; + if (nRad1!=0) nShift=nPointAnz-5; + sal_uInt16 j=nShift; + for (sal_uInt16 i=1; i<nPointAnz; i++) { + aNeuPoly[i]=aXPoly[j]; + aNeuPoly.SetFlags(i,aXPoly.GetFlags(j)); + j++; + if (j>=nPointAnz) j=1; + } + aNeuPoly[0]=rRect1.BottomCenter(); + aNeuPoly[nPointAnz]=aNeuPoly[0]; + aXPoly=aNeuPoly; + + // Die Winkelangaben beziehen sich immer auf die linke obere Ecke von !aRect! + if (aGeo.nShearWink!=0) ShearXPoly(aXPoly,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotateXPoly(aXPoly,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + return aXPoly; +} + +void SdrRectObj::RecalcXPoly() +{ + mpXPoly = new XPolygon(ImpCalcXPoly(aRect,GetEckenradius())); +} + +const XPolygon& SdrRectObj::GetXPoly() const +{ + if(!mpXPoly) + { + ((SdrRectObj*)this)->RecalcXPoly(); + } + + return *mpXPoly; +} + +void SdrRectObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + FASTBOOL bNoTextFrame=!IsTextFrame(); + rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0; + rInfo.bResizePropAllowed=TRUE; + rInfo.bRotateFreeAllowed=TRUE; + rInfo.bRotate90Allowed =TRUE; + rInfo.bMirrorFreeAllowed=bNoTextFrame; + rInfo.bMirror45Allowed =bNoTextFrame; + rInfo.bMirror90Allowed =bNoTextFrame; + + // allow transparence + rInfo.bTransparenceAllowed = TRUE; + + // gradient depends on fillstyle + XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue(); + rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT); + + rInfo.bShearAllowed =bNoTextFrame; + rInfo.bEdgeRadiusAllowed=TRUE; + + FASTBOOL bCanConv=!HasText() || ImpCanConvTextToCurve(); + if (bCanConv && !bNoTextFrame && !HasText()) { + bCanConv=HasFill() || HasLine(); + } + rInfo.bCanConvToPath =bCanConv; + rInfo.bCanConvToPoly =bCanConv; + rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +UINT16 SdrRectObj::GetObjIdentifier() const +{ + if (IsTextFrame()) return UINT16(eTextKind); + else return UINT16(OBJ_RECT); +} + +void SdrRectObj::TakeUnrotatedSnapRect(Rectangle& rRect) const +{ + rRect=aRect; + if (aGeo.nShearWink!=0) { + long nDst=Round((aRect.Bottom()-aRect.Top())*aGeo.nTan); + if (aGeo.nShearWink>0) { + Point aRef(rRect.TopLeft()); + rRect.Left()-=nDst; + Point aTmpPt(rRect.TopLeft()); + RotatePoint(aTmpPt,aRef,aGeo.nSin,aGeo.nCos); + aTmpPt-=rRect.TopLeft(); + rRect.Move(aTmpPt.X(),aTmpPt.Y()); + } else { + rRect.Right()-=nDst; + } + } +} + +void SdrRectObj::TakeObjNameSingul(XubString& rName) const +{ + if (IsTextFrame()) + { + SdrTextObj::TakeObjNameSingul(rName); + } + else + { + USHORT nResId=STR_ObjNameSingulRECT; + if (aGeo.nShearWink!=0) { + nResId+=4; // Parallelogramm oder Raute + // Raute ist nicht, weil Shear die vertikalen Kanten verlaengert! + // Wenn Zeit ist, werde ich das mal berechnen. + } else { + if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat + } + if (GetEckenradius()!=0) nResId+=8; // abgerundet + rName=ImpGetResStr(nResId); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } + } +} + +void SdrRectObj::TakeObjNamePlural(XubString& rName) const +{ + if (IsTextFrame()) SdrTextObj::TakeObjNamePlural(rName); + else { + USHORT nResId=STR_ObjNamePluralRECT; + if (aGeo.nShearWink!=0) { + nResId+=4; // Parallelogramm oder Raute + } else { + if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat + } + if (GetEckenradius()!=0) nResId+=8; // abgerundet + rName=ImpGetResStr(nResId); + } +} + +void SdrRectObj::operator=(const SdrObject& rObj) +{ + SdrTextObj::operator=(rObj); +} + +basegfx::B2DPolyPolygon SdrRectObj::TakeXorPoly() const +{ + XPolyPolygon aXPP; + aXPP.Insert(ImpCalcXPoly(aRect,GetEckenradius())); + return aXPP.getB2DPolyPolygon(); +} + +void SdrRectObj::RecalcSnapRect() +{ + long nEckRad=GetEckenradius(); + if ((aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) && nEckRad!=0) { + maSnapRect=GetXPoly().GetBoundRect(); + } else { + SdrTextObj::RecalcSnapRect(); + } +} + +void SdrRectObj::NbcSetSnapRect(const Rectangle& rRect) +{ + SdrTextObj::NbcSetSnapRect(rRect); + SetXPolyDirty(); +} + +void SdrRectObj::NbcSetLogicRect(const Rectangle& rRect) +{ + SdrTextObj::NbcSetLogicRect(rRect); + SetXPolyDirty(); +} + +sal_uInt32 SdrRectObj::GetHdlCount() const +{ + return IsTextFrame() ? 10 : 9; +} + +SdrHdl* SdrRectObj::GetHdl(sal_uInt32 nHdlNum) const +{ + SdrHdl* pH = NULL; + Point aPnt; + SdrHdlKind eKind = HDL_MOVE; + + if(!IsTextFrame()) + { + nHdlNum++; + } + + switch(nHdlNum) + { + case 0: + { + pH = new ImpTextframeHdl(aRect); + pH->SetObj((SdrObject*)this); + pH->SetDrehWink(aGeo.nDrehWink); + break; + } + case 1: + { + long a = GetEckenradius(); + long b = Max(aRect.GetWidth(),aRect.GetHeight())/2; // Wird aufgerundet, da GetWidth() eins draufaddiert + if (a>b) a=b; + if (a<0) a=0; + aPnt=aRect.TopLeft(); + aPnt.X()+=a; + eKind = HDL_CIRC; + break; + } + case 2: aPnt=aRect.TopLeft(); eKind = HDL_UPLFT; break; // Oben links + case 3: aPnt=aRect.TopCenter(); eKind = HDL_UPPER; break; // Oben + case 4: aPnt=aRect.TopRight(); eKind = HDL_UPRGT; break; // Oben rechts + case 5: aPnt=aRect.LeftCenter(); eKind = HDL_LEFT ; break; // Links + case 6: aPnt=aRect.RightCenter(); eKind = HDL_RIGHT; break; // Rechts + case 7: aPnt=aRect.BottomLeft(); eKind = HDL_LWLFT; break; // Unten links + case 8: aPnt=aRect.BottomCenter(); eKind = HDL_LOWER; break; // Unten + case 9: aPnt=aRect.BottomRight(); eKind = HDL_LWRGT; break; // Unten rechts + } + + if(!pH) + { + if(aGeo.nShearWink) + { + ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan); + } + + if(aGeo.nDrehWink) + { + RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + } + + pH = new SdrHdl(aPnt,eKind); + pH->SetObj((SdrObject*)this); + pH->SetDrehWink(aGeo.nDrehWink); + } + + return pH; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrRectObj::hasSpecialDrag() const +{ + return true; +} + +bool SdrRectObj::beginSpecialDrag(SdrDragStat& rDrag) const +{ + const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); + + if(bRad) + { + rDrag.SetEndDragChangesAttributes(true); + + return true; + } + + return SdrTextObj::beginSpecialDrag(rDrag); +} + +bool SdrRectObj::applySpecialDrag(SdrDragStat& rDrag) +{ + const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); + + if (bRad) + { + Rectangle aBoundRect0; + Point aPt(rDrag.GetNow()); + + if(aGeo.nDrehWink) + RotatePoint(aPt,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); + + sal_Int32 nRad(aPt.X() - aRect.Left()); + + if (nRad < 0) + nRad = 0; + + if(nRad != GetEckenradius()) + { + NbcSetEckenradius(nRad); + } + + return true; + } + else + { + return SdrTextObj::applySpecialDrag(rDrag); + } +} + +String SdrRectObj::getSpecialDragComment(const SdrDragStat& rDrag) const +{ + const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj()); + + if(bCreateComment) + { + return String(); + } + else + { + const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); + + if(bRad) + { + Point aPt(rDrag.GetNow()); + + // -sin fuer Umkehrung + if(aGeo.nDrehWink) + RotatePoint(aPt, aRect.TopLeft(), -aGeo.nSin, aGeo.nCos); + + sal_Int32 nRad(aPt.X() - aRect.Left()); + + if(nRad < 0) + nRad = 0; + + XubString aStr; + + ImpTakeDescriptionStr(STR_DragRectEckRad, aStr); + aStr.AppendAscii(" ("); + aStr += GetMetrStr(nRad); + aStr += sal_Unicode(')'); + + return aStr; + } + else + { + return SdrTextObj::getSpecialDragComment(rDrag); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +basegfx::B2DPolyPolygon SdrRectObj::TakeCreatePoly(const SdrDragStat& rDrag) const +{ + Rectangle aRect1; + rDrag.TakeCreateRect(aRect1); + aRect1.Justify(); + + basegfx::B2DPolyPolygon aRetval; + aRetval.append(ImpCalcXPoly(aRect1,GetEckenradius()).getB2DPolygon()); + return aRetval; +} + +Pointer SdrRectObj::GetCreatePointer() const +{ + if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT); + return Pointer(POINTER_DRAW_RECT); +} + +void SdrRectObj::NbcMove(const Size& rSiz) +{ + SdrTextObj::NbcMove(rSiz); + SetXPolyDirty(); +} + +void SdrRectObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + SdrTextObj::NbcResize(rRef,xFact,yFact); + SetXPolyDirty(); +} + +void SdrRectObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + SdrTextObj::NbcRotate(rRef,nWink,sn,cs); + SetXPolyDirty(); +} + +void SdrRectObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + SdrTextObj::NbcShear(rRef,nWink,tn,bVShear); + SetXPolyDirty(); +} + +void SdrRectObj::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + SdrTextObj::NbcMirror(rRef1,rRef2); + SetXPolyDirty(); +} + +FASTBOOL SdrRectObj::DoMacro(const SdrObjMacroHitRec& rRec) +{ + return SdrTextObj::DoMacro(rRec); +} + +XubString SdrRectObj::GetMacroPopupComment(const SdrObjMacroHitRec& rRec) const +{ + return SdrTextObj::GetMacroPopupComment(rRec); +} + +SdrGluePoint SdrRectObj::GetVertexGluePoint(USHORT nPosNum) const +{ + INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue(); + + // #i25616# + if(!LineIsOutsideGeometry()) + { + nWdt++; + nWdt /= 2; + } + + Point aPt; + switch (nPosNum) { + case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break; + case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break; + case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break; + case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break; + } + if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + aPt-=GetSnapRect().Center(); + SdrGluePoint aGP(aPt); + aGP.SetPercent(FALSE); + return aGP; +} + +SdrGluePoint SdrRectObj::GetCornerGluePoint(USHORT nPosNum) const +{ + INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue(); + + // #i25616# + if(!LineIsOutsideGeometry()) + { + nWdt++; + nWdt /= 2; + } + + Point aPt; + switch (nPosNum) { + case 0: aPt=aRect.TopLeft(); aPt.X()-=nWdt; aPt.Y()-=nWdt; break; + case 1: aPt=aRect.TopRight(); aPt.X()+=nWdt; aPt.Y()-=nWdt; break; + case 2: aPt=aRect.BottomRight(); aPt.X()+=nWdt; aPt.Y()+=nWdt; break; + case 3: aPt=aRect.BottomLeft(); aPt.X()-=nWdt; aPt.Y()+=nWdt; break; + } + if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + aPt-=GetSnapRect().Center(); + SdrGluePoint aGP(aPt); + aGP.SetPercent(FALSE); + return aGP; +} + +SdrObject* SdrRectObj::DoConvertToPolyObj(BOOL bBezier) const +{ + XPolygon aXP(ImpCalcXPoly(aRect,GetEckenradius())); + { // #40608# Nur Uebergangsweise bis zum neuen TakeContour() + aXP.Remove(0,1); + aXP[aXP.GetPointCount()-1]=aXP[0]; + } + + basegfx::B2DPolyPolygon aPolyPolygon(aXP.getB2DPolygon()); + aPolyPolygon.removeDoublePoints(); + SdrObject* pRet = 0L; + + if(!IsTextFrame() || HasFill() || HasLine()) + { + pRet = ImpConvertMakeObj(aPolyPolygon, sal_True, bBezier); + } + + pRet = ImpConvertAddText(pRet, bBezier); + + return pRet; +} + +void SdrRectObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + SdrTextObj::Notify(rBC,rHint); + SetXPolyDirty(); // wg. Eckenradius +} + +void SdrRectObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrTextObj::RestGeoData(rGeo); + SetXPolyDirty(); +} + +// eof diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx new file mode 100644 index 000000000000..6a79359e1a00 --- /dev/null +++ b/svx/source/svdraw/svdotext.cxx @@ -0,0 +1,2132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdotext.hxx> +#include "svditext.hxx" +#include <svx/svdpagv.hxx> // fuer Abfrage im Paint, ob das +#include <svx/svdview.hxx> // Objekt gerade editiert wird +#include <svx/svdpage.hxx> // und fuer AnimationHandler (Laufschrift) +#include <svx/svdetc.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdmodel.hxx> // OutlinerDefaults +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname +#include <editeng/writingmodeitem.hxx> +#include <svx/sdtfchim.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editstat.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <editeng/outliner.hxx> +#include <editeng/fhgtitem.hxx> +#include <svl/itempool.hxx> +#include <editeng/adjitem.hxx> +#include <editeng/flditem.hxx> +#include <svx/xftouit.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <svx/xflgrit.hxx> +#include <svx/svdpool.hxx> +#include <svx/xflclit.hxx> +#include <svl/style.hxx> +#include <editeng/editeng.hxx> +#include <svl/itemiter.hxx> +#include <svx/sdr/properties/textproperties.hxx> +#include <vcl/metaact.hxx> +#include <svx/sdr/contact/viewcontactoftextobj.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <vcl/virdev.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// +// #104018# replace macros above with type-safe methods +inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } +inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* SdrTextObj::CreateObjectSpecificProperties() +{ + return new sdr::properties::TextProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// DrawContact section + +sdr::contact::ViewContact* SdrTextObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfTextObj(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrTextObj,SdrAttrObj); + +SdrTextObj::SdrTextObj() +: SdrAttrObj(), + mpText(NULL), + pEdtOutl(NULL), + pFormTextBoundRect(NULL), + eTextKind(OBJ_TEXT) +{ + bTextSizeDirty=FALSE; + bTextFrame=FALSE; + bNoShear=FALSE; + bNoRotate=FALSE; + bNoMirror=FALSE; + bDisableAutoWidthOnDragging=FALSE; + + // #101684# + mbInEditMode = FALSE; + + // #111096# + mbTextHidden = sal_False; + + // #111096# + mbTextAnimationAllowed = sal_True; + + // #108784# + maTextEditOffset = Point(0, 0); + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_True; +} + +SdrTextObj::SdrTextObj(const Rectangle& rNewRect) +: SdrAttrObj(), + aRect(rNewRect), + mpText(NULL), + pEdtOutl(NULL), + pFormTextBoundRect(NULL) +{ + bTextSizeDirty=FALSE; + bTextFrame=FALSE; + bNoShear=FALSE; + bNoRotate=FALSE; + bNoMirror=FALSE; + bDisableAutoWidthOnDragging=FALSE; + ImpJustifyRect(aRect); + + // #101684# + mbInEditMode = FALSE; + + // #111096# + mbTextHidden = sal_False; + + // #111096# + mbTextAnimationAllowed = sal_True; + + // #108784# + maTextEditOffset = Point(0, 0); + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_True; +} + +SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind) +: SdrAttrObj(), + mpText(NULL), + pEdtOutl(NULL), + pFormTextBoundRect(NULL), + eTextKind(eNewTextKind) +{ + bTextSizeDirty=FALSE; + bTextFrame=TRUE; + bNoShear=TRUE; + bNoRotate=FALSE; + bNoMirror=TRUE; + bDisableAutoWidthOnDragging=FALSE; + + // #101684# + mbInEditMode = FALSE; + + // #111096# + mbTextHidden = sal_False; + + // #111096# + mbTextAnimationAllowed = sal_True; + + // #108784# + maTextEditOffset = Point(0, 0); + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_True; +} + +SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect) +: SdrAttrObj(), + aRect(rNewRect), + mpText(NULL), + pEdtOutl(NULL), + pFormTextBoundRect(NULL), + eTextKind(eNewTextKind) +{ + bTextSizeDirty=FALSE; + bTextFrame=TRUE; + bNoShear=TRUE; + bNoRotate=FALSE; + bNoMirror=TRUE; + bDisableAutoWidthOnDragging=FALSE; + ImpJustifyRect(aRect); + + // #101684# + mbInEditMode = FALSE; + + // #111096# + mbTextHidden = sal_False; + + // #111096# + mbTextAnimationAllowed = sal_True; + + // #108784# + maTextEditOffset = Point(0, 0); + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_True; +} + +SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect, SvStream& rInput, const String& rBaseURL, USHORT eFormat) +: SdrAttrObj(), + aRect(rNewRect), + mpText(NULL), + pEdtOutl(NULL), + pFormTextBoundRect(NULL), + eTextKind(eNewTextKind) +{ + bTextSizeDirty=FALSE; + bTextFrame=TRUE; + bNoShear=TRUE; + bNoRotate=FALSE; + bNoMirror=TRUE; + bDisableAutoWidthOnDragging=FALSE; + ImpJustifyRect(aRect); + + NbcSetText(rInput, rBaseURL, eFormat); + + // #101684# + mbInEditMode = FALSE; + + // #111096# + mbTextHidden = sal_False; + + // #111096# + mbTextAnimationAllowed = sal_True; + + // #108784# + maTextEditOffset = Point(0, 0); + + // #i25616# + mbSupportTextIndentingOnLineWidthChange = sal_True; +} + +SdrTextObj::~SdrTextObj() +{ + if( pModel ) + { + SdrOutliner& rOutl = pModel->GetHitTestOutliner(); + if( rOutl.GetTextObj() == this ) + rOutl.SetTextObj( NULL ); + } + + if(mpText!=NULL) + delete mpText; + + if (pFormTextBoundRect!=NULL) + delete pFormTextBoundRect; + + ImpLinkAbmeldung(); +} + +void SdrTextObj::FitFrameToTextSize() +{ + DBG_ASSERT(pModel!=NULL,"SdrTextObj::FitFrameToTextSize(): pModel=NULL!"); + ImpJustifyRect(aRect); + + SdrText* pText = getActiveText(); + if( pText!=NULL && pText->GetOutlinerParaObject() && pModel!=NULL) + { + SdrOutliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetPaperSize(Size(aRect.Right()-aRect.Left(),aRect.Bottom()-aRect.Top())); + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetText(*pText->GetOutlinerParaObject()); + Rectangle aTextRect; + Size aNewSize(rOutliner.CalcTextSize()); + rOutliner.Clear(); + aNewSize.Width()++; // wegen evtl. Rundungsfehler + aNewSize.Width()+=GetTextLeftDistance()+GetTextRightDistance(); + aNewSize.Height()+=GetTextUpperDistance()+GetTextLowerDistance(); + Rectangle aNewRect(aRect); + aNewRect.SetSize(aNewSize); + ImpJustifyRect(aNewRect); + if (aNewRect!=aRect) { + SetLogicRect(aNewRect); + } + } +} + +void SdrTextObj::NbcSetText(const XubString& rStr) +{ + SdrOutliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetStyleSheet( 0, GetStyleSheet()); + //OutputDevice* pRef1=rOutliner.GetRefDevice(); + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetText(rStr,rOutliner.GetParagraph( 0 )); + OutlinerParaObject* pNewText=rOutliner.CreateParaObject(); + Size aSiz(rOutliner.CalcTextSize()); + //OutputDevice* pRef2=rOutliner.GetRefDevice(); + rOutliner.Clear(); + NbcSetOutlinerParaObject(pNewText); + aTextSize=aSiz; + bTextSizeDirty=FALSE; +} + +void SdrTextObj::SetText(const XubString& rStr) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetText(rStr); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + //if (GetBoundRect()!=aBoundRect0) { + // SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + //} +} + +void SdrTextObj::NbcSetText(SvStream& rInput, const String& rBaseURL, USHORT eFormat) +{ + SdrOutliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetStyleSheet( 0, GetStyleSheet()); + rOutliner.Read(rInput,rBaseURL,eFormat); + OutlinerParaObject* pNewText=rOutliner.CreateParaObject(); + rOutliner.SetUpdateMode(TRUE); + Size aSiz(rOutliner.CalcTextSize()); + rOutliner.Clear(); + NbcSetOutlinerParaObject(pNewText); + aTextSize=aSiz; + bTextSizeDirty=FALSE; +} + +void SdrTextObj::SetText(SvStream& rInput, const String& rBaseURL, USHORT eFormat) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcSetText(rInput,rBaseURL,eFormat); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +const Size& SdrTextObj::GetTextSize() const +{ + if (bTextSizeDirty) + { + Size aSiz; + SdrText* pText = getActiveText(); + if( pText && pText->GetOutlinerParaObject ()) + { + SdrOutliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetText(*pText->GetOutlinerParaObject()); + rOutliner.SetUpdateMode(TRUE); + aSiz=rOutliner.CalcTextSize(); + rOutliner.Clear(); + } + // 2x casting auf nonconst + ((SdrTextObj*)this)->aTextSize=aSiz; + ((SdrTextObj*)this)->bTextSizeDirty=FALSE; + } + return aTextSize; +} + +FASTBOOL SdrTextObj::IsAutoGrowHeight() const +{ + if(!bTextFrame) + return FALSE; // AutoGrow nur bei TextFrames + + const SfxItemSet& rSet = GetObjectItemSet(); + BOOL bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue(); + + if(bRet) + { + SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); + + if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) + { + SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); + + if(eDirection == SDRTEXTANI_UP || eDirection == SDRTEXTANI_DOWN) + { + bRet = FALSE; + } + } + } + return bRet; +} + +FASTBOOL SdrTextObj::IsAutoGrowWidth() const +{ + if(!bTextFrame) + return FALSE; // AutoGrow nur bei TextFrames + + const SfxItemSet& rSet = GetObjectItemSet(); + BOOL bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue(); + + // #101684# + BOOL bInEditMOde = IsInEditMode(); + + if(!bInEditMOde && bRet) + { + SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); + + if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) + { + SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); + + if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT) + { + bRet = FALSE; + } + } + } + return bRet; +} + +SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust() const +{ + return GetTextHorizontalAdjust(GetObjectItemSet()); +} + +SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet& rSet) const +{ + if(IsContourTextFrame()) + return SDRTEXTHORZADJUST_BLOCK; + + SdrTextHorzAdjust eRet = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue(); + + // #101684# + BOOL bInEditMode = IsInEditMode(); + + if(!bInEditMode && eRet == SDRTEXTHORZADJUST_BLOCK) + { + SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); + + if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) + { + SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); + + if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT) + { + eRet = SDRTEXTHORZADJUST_LEFT; + } + } + } + + return eRet; +} // defaults: BLOCK fuer Textrahmen, CENTER fuer beschriftete Grafikobjekte + +SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust() const +{ + return GetTextVerticalAdjust(GetObjectItemSet()); +} + +SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust(const SfxItemSet& rSet) const +{ + if(IsContourTextFrame()) + return SDRTEXTVERTADJUST_TOP; + + // #103516# Take care for vertical text animation here + SdrTextVertAdjust eRet = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue(); + BOOL bInEditMode = IsInEditMode(); + + // #103516# Take care for vertical text animation here + if(!bInEditMode && eRet == SDRTEXTVERTADJUST_BLOCK) + { + SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); + + if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) + { + SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); + + if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT) + { + eRet = SDRTEXTVERTADJUST_TOP; + } + } + } + + return eRet; +} // defaults: TOP fuer Textrahmen, CENTER fuer beschriftete Grafikobjekte + +void SdrTextObj::ImpJustifyRect(Rectangle& rRect) const +{ + if (!rRect.IsEmpty()) { + rRect.Justify(); + if (rRect.Left()==rRect.Right()) rRect.Right()++; + if (rRect.Top()==rRect.Bottom()) rRect.Bottom()++; + } +} + +void SdrTextObj::ImpCheckShear() +{ + if (bNoShear && aGeo.nShearWink!=0) { + aGeo.nShearWink=0; + aGeo.nTan=0; + } +} + +void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + FASTBOOL bNoTextFrame=!IsTextFrame(); + rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0; + rInfo.bResizePropAllowed=TRUE; + rInfo.bRotateFreeAllowed=TRUE; + rInfo.bRotate90Allowed =TRUE; + rInfo.bMirrorFreeAllowed=bNoTextFrame; + rInfo.bMirror45Allowed =bNoTextFrame; + rInfo.bMirror90Allowed =bNoTextFrame; + + // allow transparence + rInfo.bTransparenceAllowed = TRUE; + + // gradient depends on fillstyle + XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue(); + rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT); + rInfo.bShearAllowed =bNoTextFrame; + rInfo.bEdgeRadiusAllowed=TRUE; + FASTBOOL bCanConv=ImpCanConvTextToCurve(); + rInfo.bCanConvToPath =bCanConv; + rInfo.bCanConvToPoly =bCanConv; + rInfo.bCanConvToPathLineToArea=bCanConv; + rInfo.bCanConvToPolyLineToArea=bCanConv; + rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); +} + +UINT16 SdrTextObj::GetObjIdentifier() const +{ + return USHORT(eTextKind); +} + +bool SdrTextObj::HasTextImpl( SdrOutliner* pOutliner ) +{ + bool bRet=false; + if(pOutliner) + { + Paragraph* p1stPara=pOutliner->GetParagraph( 0 ); + ULONG nParaAnz=pOutliner->GetParagraphCount(); + if(p1stPara==NULL) + nParaAnz=0; + + if(nParaAnz==1) + { + // if it is only one paragraph, check if that paragraph is empty + XubString aStr(pOutliner->GetText(p1stPara)); + + if(!aStr.Len()) + nParaAnz = 0; + } + + bRet= nParaAnz!=0; + } + return bRet; +} + +FASTBOOL SdrTextObj::HasEditText() const +{ + return HasTextImpl( pEdtOutl ); +} + +void SdrTextObj::SetPage(SdrPage* pNewPage) +{ + FASTBOOL bRemove=pNewPage==NULL && pPage!=NULL; + FASTBOOL bInsert=pNewPage!=NULL && pPage==NULL; + FASTBOOL bLinked=IsLinkedText(); + + if (bLinked && bRemove) { + ImpLinkAbmeldung(); + } + + SdrAttrObj::SetPage(pNewPage); + + if (bLinked && bInsert) { + ImpLinkAnmeldung(); + } +} + +void SdrTextObj::SetModel(SdrModel* pNewModel) +{ + SdrModel* pOldModel=pModel; + bool bLinked=IsLinkedText(); + bool bChg=pNewModel!=pModel; + + if (bLinked && bChg) + { + ImpLinkAbmeldung(); + } + + SdrAttrObj::SetModel(pNewModel); + + if( bChg ) + { + if( pNewModel != 0 && pOldModel != 0 ) + SetTextSizeDirty(); + + sal_Int32 nCount = getTextCount(); + for( sal_Int32 nText = 0; nText < nCount; nText++ ) + { + SdrText* pText = getText( nText ); + if( pText ) + pText->SetModel( pNewModel ); + } + } + + if (bLinked && bChg) + { + ImpLinkAnmeldung(); + } +} + +FASTBOOL SdrTextObj::NbcSetEckenradius(long nRad) +{ + SetObjectItem(SdrEckenradiusItem(nRad)); + return TRUE; +} + +FASTBOOL SdrTextObj::NbcSetAutoGrowHeight(bool bAuto) +{ + if(bTextFrame) + { + SetObjectItem(SdrTextAutoGrowHeightItem(bAuto)); + return TRUE; + } + return FALSE; +} + +FASTBOOL SdrTextObj::NbcSetMinTextFrameHeight(long nHgt) +{ + if( bTextFrame && ( !pModel || !pModel->isLocked() ) ) // SJ: #i44922# + { + SetObjectItem(SdrTextMinFrameHeightItem(nHgt)); + + // #84974# use bDisableAutoWidthOnDragging as + // bDisableAutoHeightOnDragging if vertical. + if(IsVerticalWriting() && bDisableAutoWidthOnDragging) + { + bDisableAutoWidthOnDragging = FALSE; + SetObjectItem(SdrTextAutoGrowHeightItem(FALSE)); + } + + return TRUE; + } + return FALSE; +} + +FASTBOOL SdrTextObj::NbcSetMaxTextFrameHeight(long nHgt) +{ + if(bTextFrame) + { + SetObjectItem(SdrTextMaxFrameHeightItem(nHgt)); + return TRUE; + } + return FALSE; +} + +FASTBOOL SdrTextObj::NbcSetAutoGrowWidth(bool bAuto) +{ + if(bTextFrame) + { + SetObjectItem(SdrTextAutoGrowWidthItem(bAuto)); + return TRUE; + } + return FALSE; +} + +FASTBOOL SdrTextObj::NbcSetMinTextFrameWidth(long nWdt) +{ + if( bTextFrame && ( !pModel || !pModel->isLocked() ) ) // SJ: #i44922# + { + SetObjectItem(SdrTextMinFrameWidthItem(nWdt)); + + // #84974# use bDisableAutoWidthOnDragging only + // when not vertical. + if(!IsVerticalWriting() && bDisableAutoWidthOnDragging) + { + bDisableAutoWidthOnDragging = FALSE; + SetObjectItem(SdrTextAutoGrowWidthItem(FALSE)); + } + + return TRUE; + } + return FALSE; +} + +FASTBOOL SdrTextObj::NbcSetMaxTextFrameWidth(long nWdt) +{ + if(bTextFrame) + { + SetObjectItem(SdrTextMaxFrameWidthItem(nWdt)); + return TRUE; + } + return FALSE; +} + +FASTBOOL SdrTextObj::NbcSetFitToSize(SdrFitToSizeType eFit) +{ + if(bTextFrame) + { + SetObjectItem(SdrTextFitToSizeTypeItem(eFit)); + return TRUE; + } + return FALSE; +} + +void SdrTextObj::ImpSetContourPolygon( SdrOutliner& rOutliner, Rectangle& rAnchorRect, BOOL bLineWidth ) const +{ + basegfx::B2DPolyPolygon aXorPolyPolygon(TakeXorPoly()); + basegfx::B2DPolyPolygon* pContourPolyPolygon = 0L; + basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix( + -rAnchorRect.Left(), -rAnchorRect.Top())); + + if(aGeo.nDrehWink) + { + // Unrotate! + aMatrix.rotate(-aGeo.nDrehWink * nPi180); + } + + aXorPolyPolygon.transform(aMatrix); + + if( bLineWidth ) + { + // Strichstaerke beruecksichtigen + // Beim Hittest muss das unterbleiben (Performance!) + pContourPolyPolygon = new basegfx::B2DPolyPolygon(); + + // #86258# test if shadow needs to be avoided for TakeContour() + const SfxItemSet& rSet = GetObjectItemSet(); + sal_Bool bShadowOn = ((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue(); + + // #i33696# + // Remember TextObject currently set at the DrawOutliner, it WILL be + // replaced during calculating the outline since it uses an own paint + // and that one uses the DrawOutliner, too. + const SdrTextObj* pLastTextObject = rOutliner.GetTextObj(); + + if(bShadowOn) + { + // #86258# force shadow off + SdrObject* pCopy = Clone(); + pCopy->SetMergedItem(SdrShadowItem(FALSE)); + *pContourPolyPolygon = pCopy->TakeContour(); + SdrObject::Free( pCopy ); + } + else + { + *pContourPolyPolygon = TakeContour(); + } + + // #i33696# + // restore remembered text object + if(pLastTextObject != rOutliner.GetTextObj()) + { + rOutliner.SetTextObj(pLastTextObject); + } + + pContourPolyPolygon->transform(aMatrix); + } + + rOutliner.SetPolygon(aXorPolyPolygon, pContourPolyPolygon); +} + +void SdrTextObj::TakeUnrotatedSnapRect(Rectangle& rRect) const +{ + rRect=aRect; +} + +void SdrTextObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const +{ + long nLeftDist=GetTextLeftDistance(); + long nRightDist=GetTextRightDistance(); + long nUpperDist=GetTextUpperDistance(); + long nLowerDist=GetTextLowerDistance(); + Rectangle aAnkRect(aRect); // Rect innerhalb dem geankert wird + FASTBOOL bFrame=IsTextFrame(); + if (!bFrame) { + TakeUnrotatedSnapRect(aAnkRect); + } + Point aRotateRef(aAnkRect.TopLeft()); + aAnkRect.Left()+=nLeftDist; + aAnkRect.Top()+=nUpperDist; + aAnkRect.Right()-=nRightDist; + aAnkRect.Bottom()-=nLowerDist; + + // #108816# + // Since sizes may be bigger than the object bounds it is necessary to + // justify the rect now. + ImpJustifyRect(aAnkRect); + + if (bFrame) { + // !!! hier noch etwas verfeinern !!! + if (aAnkRect.GetWidth()<2) aAnkRect.Right()=aAnkRect.Left()+1; // Mindestgroesse 2 + if (aAnkRect.GetHeight()<2) aAnkRect.Bottom()=aAnkRect.Top()+1; // Mindestgroesse 2 + } + if (aGeo.nDrehWink!=0) { + Point aTmpPt(aAnkRect.TopLeft()); + RotatePoint(aTmpPt,aRotateRef,aGeo.nSin,aGeo.nCos); + aTmpPt-=aAnkRect.TopLeft(); + aAnkRect.Move(aTmpPt.X(),aTmpPt.Y()); + } + rAnchorRect=aAnkRect; +} + +void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, + Rectangle* pAnchorRect, BOOL bLineWidth ) const +{ + Rectangle aAnkRect; // Rect innerhalb dem geankert wird + TakeTextAnchorRect(aAnkRect); + SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); + SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); + SdrTextAniKind eAniKind=GetTextAniKind(); + SdrTextAniDirection eAniDirection=GetTextAniDirection(); + + SdrFitToSizeType eFit=GetFitToSize(); + FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); + FASTBOOL bContourFrame=IsContourTextFrame(); + + FASTBOOL bFrame=IsTextFrame(); + ULONG nStat0=rOutliner.GetControlWord(); + Size aNullSize; + if (!bContourFrame) + { + rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE); + rOutliner.SetMinAutoPaperSize(aNullSize); + rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000)); + } + + if (!bFitToSize && !bContourFrame) + { + long nAnkWdt=aAnkRect.GetWidth(); + long nAnkHgt=aAnkRect.GetHeight(); + if (bFrame) + { + long nWdt=nAnkWdt; + long nHgt=nAnkHgt; + + // #101684# + BOOL bInEditMode = IsInEditMode(); + + if (!bInEditMode && (eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE)) + { + // Grenzenlose Papiergroesse fuer Laufschrift + if (eAniDirection==SDRTEXTANI_LEFT || eAniDirection==SDRTEXTANI_RIGHT) nWdt=1000000; + if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nHgt=1000000; + } + rOutliner.SetMaxAutoPaperSize(Size(nWdt,nHgt)); + } + + // #103516# New try with _BLOCK for hor and ver after completely + // supporting full width for vertical text. + if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting()) + { + rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0)); + } + + if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting()) + { + rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt)); + } + } + + rOutliner.SetPaperSize(aNullSize); + if (bContourFrame) + ImpSetContourPolygon( rOutliner, aAnkRect, bLineWidth ); + + // put text into the outliner, if available from the edit outliner + SdrText* pText = getActiveText(); + OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0; + OutlinerParaObject* pPara = (pEdtOutl && !bNoEditText) ? pEdtOutl->CreateParaObject() : pOutlinerParaObject; + + if (pPara) + { + BOOL bHitTest = FALSE; + if( pModel ) + bHitTest = &pModel->GetHitTestOutliner() == &rOutliner; + + const SdrTextObj* pTestObj = rOutliner.GetTextObj(); + if( !pTestObj || !bHitTest || pTestObj != this || + pTestObj->GetOutlinerParaObject() != pOutlinerParaObject ) + { + if( bHitTest ) // #i33696# take back fix #i27510# + { + rOutliner.SetTextObj( this ); + rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); + } + + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetText(*pPara); + } + } + else + { + rOutliner.SetTextObj( NULL ); + } + + if (pEdtOutl && !bNoEditText && pPara) + delete pPara; + + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetControlWord(nStat0); + + if( pText ) + pText->CheckPortionInfo(rOutliner); + + Point aTextPos(aAnkRect.TopLeft()); + Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() hat etwas Toleranz drauf, oder? + + // #106653# + // For draw objects containing text correct hor/ver alignment if text is bigger + // than the object itself. Without that correction, the text would always be + // formatted to the left edge (or top edge when vertical) of the draw object. + if(!IsTextFrame()) + { + if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting()) + { + // #110129# + // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTHORZADJUST_BLOCK == eHAdj) + { + eHAdj = SDRTEXTHORZADJUST_CENTER; + } + } + + if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting()) + { + // #110129# + // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTVERTADJUST_BLOCK == eVAdj) + { + eVAdj = SDRTEXTVERTADJUST_CENTER; + } + } + } + + if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT) + { + long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width(); + if (eHAdj==SDRTEXTHORZADJUST_CENTER) + aTextPos.X()+=nFreeWdt/2; + if (eHAdj==SDRTEXTHORZADJUST_RIGHT) + aTextPos.X()+=nFreeWdt; + } + if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM) + { + long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height(); + if (eVAdj==SDRTEXTVERTADJUST_CENTER) + aTextPos.Y()+=nFreeHgt/2; + if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) + aTextPos.Y()+=nFreeHgt; + } + if (aGeo.nDrehWink!=0) + RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos); + + if (pAnchorRect) + *pAnchorRect=aAnkRect; + + // rTextRect ist bei ContourFrame in einigen Faellen nicht korrekt + rTextRect=Rectangle(aTextPos,aTextSiz); + if (bContourFrame) + rTextRect=aAnkRect; +} + +OutlinerParaObject* SdrTextObj::GetEditOutlinerParaObject() const +{ + OutlinerParaObject* pPara=NULL; + if( HasTextImpl( pEdtOutl ) ) + { + sal_uInt16 nParaAnz = static_cast< sal_uInt16 >( pEdtOutl->GetParagraphCount() ); + pPara = pEdtOutl->CreateParaObject(0, nParaAnz); + } + return pPara; +} + +void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Rectangle& rTextRect, const Rectangle& rAnchorRect, Fraction& rFitXKorreg) const +{ + OutputDevice* pOut = rOutliner.GetRefDevice(); + BOOL bNoStretching(FALSE); + + if(pOut && pOut->GetOutDevType() == OUTDEV_PRINTER) + { + // #35762#: Checken ob CharStretching ueberhaupt moeglich + GDIMetaFile* pMtf = pOut->GetConnectMetaFile(); + UniString aTestString(sal_Unicode('J')); + + if(pMtf && (!pMtf->IsRecord() || pMtf->IsPause())) + pMtf = NULL; + + if(pMtf) + pMtf->Pause(TRUE); + + Font aFontMerk(pOut->GetFont()); + Font aTmpFont( OutputDevice::GetDefaultFont( DEFAULTFONT_SERIF, LANGUAGE_SYSTEM, DEFAULTFONT_FLAGS_ONLYONE ) ); + + aTmpFont.SetSize(Size(0,100)); + pOut->SetFont(aTmpFont); + Size aSize1(pOut->GetTextWidth(aTestString), pOut->GetTextHeight()); + aTmpFont.SetSize(Size(800,100)); + pOut->SetFont(aTmpFont); + Size aSize2(pOut->GetTextWidth(aTestString), pOut->GetTextHeight()); + pOut->SetFont(aFontMerk); + + if(pMtf) + pMtf->Pause(FALSE); + + bNoStretching = (aSize1 == aSize2); + +#ifdef WNT + // #35762# Windows vergroessert bei Size(100,500) den Font proportional + // Und das finden wir nicht so schoen. + if(aSize2.Height() >= aSize1.Height() * 2) + { + bNoStretching = TRUE; + } +#endif + } + unsigned nLoopCount=0; + FASTBOOL bNoMoreLoop=FALSE; + long nXDiff0=0x7FFFFFFF; + long nWantWdt=rAnchorRect.Right()-rAnchorRect.Left(); + long nIsWdt=rTextRect.Right()-rTextRect.Left(); + if (nIsWdt==0) nIsWdt=1; + + long nWantHgt=rAnchorRect.Bottom()-rAnchorRect.Top(); + long nIsHgt=rTextRect.Bottom()-rTextRect.Top(); + if (nIsHgt==0) nIsHgt=1; + + long nXTolPl=nWantWdt/100; // Toleranz +1% + long nXTolMi=nWantWdt/25; // Toleranz -4% + long nXKorr =nWantWdt/20; // Korrekturmasstab 5% + + long nX=(nWantWdt*100) /nIsWdt; // X-Stretching berechnen + long nY=(nWantHgt*100) /nIsHgt; // Y-Stretching berechnen + FASTBOOL bChkX=TRUE; + FASTBOOL bChkY=TRUE; + if (bNoStretching) { // #35762# evtl. nur proportional moeglich + if (nX>nY) { nX=nY; bChkX=FALSE; } + else { nY=nX; bChkY=FALSE; } + } + + while (nLoopCount<5 && !bNoMoreLoop) { + if (nX<0) nX=-nX; + if (nX<1) { nX=1; bNoMoreLoop=TRUE; } + if (nX>65535) { nX=65535; bNoMoreLoop=TRUE; } + + if (nY<0) nY=-nY; + if (nY<1) { nY=1; bNoMoreLoop=TRUE; } + if (nY>65535) { nY=65535; bNoMoreLoop=TRUE; } + + // exception, there is no text yet (horizontal case) + if(nIsWdt <= 1) + { + nX = nY; + bNoMoreLoop = TRUE; + } + + // #87877# exception, there is no text yet (vertical case) + if(nIsHgt <= 1) + { + nY = nX; + bNoMoreLoop = TRUE; + } + + rOutliner.SetGlobalCharStretching((USHORT)nX,(USHORT)nY); + nLoopCount++; + Size aSiz(rOutliner.CalcTextSize()); + long nXDiff=aSiz.Width()-nWantWdt; + rFitXKorreg=Fraction(nWantWdt,aSiz.Width()); + if (((nXDiff>=nXTolMi || !bChkX) && nXDiff<=nXTolPl) || nXDiff==nXDiff0/*&& Abs(nYDiff)<=nYTol*/) { + bNoMoreLoop=TRUE; + } else { + // Stretchingfaktoren korregieren + long nMul=nWantWdt; + long nDiv=aSiz.Width(); + if (Abs(nXDiff)<=2*nXKorr) { + if (nMul>nDiv) nDiv+=(nMul-nDiv)/2; // und zwar nur um die haelfte des berechneten + else nMul+=(nDiv-nMul)/2; // weil die EE ja eh wieder falsch rechnet + } + nX=nX*nMul/nDiv; + if (bNoStretching) nY=nX; + } + nXDiff0=nXDiff; + } +} + +void SdrTextObj::StartTextAnimation(OutputDevice* /*pOutDev*/, const Point& /*rOffset*/, long /*nExtraData*/) +{ + // #111096# + // use new text animation + SetTextAnimationAllowed(sal_True); +} + +void SdrTextObj::StopTextAnimation(OutputDevice* /*pOutDev*/, long /*nExtraData*/) +{ + // #111096# + // use new text animation + SetTextAnimationAllowed(sal_False); +} + +void SdrTextObj::TakeObjNameSingul(XubString& rName) const +{ + XubString aStr; + + switch(eTextKind) + { + case OBJ_OUTLINETEXT: + { + aStr = ImpGetResStr(STR_ObjNameSingulOUTLINETEXT); + break; + } + + case OBJ_TITLETEXT : + { + aStr = ImpGetResStr(STR_ObjNameSingulTITLETEXT); + break; + } + + default: + { + if(IsLinkedText()) + aStr = ImpGetResStr(STR_ObjNameSingulTEXTLNK); + else + aStr = ImpGetResStr(STR_ObjNameSingulTEXT); + break; + } + } + + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if(pOutlinerParaObject && eTextKind != OBJ_OUTLINETEXT) + { + // Macht bei OUTLINETEXT wohl derzeit noch etwas Probleme + XubString aStr2(pOutlinerParaObject->GetTextObject().GetText(0)); + aStr2.EraseLeadingChars(); + + // #69446# avoid non expanded text portions in object name + // (second condition is new) + if(aStr2.Len() && aStr2.Search(sal_Unicode(255)) == STRING_NOTFOUND) + { + // #76681# space between ResStr and content text + aStr += sal_Unicode(' '); + + aStr += sal_Unicode('\''); + + if(aStr2.Len() > 10) + { + aStr2.Erase(8); + aStr2.AppendAscii("...", 3); + } + + aStr += aStr2; + aStr += sal_Unicode('\''); + } + } + + rName = aStr; + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } + +} + +void SdrTextObj::TakeObjNamePlural(XubString& rName) const +{ + switch (eTextKind) { + case OBJ_OUTLINETEXT: rName=ImpGetResStr(STR_ObjNamePluralOUTLINETEXT); break; + case OBJ_TITLETEXT : rName=ImpGetResStr(STR_ObjNamePluralTITLETEXT); break; + default: { + if (IsLinkedText()) { + rName=ImpGetResStr(STR_ObjNamePluralTEXTLNK); + } else { + rName=ImpGetResStr(STR_ObjNamePluralTEXT); + } + } break; + } // switch +} + +void SdrTextObj::operator=(const SdrObject& rObj) +{ + // call parent + SdrObject::operator=(rObj); + + const SdrTextObj* pTextObj = dynamic_cast< const SdrTextObj* >( &rObj ); + if (pTextObj!=NULL) + { + aRect =pTextObj->aRect; + aGeo =pTextObj->aGeo; + eTextKind =pTextObj->eTextKind; + bTextFrame=pTextObj->bTextFrame; + aTextSize=pTextObj->aTextSize; + bTextSizeDirty=pTextObj->bTextSizeDirty; + + // #101776# Not all of the necessary parameters were copied yet. + bNoShear = pTextObj->bNoShear; + bNoRotate = pTextObj->bNoRotate; + bNoMirror = pTextObj->bNoMirror; + bDisableAutoWidthOnDragging = pTextObj->bDisableAutoWidthOnDragging; + + OutlinerParaObject* pNewOutlinerParaObject = 0; + + SdrText* pText = getActiveText(); + + if( pText && pTextObj->HasText() ) + { + const Outliner* pEO=pTextObj->pEdtOutl; + if (pEO!=NULL) + { + pNewOutlinerParaObject = pEO->CreateParaObject(); + } + else + { + pNewOutlinerParaObject = new OutlinerParaObject(*pTextObj->getActiveText()->GetOutlinerParaObject()); + } + } + + mpText->SetOutlinerParaObject( pNewOutlinerParaObject ); + ImpSetTextStyleSheetListeners(); + } +} + +basegfx::B2DPolyPolygon SdrTextObj::TakeXorPoly() const +{ + Polygon aPol(aRect); + if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + + basegfx::B2DPolyPolygon aRetval; + aRetval.append(aPol.getB2DPolygon()); + return aRetval; +} + +basegfx::B2DPolyPolygon SdrTextObj::TakeContour() const +{ + basegfx::B2DPolyPolygon aRetval(SdrAttrObj::TakeContour()); + + // und nun noch ggf. das BoundRect des Textes dazu + if ( pModel && GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() ) + { + // #80328# using Clone()-Paint() strategy inside TakeContour() leaves a destroyed + // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner + // in every case + SdrOutliner& rOutliner=ImpGetDrawOutliner(); + + Rectangle aAnchor2; + Rectangle aR; + TakeTextRect(rOutliner,aR,FALSE,&aAnchor2); + rOutliner.Clear(); + SdrFitToSizeType eFit=GetFitToSize(); + FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); + if (bFitToSize) aR=aAnchor2; + Polygon aPol(aR); + if (aGeo.nDrehWink!=0) RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos); + + aRetval.append(aPol.getB2DPolygon()); + } + + return aRetval; +} + +void SdrTextObj::RecalcSnapRect() +{ + if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) { + Polygon aPol(aRect); + if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + maSnapRect=aPol.GetBoundRect(); + } else { + maSnapRect=aRect; + } +} + +sal_uInt32 SdrTextObj::GetSnapPointCount() const +{ + return 4L; +} + +Point SdrTextObj::GetSnapPoint(sal_uInt32 i) const +{ + Point aP; + switch (i) { + case 0: aP=aRect.TopLeft(); break; + case 1: aP=aRect.TopRight(); break; + case 2: aP=aRect.BottomLeft(); break; + case 3: aP=aRect.BottomRight(); break; + default: aP=aRect.Center(); break; + } + if (aGeo.nShearWink!=0) ShearPoint(aP,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoint(aP,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + return aP; +} + +void SdrTextObj::ImpCheckMasterCachable() +{ + bNotMasterCachable=FALSE; + + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + + if(!bNotVisibleAsMaster && pOutlinerParaObject && pOutlinerParaObject->IsEditDoc() ) + { + const EditTextObject& rText= pOutlinerParaObject->GetTextObject(); + bNotMasterCachable=rText.HasField(SvxPageField::StaticType()); + if( !bNotMasterCachable ) + { + bNotMasterCachable=rText.HasField(SvxHeaderField::StaticType()); + if( !bNotMasterCachable ) + { + bNotMasterCachable=rText.HasField(SvxFooterField::StaticType()); + if( !bNotMasterCachable ) + { + bNotMasterCachable=rText.HasField(SvxDateTimeField::StaticType()); + } + } + } + } +} + +// #101029#: Extracted from ImpGetDrawOutliner() +void SdrTextObj::ImpInitDrawOutliner( SdrOutliner& rOutl ) const +{ + rOutl.SetUpdateMode(FALSE); + USHORT nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT; + if ( !IsOutlText() ) + nOutlinerMode = OUTLINERMODE_TEXTOBJECT; + rOutl.Init( nOutlinerMode ); + + rOutl.SetGlobalCharStretching(100,100); + ULONG nStat=rOutl.GetControlWord(); + nStat&=~(EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE); + rOutl.SetControlWord(nStat); + Size aNullSize; + Size aMaxSize(100000,100000); + rOutl.SetMinAutoPaperSize(aNullSize); + rOutl.SetMaxAutoPaperSize(aMaxSize); + rOutl.SetPaperSize(aMaxSize); + rOutl.ClearPolygon(); +} + +SdrOutliner& SdrTextObj::ImpGetDrawOutliner() const +{ + SdrOutliner& rOutl=pModel->GetDrawOutliner(this); + + // #101029#: Code extracted to ImpInitDrawOutliner() + ImpInitDrawOutliner( rOutl ); + + return rOutl; +} + +boost::shared_ptr< SdrOutliner > SdrTextObj::CreateDrawOutliner() +{ + boost::shared_ptr< SdrOutliner > xDrawOutliner( pModel->CreateDrawOutliner(this) ); + ImpInitDrawOutliner( *(xDrawOutliner.get()) ); + return xDrawOutliner; +} + +// #101029#: Extracted from Paint() +void SdrTextObj::ImpSetupDrawOutlinerForPaint( FASTBOOL bContourFrame, + SdrOutliner& rOutliner, + Rectangle& rTextRect, + Rectangle& rAnchorRect, + Rectangle& rPaintRect, + Fraction& rFitXKorreg ) const +{ + if (!bContourFrame) + { + // FitToSize erstmal nicht mit ContourFrame + SdrFitToSizeType eFit=GetFitToSize(); + if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES) + { + ULONG nStat=rOutliner.GetControlWord(); + nStat|=EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE; + rOutliner.SetControlWord(nStat); + } + } + rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); + TakeTextRect(rOutliner, rTextRect, FALSE, &rAnchorRect); + rPaintRect = rTextRect; + + if (!bContourFrame) + { + // FitToSize erstmal nicht mit ContourFrame + SdrFitToSizeType eFit=GetFitToSize(); + if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES) + { + ImpSetCharStretching(rOutliner,rTextRect,rAnchorRect,rFitXKorreg); + rPaintRect=rAnchorRect; + } + } +} + +void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const +{ + ImpInitDrawOutliner( rOutl ); + UpdateOutlinerFormatting( rOutl, rPaintRect ); +} + +void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const +{ + Rectangle aTextRect; + Rectangle aAnchorRect; + Fraction aFitXKorreg(1,1); + + FASTBOOL bContourFrame=IsContourTextFrame(); + + ImpSetupDrawOutlinerForPaint( bContourFrame, rOutl, aTextRect, aAnchorRect, rPaintRect, aFitXKorreg ); + + if( GetModel() ) + { + MapMode aMapMode(GetModel()->GetScaleUnit(), Point(0,0), + GetModel()->GetScaleFraction(), + GetModel()->GetScaleFraction()); + rOutl.SetRefMapMode(aMapMode); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +OutlinerParaObject* SdrTextObj::GetOutlinerParaObject() const +{ + SdrText* pText = getActiveText(); + if( pText ) + return pText->GetOutlinerParaObject(); + else + return 0; +} + +bool SdrTextObj::HasOutlinerParaObject() const +{ + SdrText* pText = getActiveText(); + if( pText && pText->GetOutlinerParaObject() ) + return true; + return false; +} + +void SdrTextObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject) +{ + NbcSetOutlinerParaObjectForText( pTextObject, getActiveText() ); +} + +void SdrTextObj::NbcSetOutlinerParaObjectForText( OutlinerParaObject* pTextObject, SdrText* pText ) +{ + if( pText ) + pText->SetOutlinerParaObject( pTextObject ); + + if( pText->GetOutlinerParaObject() ) + { + SvxWritingModeItem aWritingMode(pText->GetOutlinerParaObject()->IsVertical() + ? com::sun::star::text::WritingMode_TB_RL + : com::sun::star::text::WritingMode_LR_TB, + SDRATTR_TEXTDIRECTION); + GetProperties().SetObjectItemDirect(aWritingMode); + } + + SetTextSizeDirty(); + if (IsTextFrame() && (IsAutoGrowHeight() || IsAutoGrowWidth())) + { // Textrahmen anpassen! + NbcAdjustTextFrameWidthAndHeight(); + } + if (!IsTextFrame()) + { + // Das SnapRect behaelt seine Groesse bei + SetRectsDirty(sal_True); + } + + // always invalidate BoundRect on change + SetBoundRectDirty(); + ActionChanged(); + + ImpSetTextStyleSheetListeners(); + ImpCheckMasterCachable(); +} + +void SdrTextObj::NbcReformatText() +{ + SdrText* pText = getActiveText(); + if( pText && pText->GetOutlinerParaObject() ) + { + pText->ReformatText(); + if (bTextFrame) + { + NbcAdjustTextFrameWidthAndHeight(); + } + else + { + // Das SnapRect behaelt seine Groesse bei + SetBoundRectDirty(); + SetRectsDirty(sal_True); + } + SetTextSizeDirty(); + ActionChanged(); + // FME, AW: i22396 + // Necessary here since we have no compare operator at the outliner + // para object which may detect changes regarding the combination + // of outliner para data and configuration (e.g., change of + // formatting of text numerals) + GetViewContact().flushViewObjectContacts(false); + } +} + +void SdrTextObj::ReformatText() +{ + if(GetOutlinerParaObject()) + { + Rectangle aBoundRect0; + if (pUserCall!=NULL) + aBoundRect0=GetLastBoundRect(); + + // #110094#-14 SendRepaintBroadcast(); + NbcReformatText(); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +SdrObjGeoData* SdrTextObj::NewGeoData() const +{ + return new SdrTextObjGeoData; +} + +void SdrTextObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrAttrObj::SaveGeoData(rGeo); + SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo; + rTGeo.aRect =aRect; + rTGeo.aGeo =aGeo; +} + +void SdrTextObj::RestGeoData(const SdrObjGeoData& rGeo) +{ // RectsDirty wird von SdrObject gerufen + SdrAttrObj::RestGeoData(rGeo); + SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo; + aRect =rTGeo.aRect; + aGeo =rTGeo.aGeo; + SetTextSizeDirty(); +} + +SdrFitToSizeType SdrTextObj::GetFitToSize() const +{ + SdrFitToSizeType eType = SDRTEXTFIT_NONE; + + if(!IsAutoGrowWidth()) + eType = ((SdrTextFitToSizeTypeItem&)(GetObjectItem(SDRATTR_TEXT_FITTOSIZE))).GetValue(); + + return eType; +} + +void SdrTextObj::ForceOutlinerParaObject() +{ + SdrText* pText = getActiveText(); + if( pText && (pText->GetOutlinerParaObject() == 0) ) + { + USHORT nOutlMode = OUTLINERMODE_TEXTOBJECT; + if( IsTextFrame() && eTextKind == OBJ_OUTLINETEXT ) + nOutlMode = OUTLINERMODE_OUTLINEOBJECT; + + pText->ForceOutlinerParaObject( nOutlMode ); + } +} + +sal_Bool SdrTextObj::IsVerticalWriting() const +{ + // #89459# + if(pEdtOutl) + { + return pEdtOutl->IsVertical(); + } + + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if(pOutlinerParaObject) + { + return pOutlinerParaObject->IsVertical(); + } + + return sal_False; +} + +void SdrTextObj::SetVerticalWriting(sal_Bool bVertical) +{ + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if( !pOutlinerParaObject && bVertical ) + { + // we only need to force a outliner para object if the default of + // horizontal text is changed + ForceOutlinerParaObject(); + pOutlinerParaObject = GetOutlinerParaObject(); + } + + if( pOutlinerParaObject && (pOutlinerParaObject->IsVertical() != (bool)bVertical) ) + { + // get item settings + const SfxItemSet& rSet = GetObjectItemSet(); + sal_Bool bAutoGrowWidth = ((SdrTextAutoGrowWidthItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue(); + sal_Bool bAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue(); + + // #103516# Also exchange hor/ver adjust items + SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue(); + SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue(); + + // rescue object size + Rectangle aObjectRect = GetSnapRect(); + + // prepare ItemSet to set exchanged width and height items + SfxItemSet aNewSet(*rSet.GetPool(), + SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT, + // #103516# Expanded item ranges to also support hor and ver adjust. + SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST, + SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST, + 0, 0); + + aNewSet.Put(rSet); + aNewSet.Put(SdrTextAutoGrowWidthItem(bAutoGrowHeight)); + aNewSet.Put(SdrTextAutoGrowHeightItem(bAutoGrowWidth)); + + // #103516# Exchange horz and vert adjusts + switch(eVert) + { + case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break; + case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break; + case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break; + case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break; + } + switch(eHorz) + { + case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break; + case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break; + case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break; + case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break; + } + + SetObjectItemSet(aNewSet); + + pOutlinerParaObject = GetOutlinerParaObject(); + if( pOutlinerParaObject ) + { + // set ParaObject orientation accordingly + pOutlinerParaObject->SetVertical(bVertical); + } + + // restore object size + SetSnapRect(aObjectRect); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// transformation interface for StarOfficeAPI. This implements support for +// homogen 3x3 matrices containing the transformation of the SdrObject. At the +// moment it contains a shearX, rotation and translation, but for setting all linear +// transforms like Scale, ShearX, ShearY, Rotate and Translate are supported. +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon +// with the base geometry and returns TRUE. Otherwise it returns FALSE. +sal_Bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const +{ + // get turn and shear + double fRotate = (aGeo.nDrehWink / 100.0) * F_PI180; + double fShearX = (aGeo.nShearWink / 100.0) * F_PI180; + + // get aRect, this is the unrotated snaprect + Rectangle aRectangle(aRect); + + // fill other values + basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight()); + basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top()); + + // position maybe relative to anchorpos, convert + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // force MapUnit to 100th mm + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // postion + aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); + aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); + + // size + aScale.setX(ImplTwipsToMM(aScale.getX())); + aScale.setY(ImplTwipsToMM(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); + } + } + } + + // build matrix + rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX), + basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate, + aTranslate); + + return sal_False; +} + +// sets the base geometry of the object using infos contained in the homogen 3x3 matrix. +// If it's an SdrPathObj it will use the provided geometry information. The Polygon has +// to use (0,0) as upper left and will be scaled to the given size in the matrix. +void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) +{ + // break up matrix + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate(0.0); + double fShearX(0.0); + rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings + // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale.setX(fabs(aScale.getX())); + aScale.setY(fabs(aScale.getY())); + fRotate = fmod(fRotate + F_PI, F_2PI); + } + + // reset object shear and rotations + aGeo.nDrehWink = 0; + aGeo.RecalcSinCos(); + aGeo.nShearWink = 0; + aGeo.RecalcTan(); + + // force metric to pool metric + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // position + aTranslate.setX(ImplMMToTwips(aTranslate.getX())); + aTranslate.setY(ImplMMToTwips(aTranslate.getY())); + + // size + aScale.setX(ImplMMToTwips(aScale.getX())); + aScale.setY(ImplMMToTwips(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); + } + } + } + + // if anchor is used, make position relative to it + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // build and set BaseRect (use scale) + Point aPoint = Point(); + Size aSize(FRound(aScale.getX()), FRound(aScale.getY())); + Rectangle aBaseRect(aPoint, aSize); + SetSnapRect(aBaseRect); + + // shear? + if(!basegfx::fTools::equalZero(fShearX)) + { + GeoStat aGeoStat; + aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0); + aGeoStat.RecalcTan(); + Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, FALSE); + } + + // rotation? + if(!basegfx::fTools::equalZero(fRotate)) + { + GeoStat aGeoStat; + + // #i78696# + // fRotate is matematically correct, but aGeoStat.nDrehWink is + // mirrored -> mirror value here + aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000)); + aGeoStat.RecalcSinCos(); + Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos); + } + + // translate? + if(!aTranslate.equalZero()) + { + Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY()))); + } +} + +bool SdrTextObj::IsRealyEdited() const +{ + return pEdtOutl && pEdtOutl->IsModified(); +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// moved inlines here form hxx + +long SdrTextObj::GetEckenradius() const +{ + return ((SdrEckenradiusItem&)(GetObjectItemSet().Get(SDRATTR_ECKENRADIUS))).GetValue(); +} + +long SdrTextObj::GetMinTextFrameHeight() const +{ + return ((SdrTextMinFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT))).GetValue(); +} + +long SdrTextObj::GetMaxTextFrameHeight() const +{ + return ((SdrTextMaxFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT))).GetValue(); +} + +long SdrTextObj::GetMinTextFrameWidth() const +{ + return ((SdrTextMinFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH))).GetValue(); +} + +long SdrTextObj::GetMaxTextFrameWidth() const +{ + return ((SdrTextMaxFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH))).GetValue(); +} + +FASTBOOL SdrTextObj::IsFontwork() const +{ + return (bTextFrame) ? FALSE // Default ist FALSE + : ((XFormTextStyleItem&)(GetObjectItemSet().Get(XATTR_FORMTXTSTYLE))).GetValue()!=XFT_NONE; +} + +FASTBOOL SdrTextObj::IsHideContour() const +{ + return (bTextFrame) ? FALSE // Default ist: Nein, kein HideContour; HideContour nicht bei TextFrames + : ((XFormTextHideFormItem&)(GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM))).GetValue(); +} + +FASTBOOL SdrTextObj::IsContourTextFrame() const +{ + return (bTextFrame) ? FALSE // ContourFrame nicht bei normalen TextFrames + : ((SdrTextContourFrameItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME))).GetValue(); +} + +long SdrTextObj::GetTextLeftDistance() const +{ + return ((SdrTextLeftDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST))).GetValue(); +} + +long SdrTextObj::GetTextRightDistance() const +{ + return ((SdrTextRightDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST))).GetValue(); +} + +long SdrTextObj::GetTextUpperDistance() const +{ + return ((SdrTextUpperDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST))).GetValue(); +} + +long SdrTextObj::GetTextLowerDistance() const +{ + return ((SdrTextLowerDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST))).GetValue(); +} + +SdrTextAniKind SdrTextObj::GetTextAniKind() const +{ + return ((SdrTextAniKindItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND))).GetValue(); +} + +SdrTextAniDirection SdrTextObj::GetTextAniDirection() const +{ + return ((SdrTextAniDirectionItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); +} + +// #111096# +// Access to thext hidden flag +sal_Bool SdrTextObj::GetTextHidden() const +{ + return mbTextHidden; +} + +void SdrTextObj::NbcSetTextHidden(sal_Bool bNew) +{ + if(bNew != mbTextHidden) + { + mbTextHidden = bNew; + } +} + +// #111096# +// Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a +// painting rectangle. Rotation is excluded from the returned values. +GDIMetaFile* SdrTextObj::GetTextScrollMetaFileAndRectangle( + Rectangle& rScrollRectangle, Rectangle& rPaintRectangle) +{ + GDIMetaFile* pRetval = 0L; + SdrOutliner& rOutliner = ImpGetDrawOutliner(); + Rectangle aTextRect; + Rectangle aAnchorRect; + Rectangle aPaintRect; + Fraction aFitXKorreg(1,1); + bool bContourFrame(IsContourTextFrame()); + + // get outliner set up. To avoid getting a somehow rotated MetaFile, + // temporarily disable object rotation. + sal_Int32 nAngle(aGeo.nDrehWink); + aGeo.nDrehWink = 0L; + ImpSetupDrawOutlinerForPaint( bContourFrame, rOutliner, aTextRect, aAnchorRect, aPaintRect, aFitXKorreg ); + aGeo.nDrehWink = nAngle; + + Rectangle aScrollFrameRect(aPaintRect); + const SfxItemSet& rSet = GetObjectItemSet(); + SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); + + if(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection) + { + aScrollFrameRect.Left() = aAnchorRect.Left(); + aScrollFrameRect.Right() = aAnchorRect.Right(); + } + + if(SDRTEXTANI_UP == eDirection || SDRTEXTANI_DOWN == eDirection) + { + aScrollFrameRect.Top() = aAnchorRect.Top(); + aScrollFrameRect.Bottom() = aAnchorRect.Bottom(); + } + + // create the MetaFile + pRetval = new GDIMetaFile; + VirtualDevice aBlackHole; + aBlackHole.EnableOutput(sal_False); + pRetval->Record(&aBlackHole); + Point aPaintPos = aPaintRect.TopLeft(); + + rOutliner.Draw(&aBlackHole, aPaintPos); + + pRetval->Stop(); + pRetval->WindStart(); + + // return PaintRectanglePixel and pRetval; + rScrollRectangle = aScrollFrameRect; + rPaintRectangle = aPaintRect; + + return pRetval; +} + +// #111096# +// Access to TextAnimationAllowed flag +bool SdrTextObj::IsTextAnimationAllowed() const +{ + return mbTextAnimationAllowed; +} + +void SdrTextObj::SetTextAnimationAllowed(sal_Bool bNew) +{ + if(mbTextAnimationAllowed != bNew) + { + mbTextAnimationAllowed = bNew; + ActionChanged(); + } +} + +/** called from the SdrObjEditView during text edit when the status of the edit outliner changes */ +void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus ) +{ + const sal_uInt32 nStat = pEditStatus->GetStatusWord(); + const bool bGrowX=(nStat & EE_STAT_TEXTWIDTHCHANGED) !=0; + const bool bGrowY=(nStat & EE_STAT_TEXTHEIGHTCHANGED) !=0; + if(bTextFrame && (bGrowX || bGrowY)) + { + const bool bAutoGrowHgt= bTextFrame && IsAutoGrowHeight(); + const bool bAutoGrowWdt= bTextFrame && IsAutoGrowWidth(); + + if ((bGrowX && bAutoGrowWdt) || (bGrowY && bAutoGrowHgt)) + { + AdjustTextFrameWidthAndHeight(); + } + } +} + +/** returns the currently active text. */ +SdrText* SdrTextObj::getActiveText() const +{ + if( !mpText ) + return getText( 0 ); + else + return mpText; +} + +/** returns the nth available text. */ +SdrText* SdrTextObj::getText( sal_Int32 nIndex ) const +{ + if( nIndex == 0 ) + { + if( mpText == 0 ) + const_cast< SdrTextObj* >(this)->mpText = new SdrText( *(const_cast< SdrTextObj* >(this)) ); + return mpText; + } + else + { + return 0; + } +} + +/** returns the number of texts available for this object. */ +sal_Int32 SdrTextObj::getTextCount() const +{ + return 1; +} + +/** changes the current active text */ +void SdrTextObj::setActiveText( sal_Int32 /*nIndex*/ ) +{ +} + +/** returns the index of the text that contains the given point or -1 */ +sal_Int32 SdrTextObj::CheckTextHit(const Point& /*rPnt*/) const +{ + return 0; +} + +void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem& rItem) +{ + static_cast< sdr::properties::TextProperties& >(GetProperties()).SetObjectItemNoBroadcast(rItem); +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Konzept des TextObjekts: +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute/Varianten: +// - BOOL Textrahmen / beschriftetes Zeichenobjekt +// - BOOL FontWork (wenn nicht Textrahmen und nicht ContourTextFrame) +// - BOOL ContourTextFrame (wenn nicht Textrahmen und nicht Fontwork) +// - long Drehwinkel (wenn nicht FontWork) +// - long Textrahmenabstaende (wenn nicht FontWork) +// - BOOL FitToSize (wenn nicht FontWork) +// - BOOL AutoGrowingWidth/Height (wenn nicht FitToSize und nicht FontWork) +// - long Min/MaxFrameWidth/Height (wenn AutoGrowingWidth/Height) +// - enum Horizontale Textverankerung Links,Mitte,Rechts,Block,Stretch(ni) +// - enum Vertikale Textverankerung Oben,Mitte,Unten,Block,Stretch(ni) +// - enum Laufschrift (wenn nicht FontWork) +// +// Jedes abgeleitete Objekt ist entweder ein Textrahmen (bTextFrame=TRUE) +// oder ein beschriftetes Zeichenobjekt (bTextFrame=FALSE). +// +// Defaultverankerung von Textrahmen: +// SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP +// = statische Pooldefaults +// Defaultverankerung von beschrifteten Zeichenobjekten: +// SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER +// durch harte Attributierung von SdrAttrObj +// +// Jedes vom SdrTextObj abgeleitete Objekt muss ein "UnrotatedSnapRect" +// (->TakeUnrotatedSnapRect()) liefern (Drehreferenz ist TopLeft dieses +// Rechtecks (aGeo.nDrehWink)), welches die Grundlage der Textverankerung +// bildet. Von diesem werden dann ringsum die Textrahmenabstaende abgezogen; +// das Ergebnis ist der Ankerbereich (->TakeTextAnchorRect()). Innerhalb +// dieses Bereichs wird dann in Abhaengigkeit von der horizontalen und +// vertikalen Ausrichtung (SdrTextVertAdjust,SdrTextHorzAdjust) der Ankerpunkt +// sowie der Ausgabebereich bestimmt. Bei beschrifteten Grafikobjekten kann +// der Ausgabebereich durchaus groesser als der Ankerbereich werden, bei +// Textrahmen ist er stets kleiner oder gleich (ausser bei negativen Textrahmen- +// abstaenden). +// +// FitToSize hat Prioritaet vor Textverankerung und AutoGrowHeight/Width. Der +// Ausgabebereich ist bei FitToSize immer genau der Ankerbereich. Weiterhin +// gibt es bei FitToSize keinen automatischen Zeilenumbruch. +// +// ContourTextFrame: +// - long Drehwinkel +// - long Textrahmenabstaende spaeter vielleicht +// - BOOL FitToSize spaeter vielleicht +// - BOOL AutoGrowingWidth/Height viel spaeter vielleicht +// - long Min/MaxFrameWidth/Height viel spaeter vielleicht +// - enum Horizontale Textverankerung spaeter vielleicht, erstmal Links, Absatz zentr. +// - enum Vertikale Textverankerung spaeter vielleicht, erstmal oben +// - enum Laufschrift spaeter vielleicht (evtl. sogar mit korrektem Clipping) +// +// Bei Aenderungen zu beachten: +// - Paint +// - HitTest +// - ConvertToPoly +// - Edit +// - Drucken,Speichern, Paint in Nachbarview waerend Edit +// - ModelChanged (z.B. durch NachbarView oder Lineale) waerend Edit +// - FillColorChanged waerend Edit +// - uvm... +// +///////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx new file mode 100644 index 000000000000..3675c7becac4 --- /dev/null +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -0,0 +1,1258 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdotext.hxx> +#include <svx/svdoutl.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> +#include <basegfx/range/b2drange.hxx> +#include <editeng/editstat.hxx> +#include <vcl/salbtype.hxx> +#include <svx/sdtfchim.hxx> +#include <svl/itemset.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/animation/animationtiming.hxx> +#include <basegfx/color/bcolor.hxx> +#include <vcl/svapp.hxx> +#include <editeng/eeitemid.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/svxenum.hxx> +#include <editeng/flditem.hxx> +#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx> +#include <vcl/metaact.hxx> +#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx> +#include <drawinglayer/primitive2d/graphicprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <unoapi.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <editeng/outlobj.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +////////////////////////////////////////////////////////////////////////////// +// helpers + +namespace +{ + drawinglayer::primitive2d::Primitive2DSequence impConvertVectorToPrimitive2DSequence(const std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& rPrimitiveVector) + { + const sal_Int32 nCount(rPrimitiveVector.size()); + drawinglayer::primitive2d::Primitive2DSequence aRetval(nCount); + + for(sal_Int32 a(0L); a < nCount; a++) + { + aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(rPrimitiveVector[a]); + } + + return aRetval; + } + + class impTextBreakupHandler + { + private: + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > maTextPortionPrimitives; + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > maLinePrimitives; + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > maParagraphPrimitives; + + SdrOutliner& mrOutliner; + basegfx::B2DHomMatrix maNewTransformA; + basegfx::B2DHomMatrix maNewTransformB; + + // the visible area for contour text decomposition + basegfx::B2DVector maScale; + + // #SJ# ClipRange for BlockText decomposition; only text portions completely + // inside are to be accepted, so this is different from geometric clipping + // (which would allow e.g. upper parts of portions to remain). Only used for + // BlockText (see there) + basegfx::B2DRange maClipRange; + + DECL_LINK(decomposeContourTextPrimitive, DrawPortionInfo* ); + DECL_LINK(decomposeBlockTextPrimitive, DrawPortionInfo* ); + DECL_LINK(decomposeStretchTextPrimitive, DrawPortionInfo* ); + + DECL_LINK(decomposeContourBulletPrimitive, DrawBulletInfo* ); + DECL_LINK(decomposeBlockBulletPrimitive, DrawBulletInfo* ); + DECL_LINK(decomposeStretchBulletPrimitive, DrawBulletInfo* ); + + bool impIsUnderlineAbove(const Font& rFont) const; + void impCreateTextPortionPrimitive(const DrawPortionInfo& rInfo); + drawinglayer::primitive2d::BasePrimitive2D* impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo) const; + void impFlushTextPortionPrimitivesToLinePrimitives(); + void impFlushLinePrimitivesToParagraphPrimitives(); + void impHandleDrawPortionInfo(const DrawPortionInfo& rInfo); + void impHandleDrawBulletInfo(const DrawBulletInfo& rInfo); + + public: + impTextBreakupHandler(SdrOutliner& rOutliner) + : maTextPortionPrimitives(), + maLinePrimitives(), + maParagraphPrimitives(), + mrOutliner(rOutliner), + maNewTransformA(), + maNewTransformB(), + maScale(), + maClipRange() + { + } + + void decomposeContourTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB, const basegfx::B2DVector& rScale) + { + maScale = rScale; + maNewTransformA = rNewTransformA; + maNewTransformB = rNewTransformB; + mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeContourTextPrimitive)); + mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeContourBulletPrimitive)); + mrOutliner.StripPortions(); + mrOutliner.SetDrawPortionHdl(Link()); + mrOutliner.SetDrawBulletHdl(Link()); + } + + void decomposeBlockTextPrimitive( + const basegfx::B2DHomMatrix& rNewTransformA, + const basegfx::B2DHomMatrix& rNewTransformB, + const basegfx::B2DRange& rClipRange) + { + maNewTransformA = rNewTransformA; + maNewTransformB = rNewTransformB; + maClipRange = rClipRange; + mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeBlockTextPrimitive)); + mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeBlockBulletPrimitive)); + mrOutliner.StripPortions(); + mrOutliner.SetDrawPortionHdl(Link()); + mrOutliner.SetDrawBulletHdl(Link()); + } + + void decomposeStretchTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB) + { + maNewTransformA = rNewTransformA; + maNewTransformB = rNewTransformB; + mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeStretchTextPrimitive)); + mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeStretchBulletPrimitive)); + mrOutliner.StripPortions(); + mrOutliner.SetDrawPortionHdl(Link()); + mrOutliner.SetDrawBulletHdl(Link()); + } + + drawinglayer::primitive2d::Primitive2DSequence getPrimitive2DSequence(); + }; + + bool impTextBreakupHandler::impIsUnderlineAbove(const Font& rFont) const + { + if(!rFont.IsVertical()) + { + return false; + } + + if((LANGUAGE_JAPANESE == rFont.GetLanguage()) || (LANGUAGE_JAPANESE == rFont.GetCJKContextLanguage())) + { + // the underline is right for Japanese only + return true; + } + + return false; + } + + void impTextBreakupHandler::impCreateTextPortionPrimitive(const DrawPortionInfo& rInfo) + { + if(rInfo.mrText.Len() && rInfo.mnTextLen) + { + basegfx::B2DVector aFontScaling; + drawinglayer::attribute::FontAttribute aFontAttribute( + drawinglayer::primitive2d::getFontAttributeFromVclFont( + aFontScaling, + rInfo.mrFont, + rInfo.IsRTL(), + false)); + basegfx::B2DHomMatrix aNewTransform; + + // add font scale to new transform + aNewTransform.scale(aFontScaling.getX(), aFontScaling.getY()); + + // look for proportional font scaling, evtl scale accordingly + if(100 != rInfo.mrFont.GetPropr()) + { + const double fFactor(rInfo.mrFont.GetPropr() / 100.0); + aNewTransform.scale(fFactor, fFactor); + } + + // apply font rotate + if(rInfo.mrFont.GetOrientation()) + { + aNewTransform.rotate(-rInfo.mrFont.GetOrientation() * F_PI1800); + } + + // look for escapement, evtl translate accordingly + if(rInfo.mrFont.GetEscapement()) + { + sal_Int16 nEsc(rInfo.mrFont.GetEscapement()); + + if(DFLT_ESC_AUTO_SUPER == nEsc) + { + nEsc = 33; + } + else if(DFLT_ESC_AUTO_SUB == nEsc) + { + nEsc = -20; + } + + if(nEsc > 100) + { + nEsc = 100; + } + else if(nEsc < -100) + { + nEsc = -100; + } + + const double fEscapement(nEsc / -100.0); + aNewTransform.translate(0.0, fEscapement * aFontScaling.getY()); + } + + // apply transformA + aNewTransform *= maNewTransformA; + + // apply local offset + aNewTransform.translate(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y()); + + // also apply embedding object's transform + aNewTransform *= maNewTransformB; + + // prepare DXArray content. To make it independent from font size (and such from + // the text transformation), scale it to unit coordinates + ::std::vector< double > aDXArray; + static bool bDisableTextArray(false); + + if(!bDisableTextArray && rInfo.mpDXArray && rInfo.mnTextLen) + { + aDXArray.reserve(rInfo.mnTextLen); + + for(xub_StrLen a(0); a < rInfo.mnTextLen; a++) + { + aDXArray.push_back((double)rInfo.mpDXArray[a]); + } + } + + // create complex text primitive and append + const Color aFontColor(rInfo.mrFont.GetColor()); + const basegfx::BColor aBFontColor(aFontColor.getBColor()); + + // prepare wordLineMode (for underline and strikeout) + // NOT for bullet texts. It is set (this may be an error by itself), but needs to be suppressed to hinder e.g. '1)' + // to be splitted which would not look like the original + const bool bWordLineMode(rInfo.mrFont.IsWordLineMode() && !rInfo.mbEndOfBullet); + + // prepare new primitive + drawinglayer::primitive2d::BasePrimitive2D* pNewPrimitive = 0; + const bool bDecoratedIsNeeded( + UNDERLINE_NONE != rInfo.mrFont.GetOverline() + || UNDERLINE_NONE != rInfo.mrFont.GetUnderline() + || STRIKEOUT_NONE != rInfo.mrFont.GetStrikeout() + || EMPHASISMARK_NONE != (rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_STYLE) + || RELIEF_NONE != rInfo.mrFont.GetRelief() + || rInfo.mrFont.IsShadow() + || bWordLineMode); + + if(bDecoratedIsNeeded) + { + // TextDecoratedPortionPrimitive2D needed, prepare some more data + // get overline and underline color. If it's on automatic (0xffffffff) use FontColor instead + const Color aUnderlineColor(rInfo.maTextLineColor); + const basegfx::BColor aBUnderlineColor((0xffffffff == aUnderlineColor.GetColor()) ? aBFontColor : aUnderlineColor.getBColor()); + const Color aOverlineColor(rInfo.maOverlineColor); + const basegfx::BColor aBOverlineColor((0xffffffff == aOverlineColor.GetColor()) ? aBFontColor : aOverlineColor.getBColor()); + + // prepare overline and underline data + const drawinglayer::primitive2d::TextLine eFontOverline( + drawinglayer::primitive2d::mapFontUnderlineToTextLine(rInfo.mrFont.GetOverline())); + const drawinglayer::primitive2d::TextLine eFontUnderline( + drawinglayer::primitive2d::mapFontUnderlineToTextLine(rInfo.mrFont.GetUnderline())); + + // check UndelineAbove + const bool bUnderlineAbove( + drawinglayer::primitive2d::TEXT_LINE_NONE != eFontUnderline && impIsUnderlineAbove(rInfo.mrFont)); + + // prepare strikeout data + const drawinglayer::primitive2d::TextStrikeout eTextStrikeout( + drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rInfo.mrFont.GetStrikeout())); + + // prepare emphasis mark data + drawinglayer::primitive2d::TextEmphasisMark eTextEmphasisMark(drawinglayer::primitive2d::TEXT_EMPHASISMARK_NONE); + + switch(rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_STYLE) + { + case EMPHASISMARK_DOT : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_DOT; break; + case EMPHASISMARK_CIRCLE : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_CIRCLE; break; + case EMPHASISMARK_DISC : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_DISC; break; + case EMPHASISMARK_ACCENT : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_ACCENT; break; + } + + const bool bEmphasisMarkAbove(rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_POS_ABOVE); + const bool bEmphasisMarkBelow(rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_POS_BELOW); + + // prepare font relief data + drawinglayer::primitive2d::TextRelief eTextRelief(drawinglayer::primitive2d::TEXT_RELIEF_NONE); + + switch(rInfo.mrFont.GetRelief()) + { + case RELIEF_EMBOSSED : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_EMBOSSED; break; + case RELIEF_ENGRAVED : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_ENGRAVED; break; + default : break; // RELIEF_NONE, FontRelief_FORCE_EQUAL_SIZE + } + + // prepare shadow/outline data + const bool bShadow(rInfo.mrFont.IsShadow()); + + // TextDecoratedPortionPrimitive2D is needed, create one + pNewPrimitive = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D( + + // attributes for TextSimplePortionPrimitive2D + aNewTransform, + rInfo.mrText, + rInfo.mnTextStart, + rInfo.mnTextLen, + aDXArray, + aFontAttribute, + rInfo.mpLocale ? *rInfo.mpLocale : ::com::sun::star::lang::Locale(), + aBFontColor, + + // attributes for TextDecoratedPortionPrimitive2D + aBOverlineColor, + aBUnderlineColor, + eFontOverline, + eFontUnderline, + bUnderlineAbove, + eTextStrikeout, + bWordLineMode, + eTextEmphasisMark, + bEmphasisMarkAbove, + bEmphasisMarkBelow, + eTextRelief, + bShadow); + } + else + { + // TextSimplePortionPrimitive2D is enough + pNewPrimitive = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aNewTransform, + rInfo.mrText, + rInfo.mnTextStart, + rInfo.mnTextLen, + aDXArray, + aFontAttribute, + rInfo.mpLocale ? *rInfo.mpLocale : ::com::sun::star::lang::Locale(), + aBFontColor); + } + + if(rInfo.mbEndOfBullet) + { + // embed in TextHierarchyBulletPrimitive2D + const drawinglayer::primitive2d::Primitive2DReference aNewReference(pNewPrimitive); + const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(&aNewReference, 1); + pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(aNewSequence); + } + + if(rInfo.mpFieldData) + { + pNewPrimitive = impCheckFieldPrimitive(pNewPrimitive, rInfo); + } + + maTextPortionPrimitives.push_back(pNewPrimitive); + + // support for WrongSpellVector. Create WrongSpellPrimitives as needed + if(rInfo.mpWrongSpellVector && !aDXArray.empty()) + { + const sal_uInt32 nSize(rInfo.mpWrongSpellVector->size()); + const sal_uInt32 nDXCount(aDXArray.size()); + const basegfx::BColor aSpellColor(1.0, 0.0, 0.0); // red, hard coded + + for(sal_uInt32 a(0); a < nSize; a++) + { + const EEngineData::WrongSpellClass& rCandidate = (*rInfo.mpWrongSpellVector)[a]; + + if(rCandidate.nStart >= rInfo.mnTextStart && rCandidate.nEnd >= rInfo.mnTextStart && rCandidate.nEnd > rCandidate.nStart) + { + const sal_uInt32 nStart(rCandidate.nStart - rInfo.mnTextStart); + const sal_uInt32 nEnd(rCandidate.nEnd - rInfo.mnTextStart); + double fStart(0.0); + double fEnd(0.0); + + if(nStart > 0 && nStart - 1 < nDXCount) + { + fStart = aDXArray[nStart - 1]; + } + + if(nEnd > 0 && nEnd - 1 < nDXCount) + { + fEnd = aDXArray[nEnd - 1]; + } + + if(!basegfx::fTools::equal(fStart, fEnd)) + { + if(rInfo.IsRTL()) + { + // #i98523# + // When the portion is RTL, mirror the redlining using the + // full portion width + const double fTextWidth(aDXArray[aDXArray.size() - 1]); + + fStart = fTextWidth - fStart; + fEnd = fTextWidth - fEnd; + } + + // need to take FontScaling out of values; it's already part of + // aNewTransform and would be double applied + const double fFontScaleX(aFontScaling.getX()); + + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) + { + fStart /= fFontScaleX; + fEnd /= fFontScaleX; + } + + maTextPortionPrimitives.push_back(new drawinglayer::primitive2d::WrongSpellPrimitive2D( + aNewTransform, + fStart, + fEnd, + aSpellColor)); + } + } + } + } + } + } + + drawinglayer::primitive2d::BasePrimitive2D* impTextBreakupHandler::impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo) const + { + if(rInfo.mpFieldData) + { + // Support for FIELD_SEQ_BEGIN, FIELD_SEQ_END. If used, create a TextHierarchyFieldPrimitive2D + // which holds the field type and evtl. the URL + const SvxURLField* pURLField = dynamic_cast< const SvxURLField* >(rInfo.mpFieldData); + const SvxPageField* pPageField = dynamic_cast< const SvxPageField* >(rInfo.mpFieldData); + + // embed current primitive to a sequence + drawinglayer::primitive2d::Primitive2DSequence aSequence; + + if(pPrimitive) + { + aSequence.realloc(1); + aSequence[0] = drawinglayer::primitive2d::Primitive2DReference(pPrimitive); + } + + if(pURLField) + { + pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_URL, pURLField->GetURL()); + } + else if(pPageField) + { + pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_PAGE, String()); + } + else + { + pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_COMMON, String()); + } + } + + return pPrimitive; + } + + void impTextBreakupHandler::impFlushTextPortionPrimitivesToLinePrimitives() + { + // only create a line primitive when we had content; there is no need for + // empty line primitives (contrary to paragraphs, see below). + if(maTextPortionPrimitives.size()) + { + drawinglayer::primitive2d::Primitive2DSequence aLineSequence(impConvertVectorToPrimitive2DSequence(maTextPortionPrimitives)); + maTextPortionPrimitives.clear(); + maLinePrimitives.push_back(new drawinglayer::primitive2d::TextHierarchyLinePrimitive2D(aLineSequence)); + } + } + + void impTextBreakupHandler::impFlushLinePrimitivesToParagraphPrimitives() + { + // ALWAYS create a paragraph primitive, even when no content was added. This is done to + // have the correct paragraph count even with empty paragraphs. Those paragraphs will + // have an empty sub-PrimitiveSequence. + drawinglayer::primitive2d::Primitive2DSequence aParagraphSequence(impConvertVectorToPrimitive2DSequence(maLinePrimitives)); + maLinePrimitives.clear(); + maParagraphPrimitives.push_back(new drawinglayer::primitive2d::TextHierarchyParagraphPrimitive2D(aParagraphSequence)); + } + + void impTextBreakupHandler::impHandleDrawPortionInfo(const DrawPortionInfo& rInfo) + { + impCreateTextPortionPrimitive(rInfo); + + if(rInfo.mbEndOfLine || rInfo.mbEndOfParagraph) + { + impFlushTextPortionPrimitivesToLinePrimitives(); + } + + if(rInfo.mbEndOfParagraph) + { + impFlushLinePrimitivesToParagraphPrimitives(); + } + } + + void impTextBreakupHandler::impHandleDrawBulletInfo(const DrawBulletInfo& rInfo) + { + basegfx::B2DHomMatrix aNewTransform; + + // add size to new transform + aNewTransform.scale(rInfo.maBulletSize.getWidth(), rInfo.maBulletSize.getHeight()); + + // apply transformA + aNewTransform *= maNewTransformA; + + // apply local offset + aNewTransform.translate(rInfo.maBulletPosition.X(), rInfo.maBulletPosition.Y()); + + // also apply embedding object's transform + aNewTransform *= maNewTransformB; + + // prepare empty GraphicAttr + const GraphicAttr aGraphicAttr; + + // create GraphicPrimitive2D + const drawinglayer::primitive2d::Primitive2DReference aNewReference(new drawinglayer::primitive2d::GraphicPrimitive2D( + aNewTransform, + rInfo.maBulletGraphicObject, + aGraphicAttr)); + + // embed in TextHierarchyBulletPrimitive2D + const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(&aNewReference, 1); + drawinglayer::primitive2d::BasePrimitive2D* pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(aNewSequence); + + // add to output + maTextPortionPrimitives.push_back(pNewPrimitive); + } + + IMPL_LINK(impTextBreakupHandler, decomposeContourTextPrimitive, DrawPortionInfo*, pInfo) + { + // for contour text, ignore (clip away) all portions which are below + // the visible area given by maScale + if(pInfo && (double)pInfo->mrStartPos.Y() < maScale.getY()) + { + impHandleDrawPortionInfo(*pInfo); + } + + return 0; + } + + IMPL_LINK(impTextBreakupHandler, decomposeBlockTextPrimitive, DrawPortionInfo*, pInfo) + { + if(pInfo) + { + // #SJ# Is clipping wanted? This is text clipping; only accept a portion + // if it's completely in the range + if(!maClipRange.isEmpty()) + { + // Test start position first; this allows to not get the text range at + // all if text is far outside + const basegfx::B2DPoint aStartPosition(pInfo->mrStartPos.X(), pInfo->mrStartPos.Y()); + + if(!maClipRange.isInside(aStartPosition)) + { + return 0; + } + + // Start position is inside. Get TextBoundRect and TopLeft next + drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; + aTextLayouterDevice.setFont(pInfo->mrFont); + + const basegfx::B2DRange aTextBoundRect( + aTextLayouterDevice.getTextBoundRect( + pInfo->mrText, pInfo->mnTextStart, pInfo->mnTextLen)); + const basegfx::B2DPoint aTopLeft(aTextBoundRect.getMinimum() + aStartPosition); + + if(!maClipRange.isInside(aTopLeft)) + { + return 0; + } + + // TopLeft is inside. Get BottomRight and check + const basegfx::B2DPoint aBottomRight(aTextBoundRect.getMaximum() + aStartPosition); + + if(!maClipRange.isInside(aBottomRight)) + { + return 0; + } + + // all inside, clip was successful + } + impHandleDrawPortionInfo(*pInfo); + } + + return 0; + } + + IMPL_LINK(impTextBreakupHandler, decomposeStretchTextPrimitive, DrawPortionInfo*, pInfo) + { + if(pInfo) + { + impHandleDrawPortionInfo(*pInfo); + } + + return 0; + } + + IMPL_LINK(impTextBreakupHandler, decomposeContourBulletPrimitive, DrawBulletInfo*, pInfo) + { + if(pInfo) + { + impHandleDrawBulletInfo(*pInfo); + } + + return 0; + } + + IMPL_LINK(impTextBreakupHandler, decomposeBlockBulletPrimitive, DrawBulletInfo*, pInfo) + { + if(pInfo) + { + impHandleDrawBulletInfo(*pInfo); + } + + return 0; + } + + IMPL_LINK(impTextBreakupHandler, decomposeStretchBulletPrimitive, DrawBulletInfo*, pInfo) + { + if(pInfo) + { + impHandleDrawBulletInfo(*pInfo); + } + + return 0; + } + + drawinglayer::primitive2d::Primitive2DSequence impTextBreakupHandler::getPrimitive2DSequence() + { + if(maTextPortionPrimitives.size()) + { + // collect non-closed lines + impFlushTextPortionPrimitivesToLinePrimitives(); + } + + if(maLinePrimitives.size()) + { + // collect non-closed paragraphs + impFlushLinePrimitivesToParagraphPrimitives(); + } + + return impConvertVectorToPrimitive2DSequence(maParagraphPrimitives); + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// +// primitive decompositions + +void SdrTextObj::impDecomposeContourTextPrimitive( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::SdrContourTextPrimitive2D& rSdrContourTextPrimitive, + const drawinglayer::geometry::ViewInformation2D& aViewInformation) const +{ + // decompose matrix to have position and size of text + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rSdrContourTextPrimitive.getObjectTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // prepare contour polygon, force to non-mirrored for layouting + basegfx::B2DPolyPolygon aPolyPolygon(rSdrContourTextPrimitive.getUnitPolyPolygon()); + aPolyPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(fabs(aScale.getX()), fabs(aScale.getY()))); + + // prepare outliner + SdrOutliner& rOutliner = ImpGetDrawOutliner(); + const Size aNullSize; + rOutliner.SetPaperSize(aNullSize); + rOutliner.SetPolygon(aPolyPolygon); + rOutliner.SetUpdateMode(true); + rOutliner.SetText(rSdrContourTextPrimitive.getOutlinerParaObject()); + + // set visualizing page at Outliner; needed e.g. for PageNumberField decomposition + rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage())); + + // prepare matrices to apply to newly created primitives + basegfx::B2DHomMatrix aNewTransformA; + + // mirroring. We are now in the polygon sizes. When mirroring in X and Y, + // move the null point which was top left to bottom right. + const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0)); + const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0)); + + // in-between the translations of the single primitives will take place. Afterwards, + // the object's transformations need to be applied + const basegfx::B2DHomMatrix aNewTransformB(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0, + fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); + + // now break up text primitives. + impTextBreakupHandler aConverter(rOutliner); + aConverter.decomposeContourTextPrimitive(aNewTransformA, aNewTransformB, aScale); + + // cleanup outliner + rOutliner.Clear(); + rOutliner.setVisualizedPage(0); + + rTarget = aConverter.getPrimitive2DSequence(); +} + +void SdrTextObj::impDecomposeBlockTextPrimitive( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::SdrBlockTextPrimitive2D& rSdrBlockTextPrimitive, + const drawinglayer::geometry::ViewInformation2D& aViewInformation) const +{ + // decompose matrix to have position and size of text + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rSdrBlockTextPrimitive.getTextRangeTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // use B2DRange aAnchorTextRange for calculations + basegfx::B2DRange aAnchorTextRange(aTranslate); + aAnchorTextRange.expand(aTranslate + aScale); + + // prepare outliner + const bool bIsCell(rSdrBlockTextPrimitive.getCellText()); + SdrOutliner& rOutliner = ImpGetDrawOutliner(); + SdrTextHorzAdjust eHAdj = rSdrBlockTextPrimitive.getSdrTextHorzAdjust(); + SdrTextVertAdjust eVAdj = rSdrBlockTextPrimitive.getSdrTextVertAdjust(); + const sal_uInt32 nOriginalControlWord(rOutliner.GetControlWord()); + const Size aNullSize; + + // set visualizing page at Outliner; needed e.g. for PageNumberField decomposition + rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage())); + rOutliner.SetFixedCellHeight(rSdrBlockTextPrimitive.isFixedCellHeight()); + rOutliner.SetControlWord(nOriginalControlWord|EE_CNTRL_AUTOPAGESIZE); + rOutliner.SetMinAutoPaperSize(aNullSize); + rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000)); + + // add one to rage sizes to get back to the old Rectangle and outliner measurements + const sal_uInt32 nAnchorTextWidth(FRound(aAnchorTextRange.getWidth() + 1L)); + const sal_uInt32 nAnchorTextHeight(FRound(aAnchorTextRange.getHeight() + 1L)); + const bool bVerticalWritintg(rSdrBlockTextPrimitive.getOutlinerParaObject().IsVertical()); + const Size aAnchorTextSize(Size(nAnchorTextWidth, nAnchorTextHeight)); + + if(bIsCell) + { + // cell text is formated neither like a text object nor like a object + // text, so use a special setup here + rOutliner.SetMaxAutoPaperSize(aAnchorTextSize); + + // #i106214# To work with an unchangeable PaperSize (CellSize in + // this case) Set(Min|Max)AutoPaperSize and SetPaperSize have to be used. + // #i106214# This was not completely correct; to still measure the real + // text height to allow vertical adjust (and vice versa for VerticalWritintg) + // only one aspect has to be set, but the other one to zero + if(bVerticalWritintg) + { + // measure the horizontal text size + rOutliner.SetMinAutoPaperSize(Size(0, aAnchorTextSize.Height())); + } + else + { + // measure the vertical text size + rOutliner.SetMinAutoPaperSize(Size(aAnchorTextSize.Width(), 0)); + } + + rOutliner.SetPaperSize(aAnchorTextSize); + rOutliner.SetUpdateMode(true); + rOutliner.SetText(rSdrBlockTextPrimitive.getOutlinerParaObject()); + } + else + { + // check if block text is used (only one of them can be true) + const bool bHorizontalIsBlock(SDRTEXTHORZADJUST_BLOCK == eHAdj && !bVerticalWritintg); + const bool bVerticalIsBlock(SDRTEXTVERTADJUST_BLOCK == eVAdj && bVerticalWritintg); + + // set minimal paper size hor/ver if needed + if(bHorizontalIsBlock) + { + rOutliner.SetMinAutoPaperSize(Size(nAnchorTextWidth, 0)); + } + else if(bVerticalIsBlock) + { + rOutliner.SetMinAutoPaperSize(Size(0, nAnchorTextHeight)); + } + + if((rSdrBlockTextPrimitive.getWordWrap() || IsTextFrame()) && !rSdrBlockTextPrimitive.getUnlimitedPage()) + { + // #i103454# maximal paper size hor/ver needs to be limited to text + // frame size. If it's block text, still allow the 'other' direction + // to grow to get a correct real text size when using GetPaperSize(). + // When just using aAnchorTextSize as maximum, GetPaperSize() + // would just return aAnchorTextSize again: this means, the wanted + // 'measurement' of the real size of block text would not work + Size aMaxAutoPaperSize(aAnchorTextSize); + + if(bHorizontalIsBlock) + { + // allow to grow vertical for horizontal blocks + aMaxAutoPaperSize.setHeight(1000000); + } + else if(bVerticalIsBlock) + { + // allow to grow horizontal for vertical blocks + aMaxAutoPaperSize.setWidth(1000000); + } + + rOutliner.SetMaxAutoPaperSize(aMaxAutoPaperSize); + } + + rOutliner.SetPaperSize(aNullSize); + rOutliner.SetUpdateMode(true); + rOutliner.SetText(rSdrBlockTextPrimitive.getOutlinerParaObject()); + } + + rOutliner.SetControlWord(nOriginalControlWord); + + // now get back the layouted text size from outliner + const Size aOutlinerTextSiz(rOutliner.GetPaperSize()); + const basegfx::B2DVector aOutlinerScale(aOutlinerTextSiz.Width(), aOutlinerTextSiz.Height()); + basegfx::B2DVector aAdjustTranslate(0.0, 0.0); + + // For draw objects containing text correct hor/ver alignment if text is bigger + // than the object itself. Without that correction, the text would always be + // formatted to the left edge (or top edge when vertical) of the draw object. + if(!IsTextFrame() && !bIsCell) + { + if(aAnchorTextRange.getWidth() < aOutlinerScale.getX() && !bVerticalWritintg) + { + // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTHORZADJUST_BLOCK == eHAdj) + { + eHAdj = SDRTEXTHORZADJUST_CENTER; + } + } + + if(aAnchorTextRange.getHeight() < aOutlinerScale.getY() && bVerticalWritintg) + { + // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTVERTADJUST_BLOCK == eVAdj) + { + eVAdj = SDRTEXTVERTADJUST_CENTER; + } + } + } + + // correct horizontal translation using the now known text size + if(SDRTEXTHORZADJUST_CENTER == eHAdj || SDRTEXTHORZADJUST_RIGHT == eHAdj) + { + const double fFree(aAnchorTextRange.getWidth() - aOutlinerScale.getX()); + + if(SDRTEXTHORZADJUST_CENTER == eHAdj) + { + aAdjustTranslate.setX(fFree / 2.0); + } + + if(SDRTEXTHORZADJUST_RIGHT == eHAdj) + { + aAdjustTranslate.setX(fFree); + } + } + + // correct vertical translation using the now known text size + if(SDRTEXTVERTADJUST_CENTER == eVAdj || SDRTEXTVERTADJUST_BOTTOM == eVAdj) + { + const double fFree(aAnchorTextRange.getHeight() - aOutlinerScale.getY()); + + if(SDRTEXTVERTADJUST_CENTER == eVAdj) + { + aAdjustTranslate.setY(fFree / 2.0); + } + + if(SDRTEXTVERTADJUST_BOTTOM == eVAdj) + { + aAdjustTranslate.setY(fFree); + } + } + + // prepare matrices to apply to newly created primitives. aNewTransformA + // will get coordinates in aOutlinerScale size and positive in X, Y. + // Translate relative to given primitive to get same rotation and shear + // as the master shape we are working on. For vertical, use the top-right + // corner + const double fStartInX(bVerticalWritintg ? aAdjustTranslate.getX() + aOutlinerScale.getX() : aAdjustTranslate.getX()); + const basegfx::B2DTuple aAdjOffset(fStartInX, aAdjustTranslate.getY()); + basegfx::B2DHomMatrix aNewTransformA(basegfx::tools::createTranslateB2DHomMatrix(aAdjOffset.getX(), aAdjOffset.getY())); + + // mirroring. We are now in aAnchorTextRange sizes. When mirroring in X and Y, + // move the null point which was top left to bottom right. + const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0)); + const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0)); + + // in-between the translations of the single primitives will take place. Afterwards, + // the object's transformations need to be applied + const basegfx::B2DHomMatrix aNewTransformB(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0, + fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); + + // #SJ# create ClipRange (if needed) + basegfx::B2DRange aClipRange; + + if(rSdrBlockTextPrimitive.getClipOnBounds()) + { + aClipRange.expand(-aAdjOffset); + aClipRange.expand(basegfx::B2DTuple(aAnchorTextSize.Width(), aAnchorTextSize.Height()) - aAdjOffset); + } + + // now break up text primitives. + impTextBreakupHandler aConverter(rOutliner); + aConverter.decomposeBlockTextPrimitive(aNewTransformA, aNewTransformB, aClipRange); + + // cleanup outliner + rOutliner.Clear(); + rOutliner.setVisualizedPage(0); + + rTarget = aConverter.getPrimitive2DSequence(); +} + +void SdrTextObj::impDecomposeStretchTextPrimitive( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::SdrStretchTextPrimitive2D& rSdrStretchTextPrimitive, + const drawinglayer::geometry::ViewInformation2D& aViewInformation) const +{ + // decompose matrix to have position and size of text + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rSdrStretchTextPrimitive.getTextRangeTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // use non-mirrored B2DRange aAnchorTextRange for calculations + basegfx::B2DRange aAnchorTextRange(aTranslate); + aAnchorTextRange.expand(aTranslate + aScale); + + // prepare outliner + SdrOutliner& rOutliner = ImpGetDrawOutliner(); + const sal_uInt32 nOriginalControlWord(rOutliner.GetControlWord()); + const Size aNullSize; + + rOutliner.SetControlWord(nOriginalControlWord|EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE); + rOutliner.SetFixedCellHeight(rSdrStretchTextPrimitive.isFixedCellHeight()); + rOutliner.SetMinAutoPaperSize(aNullSize); + rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000)); + rOutliner.SetPaperSize(aNullSize); + rOutliner.SetUpdateMode(true); + rOutliner.SetText(rSdrStretchTextPrimitive.getOutlinerParaObject()); + + // set visualizing page at Outliner; needed e.g. for PageNumberField decomposition + rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage())); + + // now get back the layouted text size from outliner + const Size aOutlinerTextSiz(rOutliner.CalcTextSize()); + const basegfx::B2DVector aOutlinerScale( + basegfx::fTools::equalZero(aOutlinerTextSiz.Width()) ? 1.0 : aOutlinerTextSiz.Width(), + basegfx::fTools::equalZero(aOutlinerTextSiz.Height()) ? 1.0 : aOutlinerTextSiz.Height()); + + // prepare matrices to apply to newly created primitives + basegfx::B2DHomMatrix aNewTransformA; + + // #i101957# Check for vertical text. If used, aNewTransformA + // needs to translate the text initially around object width to orient + // it relative to the topper right instead of the topper left + const bool bVertical(rSdrStretchTextPrimitive.getOutlinerParaObject().IsVertical()); + + if(bVertical) + { + aNewTransformA.translate(aScale.getX(), 0.0); + } + + // calculate global char stretching scale parameters. Use non-mirrored sizes + // to layout without mirroring + const double fScaleX(fabs(aScale.getX()) / aOutlinerScale.getX()); + const double fScaleY(fabs(aScale.getY()) / aOutlinerScale.getY()); + rOutliner.SetGlobalCharStretching((sal_Int16)FRound(fScaleX * 100.0), (sal_Int16)FRound(fScaleY * 100.0)); + + // mirroring. We are now in aAnchorTextRange sizes. When mirroring in X and Y, + // move the null point which was top left to bottom right. + const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0)); + const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0)); + + // in-between the translations of the single primitives will take place. Afterwards, + // the object's transformations need to be applied + const basegfx::B2DHomMatrix aNewTransformB(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0, + fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); + + // now break up text primitives. + impTextBreakupHandler aConverter(rOutliner); + aConverter.decomposeStretchTextPrimitive(aNewTransformA, aNewTransformB); + + // cleanup outliner + rOutliner.SetControlWord(nOriginalControlWord); + rOutliner.Clear(); + rOutliner.setVisualizedPage(0); + + rTarget = aConverter.getPrimitive2DSequence(); +} + +////////////////////////////////////////////////////////////////////////////// +// timing generators +#define ENDLESS_LOOP (0xffffffff) +#define ENDLESS_TIME ((double)0xffffffff) +#define PIXEL_DPI (96.0) + +void SdrTextObj::impGetBlinkTextTiming(drawinglayer::animation::AnimationEntryList& rAnimList) const +{ + if(SDRTEXTANI_BLINK == GetTextAniKind()) + { + // get values + const SfxItemSet& rSet = GetObjectItemSet(); + const sal_uInt32 nRepeat((sal_uInt32)((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue()); + bool bVisisbleWhenStopped(((SdrTextAniStopInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE)).GetValue()); + double fDelay((double)((SdrTextAniDelayItem&)rSet.Get(SDRATTR_TEXT_ANIDELAY)).GetValue()); + + if(0.0 == fDelay) + { + // use default + fDelay = 250.0; + } + + // prepare loop and add + drawinglayer::animation::AnimationEntryLoop aLoop(nRepeat ? nRepeat : ENDLESS_LOOP); + drawinglayer::animation::AnimationEntryFixed aStart(fDelay, 0.0); + aLoop.append(aStart); + drawinglayer::animation::AnimationEntryFixed aEnd(fDelay, 1.0); + aLoop.append(aEnd); + rAnimList.append(aLoop); + + // add stopped state if loop is not endless + if(0L != nRepeat) + { + drawinglayer::animation::AnimationEntryFixed aStop(ENDLESS_TIME, bVisisbleWhenStopped ? 0.0 : 1.0); + rAnimList.append(aStop); + } + } +} + +void impCreateScrollTiming(const SfxItemSet& rSet, drawinglayer::animation::AnimationEntryList& rAnimList, bool bForward, double fTimeFullPath, double fFrequency) +{ + bool bVisisbleWhenStopped(((SdrTextAniStopInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE)).GetValue()); + bool bVisisbleWhenStarted(((SdrTextAniStartInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE )).GetValue()); + const sal_uInt32 nRepeat(((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue()); + + if(bVisisbleWhenStarted) + { + // move from center to outside + drawinglayer::animation::AnimationEntryLinear aInOut(fTimeFullPath * 0.5, fFrequency, 0.5, bForward ? 1.0 : 0.0); + rAnimList.append(aInOut); + } + + // loop. In loop, move through + if(nRepeat || 0L == nRepeat) + { + drawinglayer::animation::AnimationEntryLoop aLoop(nRepeat ? nRepeat : ENDLESS_LOOP); + drawinglayer::animation::AnimationEntryLinear aThrough(fTimeFullPath, fFrequency, bForward ? 0.0 : 1.0, bForward ? 1.0 : 0.0); + aLoop.append(aThrough); + rAnimList.append(aLoop); + } + + if(0L != nRepeat && bVisisbleWhenStopped) + { + // move from outside to center + drawinglayer::animation::AnimationEntryLinear aOutIn(fTimeFullPath * 0.5, fFrequency, bForward ? 0.0 : 1.0, 0.5); + rAnimList.append(aOutIn); + + // add timing for staying at the end + drawinglayer::animation::AnimationEntryFixed aEnd(ENDLESS_TIME, 0.5); + rAnimList.append(aEnd); + } +} + +void impCreateAlternateTiming(const SfxItemSet& rSet, drawinglayer::animation::AnimationEntryList& rAnimList, double fRelativeTextLength, bool bForward, double fTimeFullPath, double fFrequency) +{ + if(basegfx::fTools::more(fRelativeTextLength, 0.5)) + { + // this is the case when fTextLength > fFrameLength, text is bigger than animation frame. + // In that case, correct direction + bForward = !bForward; + } + + const double fStartPosition(bForward ? fRelativeTextLength : 1.0 - fRelativeTextLength); + const double fEndPosition(bForward ? 1.0 - fRelativeTextLength : fRelativeTextLength); + bool bVisisbleWhenStopped(((SdrTextAniStopInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE)).GetValue()); + bool bVisisbleWhenStarted(((SdrTextAniStartInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE )).GetValue()); + const sal_uInt32 nRepeat(((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue()); + + if(!bVisisbleWhenStarted) + { + // move from outside to center + drawinglayer::animation::AnimationEntryLinear aOutIn(fTimeFullPath * 0.5, fFrequency, bForward ? 0.0 : 1.0, 0.5); + rAnimList.append(aOutIn); + } + + // loop. In loop, move out and in again. fInnerMovePath may be negative when text is bigger then frame, + // so use absolute value + const double fInnerMovePath(fabs(1.0 - (fRelativeTextLength * 2.0))); + const double fTimeForInnerPath(fTimeFullPath * fInnerMovePath); + const double fHalfInnerPath(fTimeForInnerPath * 0.5); + const sal_uInt32 nDoubleRepeat(nRepeat / 2L); + + if(nDoubleRepeat || 0L == nRepeat) + { + // double forth and back loop + drawinglayer::animation::AnimationEntryLoop aLoop(nDoubleRepeat ? nDoubleRepeat : ENDLESS_LOOP); + drawinglayer::animation::AnimationEntryLinear aTime0(fHalfInnerPath, fFrequency, 0.5, fEndPosition); + aLoop.append(aTime0); + drawinglayer::animation::AnimationEntryLinear aTime1(fTimeForInnerPath, fFrequency, fEndPosition, fStartPosition); + aLoop.append(aTime1); + drawinglayer::animation::AnimationEntryLinear aTime2(fHalfInnerPath, fFrequency, fStartPosition, 0.5); + aLoop.append(aTime2); + rAnimList.append(aLoop); + } + + if(nRepeat % 2L) + { + // repeat is uneven, so we need one more forth and back to center + drawinglayer::animation::AnimationEntryLinear aTime0(fHalfInnerPath, fFrequency, 0.5, fEndPosition); + rAnimList.append(aTime0); + drawinglayer::animation::AnimationEntryLinear aTime1(fHalfInnerPath, fFrequency, fEndPosition, 0.5); + rAnimList.append(aTime1); + } + + if(0L != nRepeat) + { + if(bVisisbleWhenStopped) + { + // add timing for staying at the end + drawinglayer::animation::AnimationEntryFixed aEnd(ENDLESS_TIME, 0.5); + rAnimList.append(aEnd); + } + else + { + // move from center to outside + drawinglayer::animation::AnimationEntryLinear aInOut(fTimeFullPath * 0.5, fFrequency, 0.5, bForward ? 1.0 : 0.0); + rAnimList.append(aInOut); + } + } +} + +void impCreateSlideTiming(const SfxItemSet& rSet, drawinglayer::animation::AnimationEntryList& rAnimList, bool bForward, double fTimeFullPath, double fFrequency) +{ + // move in from outside, start outside + const double fStartPosition(bForward ? 0.0 : 1.0); + const sal_uInt32 nRepeat(((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue()); + + // move from outside to center + drawinglayer::animation::AnimationEntryLinear aOutIn(fTimeFullPath * 0.5, fFrequency, fStartPosition, 0.5); + rAnimList.append(aOutIn); + + // loop. In loop, move out and in again + if(nRepeat > 1L || 0L == nRepeat) + { + drawinglayer::animation::AnimationEntryLoop aLoop(nRepeat ? nRepeat - 1L : ENDLESS_LOOP); + drawinglayer::animation::AnimationEntryLinear aTime0(fTimeFullPath * 0.5, fFrequency, 0.5, fStartPosition); + aLoop.append(aTime0); + drawinglayer::animation::AnimationEntryLinear aTime1(fTimeFullPath * 0.5, fFrequency, fStartPosition, 0.5); + aLoop.append(aTime1); + rAnimList.append(aLoop); + } + + // always visible when stopped, so add timing for staying at the end when not endless + if(0L != nRepeat) + { + drawinglayer::animation::AnimationEntryFixed aEnd(ENDLESS_TIME, 0.5); + rAnimList.append(aEnd); + } +} + +void SdrTextObj::impGetScrollTextTiming(drawinglayer::animation::AnimationEntryList& rAnimList, double fFrameLength, double fTextLength) const +{ + const SdrTextAniKind eAniKind(GetTextAniKind()); + + if(SDRTEXTANI_SCROLL == eAniKind || SDRTEXTANI_ALTERNATE == eAniKind || SDRTEXTANI_SLIDE == eAniKind) + { + // get data. Goal is to calculate fTimeFullPath which is the time needed to + // move animation from (0.0) to (1.0) state + const SfxItemSet& rSet = GetObjectItemSet(); + double fAnimationDelay((double)((SdrTextAniDelayItem&)rSet.Get(SDRATTR_TEXT_ANIDELAY)).GetValue()); + double fSingleStepWidth((double)((SdrTextAniAmountItem&)rSet.Get(SDRATTR_TEXT_ANIAMOUNT)).GetValue()); + const SdrTextAniDirection eDirection(GetTextAniDirection()); + const bool bForward(SDRTEXTANI_RIGHT == eDirection || SDRTEXTANI_DOWN == eDirection); + + if(basegfx::fTools::equalZero(fAnimationDelay)) + { + // default to 1/20 second + fAnimationDelay = 50.0; + } + + if(basegfx::fTools::less(fSingleStepWidth, 0.0)) + { + // data is in pixels, convert to logic. Imply PIXEL_DPI dpi. + // It makes no sense to keep the view-transformation centered + // definitions, so get rid of them here. + fSingleStepWidth = (-fSingleStepWidth * (2540.0 / PIXEL_DPI)); + } + + if(basegfx::fTools::equalZero(fSingleStepWidth)) + { + // default to 1 milimeter + fSingleStepWidth = 100.0; + } + + // use the length of the full animation path and the number of steps + // to get the full path time + const double fFullPathLength(fFrameLength + fTextLength); + const double fNumberOfSteps(fFullPathLength / fSingleStepWidth); + double fTimeFullPath(fNumberOfSteps * fAnimationDelay); + + if(fTimeFullPath < fAnimationDelay) + { + fTimeFullPath = fAnimationDelay; + } + + switch(eAniKind) + { + case SDRTEXTANI_SCROLL : + { + impCreateScrollTiming(rSet, rAnimList, bForward, fTimeFullPath, fAnimationDelay); + break; + } + case SDRTEXTANI_ALTERNATE : + { + double fRelativeTextLength(fTextLength / (fFrameLength + fTextLength)); + impCreateAlternateTiming(rSet, rAnimList, fRelativeTextLength, bForward, fTimeFullPath, fAnimationDelay); + break; + } + case SDRTEXTANI_SLIDE : + { + impCreateSlideTiming(rSet, rAnimList, bForward, fTimeFullPath, fAnimationDelay); + break; + } + default : break; // SDRTEXTANI_NONE, SDRTEXTANI_BLINK + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdotextpathdecomposition.cxx b/svx/source/svdraw/svdotextpathdecomposition.cxx new file mode 100644 index 000000000000..031e8e9dd45b --- /dev/null +++ b/svx/source/svdraw/svdotextpathdecomposition.cxx @@ -0,0 +1,824 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdotext.hxx> +#include <svx/svdoutl.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx> +#include <basegfx/range/b2drange.hxx> +#include <vcl/salbtype.hxx> +#include <svl/itemset.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <algorithm> +#include <svx/xtextit.hxx> +#include <svx/xftshtit.hxx> +#include <vcl/virdev.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/i18n/ScriptType.hdl> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/i18n/CharacterIteratorMode.hdl> +#include <editeng/unolingu.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <basegfx/color/bcolor.hxx> + +////////////////////////////////////////////////////////////////////////////// +// primitive decomposition helpers + +#include <basegfx/polygon/b2dlinegeometry.hxx> +#include <drawinglayer/attribute/strokeattribute.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlinjoit.hxx> +#include <svx/xlndsit.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> +#include <editeng/editstat.hxx> +#include <unoapi.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <svx/sdr/attribute/sdrformtextoutlineattribute.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::i18n; + +////////////////////////////////////////////////////////////////////////////// +// PathTextPortion helper + +namespace +{ + class impPathTextPortion + { + basegfx::B2DVector maOffset; + String maText; + xub_StrLen mnTextStart; + xub_StrLen mnTextLength; + sal_uInt16 mnParagraph; + xub_StrLen mnIndex; + SvxFont maFont; + ::std::vector< double > maDblDXArray; // double DXArray, font size independent -> unit coordinate system + ::com::sun::star::lang::Locale maLocale; + + // bitfield + unsigned mbRTL : 1; + + public: + impPathTextPortion(DrawPortionInfo& rInfo) + : maOffset(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y()), + maText(rInfo.mrText), + mnTextStart(rInfo.mnTextStart), + mnTextLength(rInfo.mnTextLen), + mnParagraph(rInfo.mnPara), + mnIndex(rInfo.mnIndex), + maFont(rInfo.mrFont), + maDblDXArray(), + maLocale(rInfo.mpLocale ? *rInfo.mpLocale : ::com::sun::star::lang::Locale()), + mbRTL(rInfo.mrFont.IsVertical() ? false : rInfo.IsRTL()) + { + if(mnTextLength && rInfo.mpDXArray) + { + maDblDXArray.reserve(mnTextLength); + + for(xub_StrLen a(0); a < mnTextLength; a++) + { + maDblDXArray.push_back((double)rInfo.mpDXArray[a]); + } + } + } + + // for ::std::sort + bool operator<(const impPathTextPortion& rComp) const + { + if(mnParagraph < rComp.mnParagraph) + { + return true; + } + + if(maOffset.getX() < rComp.maOffset.getX()) + { + return true; + } + + return (maOffset.getY() < rComp.maOffset.getY()); + } + + const basegfx::B2DVector& getOffset() const { return maOffset; } + const String& getText() const { return maText; } + xub_StrLen getTextStart() const { return mnTextStart; } + xub_StrLen getTextLength() const { return mnTextLength; } + sal_uInt16 getParagraph() const { return mnParagraph; } + xub_StrLen getIndex() const { return mnIndex; } + const SvxFont& getFont() const { return maFont; } + bool isRTL() const { return mbRTL; } + const ::std::vector< double >& getDoubleDXArray() const { return maDblDXArray; } + const ::com::sun::star::lang::Locale& getLocale() const { return maLocale; } + + xub_StrLen getPortionIndex(xub_StrLen nIndex, xub_StrLen nLength) const + { + if(mbRTL) + { + return (mnTextStart + (mnTextLength - (nIndex + nLength))); + } + else + { + return (mnTextStart + nIndex); + } + } + + double getDisplayLength(xub_StrLen nIndex, xub_StrLen nLength) const + { + drawinglayer::primitive2d::TextLayouterDevice aTextLayouter; + double fRetval(0.0); + + if(maFont.IsVertical()) + { + fRetval = aTextLayouter.getTextHeight() * (double)nLength; + } + else + { + fRetval = aTextLayouter.getTextWidth(maText, getPortionIndex(nIndex, nLength), nLength); + } + + return fRetval; + } + }; +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// +// TextBreakup helper + +namespace +{ + class impTextBreakupHandler + { + SdrOutliner& mrOutliner; + ::std::vector< impPathTextPortion > maPathTextPortions; + + DECL_LINK(decompositionPathTextPrimitive, DrawPortionInfo* ); + + public: + impTextBreakupHandler(SdrOutliner& rOutliner) + : mrOutliner(rOutliner) + { + } + + const ::std::vector< impPathTextPortion >& decompositionPathTextPrimitive() + { + // strip portions to maPathTextPortions + mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decompositionPathTextPrimitive)); + mrOutliner.StripPortions(); + + if(maPathTextPortions.size()) + { + // sort portions by paragraph, x and y + ::std::sort(maPathTextPortions.begin(), maPathTextPortions.end()); + } + + return maPathTextPortions; + } + }; + + IMPL_LINK(impTextBreakupHandler, decompositionPathTextPrimitive, DrawPortionInfo*, pInfo) + { + maPathTextPortions.push_back(impPathTextPortion(*pInfo)); + return 0; + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// +// TextBreakup one poly and one paragraph helper + +namespace +{ + class impPolygonParagraphHandler + { + const drawinglayer::attribute::SdrFormTextAttribute maSdrFormTextAttribute; // FormText parameters + std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& mrDecomposition; // destination primitive list + std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& mrShadowDecomposition; // destination primitive list for shadow + Reference < com::sun::star::i18n::XBreakIterator > mxBreak; // break iterator + + double getParagraphTextLength(const ::std::vector< const impPathTextPortion* >& rTextPortions) + { + drawinglayer::primitive2d::TextLayouterDevice aTextLayouter; + double fRetval(0.0); + + for(sal_uInt32 a(0L); a < rTextPortions.size(); a++) + { + const impPathTextPortion* pCandidate = rTextPortions[a]; + + if(pCandidate && pCandidate->getTextLength()) + { + aTextLayouter.setFont(pCandidate->getFont()); + fRetval += pCandidate->getDisplayLength(0L, pCandidate->getTextLength()); + } + } + + return fRetval; + } + + xub_StrLen getNextGlyphLen(const impPathTextPortion* pCandidate, xub_StrLen nPosition, const ::com::sun::star::lang::Locale& rFontLocale) + { + xub_StrLen nNextGlyphLen(1); + + if(mxBreak.is()) + { + sal_Int32 nDone(0L); + nNextGlyphLen = (xub_StrLen)mxBreak->nextCharacters(pCandidate->getText(), nPosition, + rFontLocale, CharacterIteratorMode::SKIPCELL, 1, nDone) - nPosition; + } + + return nNextGlyphLen; + } + + public: + impPolygonParagraphHandler( + const drawinglayer::attribute::SdrFormTextAttribute& rSdrFormTextAttribute, + std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& rDecomposition, + std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& rShadowDecomposition) + : maSdrFormTextAttribute(rSdrFormTextAttribute), + mrDecomposition(rDecomposition), + mrShadowDecomposition(rShadowDecomposition) + { + // prepare BreakIterator + Reference < XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); + Reference < XInterface > xInterface = xMSF->createInstance(::rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")); + + if(xInterface.is()) + { + Any x = xInterface->queryInterface(::getCppuType((const Reference< XBreakIterator >*)0)); + x >>= mxBreak; + } + } + + void HandlePair(const basegfx::B2DPolygon rPolygonCandidate, const ::std::vector< const impPathTextPortion* >& rTextPortions) + { + // prepare polygon geometry, take into account as many parameters as possible + basegfx::B2DPolygon aPolygonCandidate(rPolygonCandidate); + const double fPolyLength(basegfx::tools::getLength(aPolygonCandidate)); + double fPolyEnd(fPolyLength); + double fPolyStart(0.0); + double fAutosizeScaleFactor(1.0); + bool bAutosizeScale(false); + + if(maSdrFormTextAttribute.getFormTextMirror()) + { + aPolygonCandidate.flip(); + } + + if(maSdrFormTextAttribute.getFormTextStart() + && (XFT_LEFT == maSdrFormTextAttribute.getFormTextAdjust() + || XFT_RIGHT == maSdrFormTextAttribute.getFormTextAdjust())) + { + if(XFT_LEFT == maSdrFormTextAttribute.getFormTextAdjust()) + { + fPolyStart += maSdrFormTextAttribute.getFormTextStart(); + + if(fPolyStart > fPolyEnd) + { + fPolyStart = fPolyEnd; + } + } + else + { + fPolyEnd -= maSdrFormTextAttribute.getFormTextStart(); + + if(fPolyEnd < fPolyStart) + { + fPolyEnd = fPolyStart; + } + } + } + + if(XFT_LEFT != maSdrFormTextAttribute.getFormTextAdjust()) + { + // calculate total text length of this paragraph, some layout needs to be done + const double fParagraphTextLength(getParagraphTextLength(rTextPortions)); + + // check if text is too long for paragraph. If yes, handle as if left aligned (default), + // but still take care of XFT_AUTOSIZE in that case + const bool bTextTooLong(fParagraphTextLength > (fPolyEnd - fPolyStart)); + + if(XFT_RIGHT == maSdrFormTextAttribute.getFormTextAdjust()) + { + if(!bTextTooLong) + { + // if right aligned, add difference to polygon start + fPolyStart += ((fPolyEnd - fPolyStart) - fParagraphTextLength); + } + } + else if(XFT_CENTER == maSdrFormTextAttribute.getFormTextAdjust()) + { + if(!bTextTooLong) + { + // if centered, add half of difference to polygon start + fPolyStart += ((fPolyEnd - fPolyStart) - fParagraphTextLength) / 2.0; + } + } + else if(XFT_AUTOSIZE == maSdrFormTextAttribute.getFormTextAdjust()) + { + // if scale, prepare scale factor between curve length and text length + if(0.0 != fParagraphTextLength) + { + fAutosizeScaleFactor = (fPolyEnd - fPolyStart) / fParagraphTextLength; + bAutosizeScale = true; + } + } + } + + // handle text portions for this paragraph + for(sal_uInt32 a(0L); a < rTextPortions.size() && fPolyStart < fPolyEnd; a++) + { + const impPathTextPortion* pCandidate = rTextPortions[a]; + basegfx::B2DVector aFontScaling; + const drawinglayer::attribute::FontAttribute aCandidateFontAttribute( + drawinglayer::primitive2d::getFontAttributeFromVclFont( + aFontScaling, + pCandidate->getFont(), + pCandidate->isRTL(), + false)); + + if(pCandidate && pCandidate->getTextLength()) + { + drawinglayer::primitive2d::TextLayouterDevice aTextLayouter; + aTextLayouter.setFont(pCandidate->getFont()); + xub_StrLen nUsedTextLength(0); + + while(nUsedTextLength < pCandidate->getTextLength() && fPolyStart < fPolyEnd) + { + xub_StrLen nNextGlyphLen(getNextGlyphLen(pCandidate, pCandidate->getTextStart() + nUsedTextLength, pCandidate->getLocale())); + + // prepare portion length. Takes RTL sections into account. + double fPortionLength(pCandidate->getDisplayLength(nUsedTextLength, nNextGlyphLen)); + + if(bAutosizeScale) + { + // when autosize scaling, expand portion length + fPortionLength *= fAutosizeScaleFactor; + } + + // create transformation + basegfx::B2DHomMatrix aNewTransformA, aNewTransformB, aNewShadowTransform; + basegfx::B2DPoint aStartPos(basegfx::tools::getPositionAbsolute(aPolygonCandidate, fPolyStart, fPolyLength)); + basegfx::B2DPoint aEndPos(aStartPos); + + // add font scaling + aNewTransformA.scale(aFontScaling.getX(), aFontScaling.getY()); + + // prepare scaling of text primitive + if(bAutosizeScale) + { + // when autosize scaling, expand text primitive scaling to it + aNewTransformA.scale(fAutosizeScaleFactor, fAutosizeScaleFactor); + } + + // eventually create shadow primitives from aDecomposition and add to rDecomposition + const bool bShadow(XFTSHADOW_NONE != maSdrFormTextAttribute.getFormTextShadow()); + + if(bShadow) + { + if(XFTSHADOW_NORMAL == maSdrFormTextAttribute.getFormTextShadow()) + { + aNewShadowTransform.translate( + maSdrFormTextAttribute.getFormTextShdwXVal(), + -maSdrFormTextAttribute.getFormTextShdwYVal()); + } + else // XFTSHADOW_SLANT + { + double fScaleValue(maSdrFormTextAttribute.getFormTextShdwYVal() / 100.0); + double fShearValue(-maSdrFormTextAttribute.getFormTextShdwXVal() * F_PI1800); + + aNewShadowTransform.scale(1.0, fScaleValue); + aNewShadowTransform.shearX(sin(fShearValue)); + aNewShadowTransform.scale(1.0, cos(fShearValue)); + } + } + + switch(maSdrFormTextAttribute.getFormTextStyle()) + { + case XFT_ROTATE : + { + aEndPos = basegfx::tools::getPositionAbsolute(aPolygonCandidate, fPolyStart + fPortionLength, fPolyLength); + const basegfx::B2DVector aDirection(aEndPos - aStartPos); + aNewTransformB.rotate(atan2(aDirection.getY(), aDirection.getX())); + aNewTransformB.translate(aStartPos.getX(), aStartPos.getY()); + + break; + } + case XFT_UPRIGHT : + { + aNewTransformB.translate(aStartPos.getX() - (fPortionLength / 2.0), aStartPos.getY()); + + break; + } + case XFT_SLANTX : + { + aEndPos = basegfx::tools::getPositionAbsolute(aPolygonCandidate, fPolyStart + fPortionLength, fPolyLength); + const basegfx::B2DVector aDirection(aEndPos - aStartPos); + const double fShearValue(atan2(aDirection.getY(), aDirection.getX())); + const double fSin(sin(fShearValue)); + const double fCos(cos(fShearValue)); + + aNewTransformB.shearX(-fSin); + + // Scale may lead to objects without height since fCos == 0.0 is possible. + // Renderers need to handle that, it's not a forbidden value and does not + // need to be avoided + aNewTransformB.scale(1.0, fCos); + aNewTransformB.translate(aStartPos.getX() - (fPortionLength / 2.0), aStartPos.getY()); + + break; + } + case XFT_SLANTY : + { + aEndPos = basegfx::tools::getPositionAbsolute(aPolygonCandidate, fPolyStart + fPortionLength, fPolyLength); + const basegfx::B2DVector aDirection(aEndPos - aStartPos); + const double fShearValue(atan2(aDirection.getY(), aDirection.getX())); + const double fCos(cos(fShearValue)); + const double fTan(tan(fShearValue)); + + // shear to 'stand' on the curve + aNewTransformB.shearY(fTan); + + // scale in X to make as tight as needed. As with XFT_SLANT_X, this may + // lead to primitives without width which the renderers will handle + aNewTransformA.scale(fCos, 1.0); + + aNewTransformB.translate(aStartPos.getX(), aStartPos.getY()); + + break; + } + default : break; // XFT_NONE + } + + // distance from path? + if(maSdrFormTextAttribute.getFormTextDistance()) + { + if(aEndPos.equal(aStartPos)) + { + aEndPos = basegfx::tools::getPositionAbsolute(aPolygonCandidate, fPolyStart + fPortionLength, fPolyLength); + } + + // use back vector (aStartPos - aEndPos) here to get mirrored perpendicular as in old stuff + const basegfx::B2DVector aPerpendicular( + basegfx::getNormalizedPerpendicular(aStartPos - aEndPos) * + maSdrFormTextAttribute.getFormTextDistance()); + aNewTransformB.translate(aPerpendicular.getX(), aPerpendicular.getY()); + } + + if(pCandidate->getText().Len() && nNextGlyphLen) + { + const xub_StrLen nPortionIndex(pCandidate->getPortionIndex(nUsedTextLength, nNextGlyphLen)); + ::std::vector< double > aNewDXArray; + + if(nNextGlyphLen > 1 && pCandidate->getDoubleDXArray().size()) + { + // copy DXArray for portion + aNewDXArray.insert( + aNewDXArray.begin(), + pCandidate->getDoubleDXArray().begin() + nPortionIndex, + pCandidate->getDoubleDXArray().begin() + (nPortionIndex + nNextGlyphLen)); + + if(nPortionIndex > 0) + { + // adapt to portion start + double fDXOffset= *(pCandidate->getDoubleDXArray().begin() + (nPortionIndex - 1)); + ::std::transform( + aNewDXArray.begin(), aNewDXArray.end(), + aNewDXArray.begin(), ::std::bind2nd(::std::minus<double>(), fDXOffset)); + } + + if(bAutosizeScale) + { + // when autosize scaling, adapt to DXArray, too + ::std::transform( + aNewDXArray.begin(), aNewDXArray.end(), + aNewDXArray.begin(), ::std::bind2nd(::std::multiplies<double>(), fAutosizeScaleFactor)); + } + } + + if(bShadow) + { + // shadow primitive creation + const Color aShadowColor(maSdrFormTextAttribute.getFormTextShdwColor()); + const basegfx::BColor aRGBShadowColor(aShadowColor.getBColor()); + + drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pNew = + new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aNewTransformB * aNewShadowTransform * aNewTransformA, + pCandidate->getText(), + nPortionIndex, + nNextGlyphLen, + aNewDXArray, + aCandidateFontAttribute, + pCandidate->getLocale(), + aRGBShadowColor); + + mrShadowDecomposition.push_back(pNew); + } + + { + // primitive creation + const Color aColor(pCandidate->getFont().GetColor()); + const basegfx::BColor aRGBColor(aColor.getBColor()); + + drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pNew = + new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aNewTransformB * aNewTransformA, + pCandidate->getText(), + nPortionIndex, + nNextGlyphLen, + aNewDXArray, + aCandidateFontAttribute, + pCandidate->getLocale(), + aRGBColor); + + mrDecomposition.push_back(pNew); + } + } + + // consume from portion // no += here, xub_StrLen is USHORT and the compiler will gererate a warning here + nUsedTextLength = nUsedTextLength + nNextGlyphLen; + + // consume from polygon + fPolyStart += fPortionLength; + } + } + } + } + }; +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// +// primitive decomposition helpers + +namespace +{ + void impAddPolygonStrokePrimitives( + const basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector, + const basegfx::B2DHomMatrix& rTransform, + const drawinglayer::attribute::LineAttribute& rLineAttribute, + const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute, + std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& rTarget) + { + for(basegfx::B2DPolyPolygonVector::const_iterator aPolygon(rB2DPolyPolyVector.begin()); aPolygon != rB2DPolyPolyVector.end(); aPolygon++) + { + // prepare PolyPolygons + basegfx::B2DPolyPolygon aB2DPolyPolygon = *aPolygon; + aB2DPolyPolygon.transform(rTransform); + + for(sal_uInt32 a(0L); a < aB2DPolyPolygon.count(); a++) + { + // create one primitive per polygon + drawinglayer::primitive2d::PolygonStrokePrimitive2D* pNew = + new drawinglayer::primitive2d::PolygonStrokePrimitive2D( + aB2DPolyPolygon.getB2DPolygon(a), rLineAttribute, rStrokeAttribute); + rTarget.push_back(pNew); + } + } + } + + drawinglayer::primitive2d::Primitive2DSequence impAddPathTextOutlines( + const std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& rSource, + const drawinglayer::attribute::SdrFormTextOutlineAttribute& rOutlineAttribute) + { + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aNewPrimitives; + + for(sal_uInt32 a(0L); a < rSource.size(); a++) + { + const drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pTextCandidate = dynamic_cast< const drawinglayer::primitive2d::TextSimplePortionPrimitive2D* >(rSource[a]); + + if(pTextCandidate) + { + basegfx::B2DPolyPolygonVector aB2DPolyPolyVector; + basegfx::B2DHomMatrix aPolygonTransform; + + // get text outlines and their object transformation + pTextCandidate->getTextOutlinesAndTransformation(aB2DPolyPolyVector, aPolygonTransform); + + if(aB2DPolyPolyVector.size()) + { + // create stroke primitives + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aStrokePrimitives; + impAddPolygonStrokePrimitives( + aB2DPolyPolyVector, + aPolygonTransform, + rOutlineAttribute.getLineAttribute(), + rOutlineAttribute.getStrokeAttribute(), + aStrokePrimitives); + const sal_uInt32 nStrokeCount(aStrokePrimitives.size()); + + if(nStrokeCount) + { + if(rOutlineAttribute.getTransparence()) + { + // create UnifiedTransparencePrimitive2D + drawinglayer::primitive2d::Primitive2DSequence aStrokePrimitiveSequence(nStrokeCount); + + for(sal_uInt32 b(0L); b < nStrokeCount; b++) + { + aStrokePrimitiveSequence[b] = drawinglayer::primitive2d::Primitive2DReference(aStrokePrimitives[b]); + } + + drawinglayer::primitive2d::UnifiedTransparencePrimitive2D* pNew2 = + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + aStrokePrimitiveSequence, + (double)rOutlineAttribute.getTransparence() / 100.0); + aNewPrimitives.push_back(pNew2); + } + else + { + // add polygons to rDecomposition as polygonStrokePrimitives + aNewPrimitives.insert(aNewPrimitives.end(), aStrokePrimitives.begin(), aStrokePrimitives.end()); + } + } + } + } + } + + const sal_uInt32 nNewCount(aNewPrimitives.size()); + + if(nNewCount) + { + drawinglayer::primitive2d::Primitive2DSequence aRetval(nNewCount); + + for(sal_uInt32 a(0L); a < nNewCount; a++) + { + aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(aNewPrimitives[a]); + } + + return aRetval; + } + else + { + return drawinglayer::primitive2d::Primitive2DSequence(); + } + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// +// primitive decomposition + +void SdrTextObj::impDecomposePathTextPrimitive( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::SdrPathTextPrimitive2D& rSdrPathTextPrimitive, + const drawinglayer::geometry::ViewInformation2D& aViewInformation) const +{ + drawinglayer::primitive2d::Primitive2DSequence aRetvalA; + drawinglayer::primitive2d::Primitive2DSequence aRetvalB; + + // prepare outliner + SdrOutliner& rOutliner = ImpGetDrawOutliner(); + rOutliner.SetUpdateMode(true); + rOutliner.Clear(); + rOutliner.SetPaperSize(Size(LONG_MAX,LONG_MAX)); + rOutliner.SetText(rSdrPathTextPrimitive.getOutlinerParaObject()); + + // set visualizing page at Outliner; needed e.g. for PageNumberField decomposition + rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage())); + + // now break up to text portions + impTextBreakupHandler aConverter(rOutliner); + const ::std::vector< impPathTextPortion > rPathTextPortions = aConverter.decompositionPathTextPrimitive(); + + if(rPathTextPortions.size()) + { + // get FormText and polygon values + const drawinglayer::attribute::SdrFormTextAttribute& rFormTextAttribute = rSdrPathTextPrimitive.getSdrFormTextAttribute(); + const basegfx::B2DPolyPolygon& rPathPolyPolygon(rSdrPathTextPrimitive.getPathPolyPolygon()); + + // get loop count + sal_uInt32 nLoopCount(rPathPolyPolygon.count()); + + if(rOutliner.GetParagraphCount() < nLoopCount) + { + nLoopCount = rOutliner.GetParagraphCount(); + } + + if(nLoopCount) + { + // prepare common decomposition stuff + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aRegularDecomposition; + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aShadowDecomposition; + impPolygonParagraphHandler aPolygonParagraphHandler( + rFormTextAttribute, + aRegularDecomposition, + aShadowDecomposition); + sal_uInt32 a; + + for(a = 0L; a < nLoopCount; a++) + { + // filter text portions for this paragraph + ::std::vector< const impPathTextPortion* > aParagraphTextPortions; + + for(sal_uInt32 b(0L); b < rPathTextPortions.size(); b++) + { + const impPathTextPortion& rCandidate = rPathTextPortions[b]; + + if(rCandidate.getParagraph() == a) + { + aParagraphTextPortions.push_back(&rCandidate); + } + } + + // handle data pair polygon/ParagraphTextPortions + if(aParagraphTextPortions.size()) + { + aPolygonParagraphHandler.HandlePair(rPathPolyPolygon.getB2DPolygon(a), aParagraphTextPortions); + } + } + + const sal_uInt32 nShadowCount(aShadowDecomposition.size()); + const sal_uInt32 nRegularCount(aRegularDecomposition.size()); + + if(nShadowCount) + { + // add shadow primitives to decomposition + aRetvalA.realloc(nShadowCount); + + for(a = 0L; a < nShadowCount; a++) + { + aRetvalA[a] = drawinglayer::primitive2d::Primitive2DReference(aShadowDecomposition[a]); + } + + // evtl. add shadow outlines + if(rFormTextAttribute.getFormTextOutline() + && !rFormTextAttribute.getShadowOutline().isDefault()) + { + const drawinglayer::primitive2d::Primitive2DSequence aOutlines( + impAddPathTextOutlines( + aShadowDecomposition, + rFormTextAttribute.getShadowOutline())); + + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aRetvalA, aOutlines); + } + } + + if(nRegularCount) + { + // add normal primitives to decomposition + aRetvalB.realloc(nRegularCount); + + for(a = 0L; a < nRegularCount; a++) + { + aRetvalB[a] = drawinglayer::primitive2d::Primitive2DReference(aRegularDecomposition[a]); + } + + // evtl. add outlines + if(rFormTextAttribute.getFormTextOutline() + && !rFormTextAttribute.getOutline().isDefault()) + { + const drawinglayer::primitive2d::Primitive2DSequence aOutlines( + impAddPathTextOutlines( + aRegularDecomposition, + rFormTextAttribute.getOutline())); + + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aRetvalB, aOutlines); + } + } + } + } + + // cleanup outliner + rOutliner.SetDrawPortionHdl(Link()); + rOutliner.Clear(); + rOutliner.setVisualizedPage(0); + + // concatenate all results + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aRetvalA); + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aRetvalB); +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdotxat.cxx b/svx/source/svdraw/svdotxat.cxx new file mode 100644 index 000000000000..13064e890313 --- /dev/null +++ b/svx/source/svdraw/svdotxat.cxx @@ -0,0 +1,462 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svl/style.hxx> +#include <svx/svdotext.hxx> +#include "svditext.hxx" +#include <svx/svdmodel.hxx> // fuer GetMaxObjSize und GetStyleSheetPool +#include <svx/svdoutl.hxx> +#include <svx/svdorect.hxx> // fuer SetDirty bei NbcAdjustTextFrameWidthAndHeight +#include <svx/svdocapt.hxx> // fuer SetDirty bei NbcAdjustTextFrameWidthAndHeight +#include <svx/svdetc.hxx> +#include <editeng/writingmodeitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/flditem.hxx> +#include <svx/sdtfchim.hxx> + + +#include <editeng/editview.hxx> +#include <svl/smplhint.hxx> +#include <svl/whiter.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/outliner.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editobj.hxx> +#include <editeng/fhgtitem.hxx> + +#include <editeng/charscaleitem.hxx> +#include <svl/style.hxx> +#include <svl/itemiter.hxx> +#include <editeng/lrspitem.hxx> +#include <svl/itempool.hxx> +#include <editeng/numitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/postitem.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ +// +// Attribute, StyleSheets und AutoGrow +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHgt, FASTBOOL bWdt) const +{ + if (bTextFrame && pModel!=NULL && !rR.IsEmpty()) + { + SdrFitToSizeType eFit=GetFitToSize(); + FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); + FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth(); + FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight(); + SdrTextAniKind eAniKind=GetTextAniKind(); + SdrTextAniDirection eAniDir=GetTextAniDirection(); + FASTBOOL bScroll=eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE; + FASTBOOL bHScroll=bScroll && (eAniDir==SDRTEXTANI_LEFT || eAniDir==SDRTEXTANI_RIGHT); + FASTBOOL bVScroll=bScroll && (eAniDir==SDRTEXTANI_UP || eAniDir==SDRTEXTANI_DOWN); + if (!bFitToSize && (bWdtGrow || bHgtGrow)) + { + Rectangle aR0(rR); + long nHgt=0,nMinHgt=0,nMaxHgt=0; + long nWdt=0,nMinWdt=0,nMaxWdt=0; + Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--; + Size aMaxSiz(100000,100000); + Size aTmpSiz(pModel->GetMaxObjSize()); + if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); + if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); + if (bWdtGrow) + { + nMinWdt=GetMinTextFrameWidth(); + nMaxWdt=GetMaxTextFrameWidth(); + if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width(); + if (nMinWdt<=0) nMinWdt=1; + aSiz.Width()=nMaxWdt; + } + if (bHgtGrow) + { + nMinHgt=GetMinTextFrameHeight(); + nMaxHgt=GetMaxTextFrameHeight(); + if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height(); + if (nMinHgt<=0) nMinHgt=1; + aSiz.Height()=nMaxHgt; + } + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + aSiz.Width()-=nHDist; + aSiz.Height()-=nVDist; + if (aSiz.Width()<2) aSiz.Width()=2; // Mindestgroesse 2 + if (aSiz.Height()<2) aSiz.Height()=2; // Mindestgroesse 2 + + // #101684# + BOOL bInEditMode = IsInEditMode(); + + if(!bInEditMode) + { + if (bHScroll) aSiz.Width()=0x0FFFFFFF; // Laufschrift nicht umbrechen + if (bVScroll) aSiz.Height()=0x0FFFFFFF; + } + + if(pEdtOutl) + { + pEdtOutl->SetMaxAutoPaperSize(aSiz); + if (bWdtGrow) { + Size aSiz2(pEdtOutl->CalcTextSize()); + nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz + if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz + } else { + nHgt=pEdtOutl->GetTextHeight()+1; // lieber etwas Tolleranz + } + } else { + Outliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetPaperSize(aSiz); + rOutliner.SetUpdateMode(TRUE); + // !!! hier sollte ich wohl auch noch mal die Optimierung mit + // bPortionInfoChecked usw einbauen + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if ( pOutlinerParaObject != NULL ) + { + rOutliner.SetText(*pOutlinerParaObject); + rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); + } + if (bWdtGrow) + { + Size aSiz2(rOutliner.CalcTextSize()); + nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz + if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz + } else { + nHgt=rOutliner.GetTextHeight()+1; // lieber etwas Tolleranz + } + rOutliner.Clear(); + } + if (nWdt<nMinWdt) nWdt=nMinWdt; + if (nWdt>nMaxWdt) nWdt=nMaxWdt; + nWdt+=nHDist; + if (nWdt<1) nWdt=1; // nHDist kann auch negativ sein + if (nHgt<nMinHgt) nHgt=nMinHgt; + if (nHgt>nMaxHgt) nHgt=nMaxHgt; + nHgt+=nVDist; + if (nHgt<1) nHgt=1; // nVDist kann auch negativ sein + long nWdtGrow=nWdt-(rR.Right()-rR.Left()); + long nHgtGrow=nHgt-(rR.Bottom()-rR.Top()); + if (nWdtGrow==0) bWdtGrow=FALSE; + if (nHgtGrow==0) bHgtGrow=FALSE; + if (bWdtGrow || bHgtGrow) { + if (bWdtGrow) { + SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); + if (eHAdj==SDRTEXTHORZADJUST_LEFT) rR.Right()+=nWdtGrow; + else if (eHAdj==SDRTEXTHORZADJUST_RIGHT) rR.Left()-=nWdtGrow; + else { + long nWdtGrow2=nWdtGrow/2; + rR.Left()-=nWdtGrow2; + rR.Right()=rR.Left()+nWdt; + } + } + if (bHgtGrow) { + SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); + if (eVAdj==SDRTEXTVERTADJUST_TOP) rR.Bottom()+=nHgtGrow; + else if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) rR.Top()-=nHgtGrow; + else { + long nHgtGrow2=nHgtGrow/2; + rR.Top()-=nHgtGrow2; + rR.Bottom()=rR.Top()+nHgt; + } + } + if (aGeo.nDrehWink!=0) { + Point aD1(rR.TopLeft()); + aD1-=aR0.TopLeft(); + Point aD2(aD1); + RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos); + aD2-=aD1; + rR.Move(aD2.X(),aD2.Y()); + } + return TRUE; + } + } + } + return FALSE; +} + +FASTBOOL SdrTextObj::NbcAdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) +{ + FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aRect,bHgt,bWdt); + if (bRet) { + SetRectsDirty(); + if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack + ((SdrRectObj*)this)->SetXPolyDirty(); + } + if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack + ((SdrCaptionObj*)this)->ImpRecalcTail(); + } + } + return bRet; +} + +FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) +{ + Rectangle aNeuRect(aRect); + FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt); + if (bRet) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + aRect=aNeuRect; + SetRectsDirty(); + if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack + ((SdrRectObj*)this)->SetXPolyDirty(); + } + if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack + ((SdrCaptionObj*)this)->ImpRecalcTail(); + } + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } + return bRet; +} + +void SdrTextObj::ImpSetTextStyleSheetListeners() +{ + SfxStyleSheetBasePool* pStylePool=pModel!=NULL ? pModel->GetStyleSheetPool() : NULL; + if (pStylePool!=NULL) + { + Container aStyles(1024,64,64); + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if (pOutlinerParaObject!=NULL) + { + // Zunaechst werden alle im ParaObject enthaltenen StyleSheets + // im Container aStyles gesammelt. Dazu wird die Family jeweils + // ans Ende des StyleSheet-Namen drangehaengt. + const EditTextObject& rTextObj=pOutlinerParaObject->GetTextObject(); + XubString aStyleName; + SfxStyleFamily eStyleFam; + USHORT nParaAnz=rTextObj.GetParagraphCount(); + + for(UINT16 nParaNum(0); nParaNum < nParaAnz; nParaNum++) + { + rTextObj.GetStyleSheet(nParaNum, aStyleName, eStyleFam); + + if(aStyleName.Len()) + { + XubString aFam = UniString::CreateFromInt32((UINT16)eStyleFam); + aFam.Expand(5); + + aStyleName += sal_Unicode('|'); + aStyleName += aFam; + + BOOL bFnd(FALSE); + UINT32 nNum(aStyles.Count()); + + while(!bFnd && nNum > 0) + { + // kein StyleSheet doppelt! + nNum--; + bFnd = (aStyleName.Equals(*(XubString*)aStyles.GetObject(nNum))); + } + + if(!bFnd) + { + aStyles.Insert(new XubString(aStyleName), CONTAINER_APPEND); + } + } + } + } + + // nun die Strings im Container durch StyleSheet* ersetzten + ULONG nNum=aStyles.Count(); + while (nNum>0) { + nNum--; + XubString* pName=(XubString*)aStyles.GetObject(nNum); + + // UNICODE: String aFam(pName->Cut(pName->Len()-6)); + String aFam = pName->Copy(0, pName->Len() - 6); + + aFam.Erase(0,1); + aFam.EraseTrailingChars(); + + // UNICODE: USHORT nFam=USHORT(aFam); + UINT16 nFam = (UINT16)aFam.ToInt32(); + + SfxStyleFamily eFam=(SfxStyleFamily)nFam; + SfxStyleSheetBase* pStyleBase=pStylePool->Find(*pName,eFam); + SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pStyleBase); + delete pName; + if (pStyle!=NULL && pStyle!=GetStyleSheet()) { + aStyles.Replace(pStyle,nNum); + } else { + aStyles.Remove(nNum); + } + } + // jetzt alle ueberfluessigen StyleSheets entfernen + nNum=GetBroadcasterCount(); + while (nNum>0) { + nNum--; + SfxBroadcaster* pBroadcast=GetBroadcasterJOE((USHORT)nNum); + SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pBroadcast); + if (pStyle!=NULL && pStyle!=GetStyleSheet()) { // Sonderbehandlung fuer den StyleSheet des Objekts + if (aStyles.GetPos(pStyle)==CONTAINER_ENTRY_NOTFOUND) { + EndListening(*pStyle); + } + } + } + // und schliesslich alle in aStyles enthaltenen StyleSheets mit den vorhandenen Broadcastern mergen + nNum=aStyles.Count(); + while (nNum>0) { + nNum--; + SfxStyleSheet* pStyle=(SfxStyleSheet*)aStyles.GetObject(nNum); + // StartListening soll selbst nachsehen, ob hier nicht evtl. schon gehorcht wird + StartListening(*pStyle,TRUE); + } + } +} + +void SdrTextObj::NbcResizeTextAttributes(const Fraction& xFact, const Fraction& yFact) +{ + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if (pOutlinerParaObject!=NULL && xFact.IsValid() && yFact.IsValid()) + { + Fraction n100(100,1); + long nX=long(xFact*n100); + long nY=long(yFact*n100); + if (nX<0) nX=-nX; + if (nX<1) nX=1; + if (nX>0xFFFF) nX=0xFFFF; + if (nY<0) nY=-nY; + if (nY<1) nY=1; + if (nY>0xFFFF) nY=0xFFFF; + if (nX!=100 || nY!=100) + { + // Rahmenattribute + const SfxItemSet& rSet = GetObjectItemSet(); + const SvxCharScaleWidthItem& rOldWdt=(SvxCharScaleWidthItem&)rSet.Get(EE_CHAR_FONTWIDTH); + const SvxFontHeightItem& rOldHgt=(SvxFontHeightItem&)rSet.Get(EE_CHAR_FONTHEIGHT); + + // erstmal die alten Werte holen + long nRelWdt=rOldWdt.GetValue(); + long nAbsHgt=rOldHgt.GetHeight(); + long nRelHgt=rOldHgt.GetProp(); + + // Relative Breite aendern + nRelWdt*=nX; + nRelWdt/=nY; + if (nRelWdt<0) nRelWdt=-nRelWdt; // nicht negativ + if (nRelWdt<=0) nRelWdt=1; // und mind. 1% + if (nRelWdt>0xFFFF) nRelWdt=0xFFFF; + + // Absolute Hoehe aendern + nAbsHgt*=nY; + nAbsHgt/=100; + if (nAbsHgt<0) nAbsHgt=-nAbsHgt; // nicht negativ + if (nAbsHgt<=0) nAbsHgt=1; // und mind. 1 + if (nAbsHgt>0xFFFF) nAbsHgt=0xFFFF; + + // und nun attributieren + SetObjectItem(SvxCharScaleWidthItem( (USHORT) nRelWdt, EE_CHAR_FONTWIDTH)); + SetObjectItem(SvxFontHeightItem(nAbsHgt,(USHORT)nRelHgt, EE_CHAR_FONTHEIGHT)); + // Zeichen- und Absatzattribute innerhalb des OutlinerParaObjects + Outliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetPaperSize(Size(LONG_MAX,LONG_MAX)); + rOutliner.SetText(*pOutlinerParaObject); + rOutliner.DoStretchChars((USHORT)nX,(USHORT)nY); + OutlinerParaObject* pNewPara=rOutliner.CreateParaObject(); + NbcSetOutlinerParaObject(pNewPara); + rOutliner.Clear(); + } + } +} + +/** #103836# iterates over the paragraphs of a given SdrObject and removes all + hard set character attributes with the which ids contained in the + given vector +*/ +void SdrTextObj::RemoveOutlinerCharacterAttribs( const std::vector<sal_uInt16>& rCharWhichIds ) +{ + sal_Int32 nText = getTextCount(); + + while( --nText >= 0 ) + { + SdrText* pText = getText( nText ); + OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0; + + if(pOutlinerParaObject) + { + Outliner* pOutliner = 0; + + if( pEdtOutl || (pText == getActiveText()) ) + pOutliner = pEdtOutl; + + if(!pOutliner) + { + pOutliner = &ImpGetDrawOutliner(); + pOutliner->SetText(*pOutlinerParaObject); + } + + ESelection aSelAll( 0, 0, 0xffff, 0xffff ); + std::vector<sal_uInt16>::const_iterator aIter( rCharWhichIds.begin() ); + while( aIter != rCharWhichIds.end() ) + { + pOutliner->RemoveAttribs( aSelAll, false, (*aIter++) ); + } + + if(!pEdtOutl || (pText != getActiveText()) ) + { + const sal_uInt32 nParaCount = pOutliner->GetParagraphCount(); + OutlinerParaObject* pTemp = pOutliner->CreateParaObject(0, (sal_uInt16)nParaCount); + pOutliner->Clear(); + NbcSetOutlinerParaObjectForText(pTemp, pText); + } + } + } +} + +bool SdrTextObj::HasText() const +{ + if( pEdtOutl ) + return HasEditText(); + + OutlinerParaObject* pOPO = GetOutlinerParaObject(); + + bool bHasText = false; + if( pOPO ) + { + const EditTextObject& rETO = pOPO->GetTextObject(); + USHORT nParaCount = rETO.GetParagraphCount(); + + if( nParaCount > 0 ) + bHasText = (nParaCount > 1) || (rETO.GetText( 0 ).Len() != 0); + } + + return bHasText; +} diff --git a/svx/source/svdraw/svdotxdr.cxx b/svx/source/svdraw/svdotxdr.cxx new file mode 100644 index 000000000000..97da16876ac0 --- /dev/null +++ b/svx/source/svdraw/svdotxdr.cxx @@ -0,0 +1,285 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdotext.hxx> +#include <svx/svdhdl.hxx> +#include <svx/svddrag.hxx> +#include <svx/svdview.hxx> +#include <svx/svdorect.hxx> // fuer SetXPolyDirty in MovCreate bei SolidDragging +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname +#include <svx/svdoashp.hxx> +#include <tools/bigint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ +// +// Dragging, Handles, Create +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_uInt32 SdrTextObj::GetHdlCount() const +{ + return 8L; +} + +SdrHdl* SdrTextObj::GetHdl(sal_uInt32 nHdlNum) const +{ + SdrHdl* pH=NULL; + Point aPnt; + SdrHdlKind eKind=HDL_MOVE; + switch (nHdlNum) { + case 0: aPnt=aRect.TopLeft(); eKind=HDL_UPLFT; break; // Oben links + case 1: aPnt=aRect.TopCenter(); eKind=HDL_UPPER; break; // Oben + case 2: aPnt=aRect.TopRight(); eKind=HDL_UPRGT; break; // Oben rechts + case 3: aPnt=aRect.LeftCenter(); eKind=HDL_LEFT ; break; // Links + case 4: aPnt=aRect.RightCenter(); eKind=HDL_RIGHT; break; // Rechts + case 5: aPnt=aRect.BottomLeft(); eKind=HDL_LWLFT; break; // Unten links + case 6: aPnt=aRect.BottomCenter(); eKind=HDL_LOWER; break; // Unten + case 7: aPnt=aRect.BottomRight(); eKind=HDL_LWRGT; break; // Unten rechts + } + if (aGeo.nShearWink!=0) ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + if (eKind!=HDL_MOVE) { + pH=new SdrHdl(aPnt,eKind); + pH->SetObj((SdrObject*)this); + pH->SetDrehWink(aGeo.nDrehWink); + } + return pH; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrTextObj::hasSpecialDrag() const +{ + return true; +} + +Rectangle SdrTextObj::ImpDragCalcRect(const SdrDragStat& rDrag) const +{ + Rectangle aTmpRect(aRect); + const SdrHdl* pHdl=rDrag.GetHdl(); + SdrHdlKind eHdl=pHdl==NULL ? HDL_MOVE : pHdl->GetKind(); + FASTBOOL bEcke=(eHdl==HDL_UPLFT || eHdl==HDL_UPRGT || eHdl==HDL_LWLFT || eHdl==HDL_LWRGT); + FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho(); + FASTBOOL bBigOrtho=bEcke && bOrtho && rDrag.GetView()->IsBigOrtho(); + Point aPos(rDrag.GetNow()); + // Unrotate: + if (aGeo.nDrehWink!=0) RotatePoint(aPos,aTmpRect.TopLeft(),-aGeo.nSin,aGeo.nCos); + // Unshear: + if (aGeo.nShearWink!=0) ShearPoint(aPos,aTmpRect.TopLeft(),-aGeo.nTan); + // + FASTBOOL bLft=(eHdl==HDL_UPLFT || eHdl==HDL_LEFT || eHdl==HDL_LWLFT); + FASTBOOL bRgt=(eHdl==HDL_UPRGT || eHdl==HDL_RIGHT || eHdl==HDL_LWRGT); + FASTBOOL bTop=(eHdl==HDL_UPRGT || eHdl==HDL_UPPER || eHdl==HDL_UPLFT); + FASTBOOL bBtm=(eHdl==HDL_LWRGT || eHdl==HDL_LOWER || eHdl==HDL_LWLFT); + if (bLft) aTmpRect.Left() =aPos.X(); + if (bRgt) aTmpRect.Right() =aPos.X(); + if (bTop) aTmpRect.Top() =aPos.Y(); + if (bBtm) aTmpRect.Bottom()=aPos.Y(); + if (bOrtho) { // Ortho + long nWdt0=aRect.Right() -aRect.Left(); + long nHgt0=aRect.Bottom()-aRect.Top(); + long nXMul=aTmpRect.Right() -aTmpRect.Left(); + long nYMul=aTmpRect.Bottom()-aTmpRect.Top(); + long nXDiv=nWdt0; + long nYDiv=nHgt0; + FASTBOOL bXNeg=(nXMul<0)!=(nXDiv<0); + FASTBOOL bYNeg=(nYMul<0)!=(nYDiv<0); + nXMul=Abs(nXMul); + nYMul=Abs(nYMul); + nXDiv=Abs(nXDiv); + nYDiv=Abs(nYDiv); + Fraction aXFact(nXMul,nXDiv); // Fractions zum kuerzen + Fraction aYFact(nYMul,nYDiv); // und zum vergleichen + nXMul=aXFact.GetNumerator(); + nYMul=aYFact.GetNumerator(); + nXDiv=aXFact.GetDenominator(); + nYDiv=aYFact.GetDenominator(); + if (bEcke) { // Eckpunkthandles + FASTBOOL bUseX=(aXFact<aYFact) != bBigOrtho; + if (bUseX) { + long nNeed=long(BigInt(nHgt0)*BigInt(nXMul)/BigInt(nXDiv)); + if (bYNeg) nNeed=-nNeed; + if (bTop) aTmpRect.Top()=aTmpRect.Bottom()-nNeed; + if (bBtm) aTmpRect.Bottom()=aTmpRect.Top()+nNeed; + } else { + long nNeed=long(BigInt(nWdt0)*BigInt(nYMul)/BigInt(nYDiv)); + if (bXNeg) nNeed=-nNeed; + if (bLft) aTmpRect.Left()=aTmpRect.Right()-nNeed; + if (bRgt) aTmpRect.Right()=aTmpRect.Left()+nNeed; + } + } else { // Scheitelpunkthandles + if ((bLft || bRgt) && nXDiv!=0) { + long nHgt0b=aRect.Bottom()-aRect.Top(); + long nNeed=long(BigInt(nHgt0b)*BigInt(nXMul)/BigInt(nXDiv)); + aTmpRect.Top()-=(nNeed-nHgt0b)/2; + aTmpRect.Bottom()=aTmpRect.Top()+nNeed; + } + if ((bTop || bBtm) && nYDiv!=0) { + long nWdt0b=aRect.Right()-aRect.Left(); + long nNeed=long(BigInt(nWdt0b)*BigInt(nYMul)/BigInt(nYDiv)); + aTmpRect.Left()-=(nNeed-nWdt0b)/2; + aTmpRect.Right()=aTmpRect.Left()+nNeed; + } + } + } + if (!ISA(SdrObjCustomShape)) // not justifying for CustomShapes to be able to detect if a shape has to be mirrored + ImpJustifyRect(aTmpRect); + return aTmpRect; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// drag + +bool SdrTextObj::applySpecialDrag(SdrDragStat& rDrag) +{ + Rectangle aNewRect(ImpDragCalcRect(rDrag)); + + if(aNewRect.TopLeft() != aRect.TopLeft() && (aGeo.nDrehWink || aGeo.nShearWink)) + { + Point aNewPos(aNewRect.TopLeft()); + + if(aGeo.nShearWink) + ShearPoint(aNewPos,aRect.TopLeft(),aGeo.nTan); + + if(aGeo.nDrehWink) + RotatePoint(aNewPos,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + + aNewRect.SetPos(aNewPos); + } + + if(aNewRect != aRect) + { + NbcSetLogicRect(aNewRect); + } + + return true; +} + +String SdrTextObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_DragRectResize,aStr); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Create + +FASTBOOL SdrTextObj::BegCreate(SdrDragStat& rStat) +{ + rStat.SetOrtho4Possible(); + Rectangle aRect1(rStat.GetStart(), rStat.GetNow()); + aRect1.Justify(); + rStat.SetActionRect(aRect1); + aRect = aRect1; + return TRUE; +} + +FASTBOOL SdrTextObj::MovCreate(SdrDragStat& rStat) +{ + Rectangle aRect1; + rStat.TakeCreateRect(aRect1); + ImpJustifyRect(aRect1); + rStat.SetActionRect(aRect1); + aRect=aRect1; // fuer ObjName + SetBoundRectDirty(); + bSnapRectDirty=TRUE; + if (HAS_BASE(SdrRectObj,this)) { + ((SdrRectObj*)this)->SetXPolyDirty(); + } + return TRUE; +} + +FASTBOOL SdrTextObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + rStat.TakeCreateRect(aRect); + ImpJustifyRect(aRect); + if (bTextFrame) { + if (IsAutoGrowHeight()) { + // MinTextHeight + long nHgt=aRect.GetHeight()-1; + if (nHgt==1) nHgt=0; + NbcSetMinTextFrameHeight(nHgt); + } + if (IsAutoGrowWidth()) { + // MinTextWidth + long nWdt=aRect.GetWidth()-1; + if (nWdt==1) nWdt=0; + NbcSetMinTextFrameWidth(nWdt); + } + // Textrahmen neu berechnen + NbcAdjustTextFrameWidthAndHeight(); + } + SetRectsDirty(); + if (HAS_BASE(SdrRectObj,this)) { + ((SdrRectObj*)this)->SetXPolyDirty(); + } + return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); +} + +void SdrTextObj::BrkCreate(SdrDragStat& /*rStat*/) +{ +} + +FASTBOOL SdrTextObj::BckCreate(SdrDragStat& /*rStat*/) +{ + return TRUE; +} + +basegfx::B2DPolyPolygon SdrTextObj::TakeCreatePoly(const SdrDragStat& rDrag) const +{ + Rectangle aRect1; + rDrag.TakeCreateRect(aRect1); + aRect1.Justify(); + + basegfx::B2DPolyPolygon aRetval; + const basegfx::B2DRange aRange(aRect1.Left(), aRect1.Top(), aRect1.Right(), aRect1.Bottom()); + aRetval.append(basegfx::tools::createPolygonFromRect(aRange)); + return aRetval; +} + +Pointer SdrTextObj::GetCreatePointer() const +{ + if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT); + return Pointer(POINTER_CROSS); +} + diff --git a/svx/source/svdraw/svdotxed.cxx b/svx/source/svdraw/svdotxed.cxx new file mode 100644 index 000000000000..c7715f37764c --- /dev/null +++ b/svx/source/svdraw/svdotxed.cxx @@ -0,0 +1,350 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdotext.hxx> +#include "svditext.hxx" +#include <svx/svdmodel.hxx> // fuer GetMaxObjSize +#include <svx/svdoutl.hxx> +#include <editeng/outliner.hxx> +#include <editeng/editstat.hxx> +#include <svl/itemset.hxx> +#include <editeng/eeitem.hxx> +#include <svx/sdtfchim.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ +// +// TextEdit +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrTextObj::HasTextEdit() const +{ + // lt. Anweisung von MB duerfen gelinkte Textobjekte nun doch + // geaendert werden (kein automatisches Reload) + return TRUE; +} + +sal_Bool SdrTextObj::BegTextEdit(SdrOutliner& rOutl) +{ + if (pEdtOutl!=NULL) return sal_False; // Textedit laeuft evtl. schon an einer anderen View! + pEdtOutl=&rOutl; + + // #101684# + mbInEditMode = TRUE; + + USHORT nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT; + if ( !IsOutlText() ) + nOutlinerMode = OUTLINERMODE_TEXTOBJECT; + rOutl.Init( nOutlinerMode ); + rOutl.SetRefDevice( pModel->GetRefDevice() ); + + SdrFitToSizeType eFit=GetFitToSize(); + FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); + FASTBOOL bContourFrame=IsContourTextFrame(); + ImpSetTextEditParams(); + + if (!bContourFrame) { + ULONG nStat=rOutl.GetControlWord(); + nStat|=EE_CNTRL_AUTOPAGESIZE; + if (bFitToSize) nStat|=EE_CNTRL_STRETCHING; else nStat&=~EE_CNTRL_STRETCHING; + rOutl.SetControlWord(nStat); + } + + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if(pOutlinerParaObject!=NULL) + { + rOutl.SetText(*GetOutlinerParaObject()); + rOutl.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); + } + + // ggf. Rahmenattribute am 1. (neuen) Absatz des Outliners setzen + if( !HasTextImpl( &rOutl ) ) + { + // Outliner has no text so we must set some + // empty text so the outliner initialise itself + rOutl.SetText( String(), rOutl.GetParagraph( 0 ) ); + + if(GetStyleSheet()) + rOutl.SetStyleSheet( 0, GetStyleSheet()); + + // Beim setzen der harten Attribute an den ersten Absatz muss + // der Parent pOutlAttr (=die Vorlage) temporaer entfernt + // werden, da sonst bei SetParaAttribs() auch alle in diesem + // Parent enthaltenen Items hart am Absatz attributiert werden. + // -> BugID 22467 + const SfxItemSet& rSet = GetObjectItemSet(); + SfxItemSet aFilteredSet(*rSet.GetPool(), EE_ITEMS_START, EE_ITEMS_END); + aFilteredSet.Put(rSet); + rOutl.SetParaAttribs(0, aFilteredSet); + } + if (bFitToSize) + { + Rectangle aAnchorRect; + Rectangle aTextRect; + TakeTextRect(rOutl, aTextRect, FALSE, + &aAnchorRect/* #97097# give TRUE here, not FALSE */); + Fraction aFitXKorreg(1,1); + ImpSetCharStretching(rOutl,aTextRect,aAnchorRect,aFitXKorreg); + } + + if(pOutlinerParaObject) + { + // #78476# also repaint when animated text is put to edit mode + // to not make appear the text double + // #111096# should now repaint automatically. + // BOOL bIsAnimated(pPlusData && pPlusData->pAnimator); + + if(aGeo.nDrehWink || IsFontwork() /*|| bIsAnimated*/) + { + // only repaint here, no real objectchange + +// ActionChanged(); + BroadcastObjectChange(); + } + } + + rOutl.UpdateFields(); + rOutl.ClearModifyFlag(); + + return sal_True; +} + +void SdrTextObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const +{ + SdrFitToSizeType eFit=GetFitToSize(); + FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); + Size aPaperMin,aPaperMax; + Rectangle aViewInit; + TakeTextAnchorRect(aViewInit); + if (aGeo.nDrehWink!=0) { + Point aCenter(aViewInit.Center()); + aCenter-=aViewInit.TopLeft(); + Point aCenter0(aCenter); + RotatePoint(aCenter,Point(),aGeo.nSin,aGeo.nCos); + aCenter-=aCenter0; + aViewInit.Move(aCenter.X(),aCenter.Y()); + } + Size aAnkSiz(aViewInit.GetSize()); + aAnkSiz.Width()--; aAnkSiz.Height()--; // weil GetSize() ein draufaddiert + Size aMaxSiz(1000000,1000000); + if (pModel!=NULL) { + Size aTmpSiz(pModel->GetMaxObjSize()); + if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); + if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); + } + + // #106879# + // Done earlier since used in else tree below + SdrTextHorzAdjust eHAdj(GetTextHorizontalAdjust()); + SdrTextVertAdjust eVAdj(GetTextVerticalAdjust()); + + if(IsTextFrame()) + { + long nMinWdt=GetMinTextFrameWidth(); + long nMinHgt=GetMinTextFrameHeight(); + long nMaxWdt=GetMaxTextFrameWidth(); + long nMaxHgt=GetMaxTextFrameHeight(); + if (nMinWdt<1) nMinWdt=1; + if (nMinHgt<1) nMinHgt=1; + if (!bFitToSize) { + if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width(); + if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height(); + if (!IsAutoGrowWidth() ) { nMaxWdt=aAnkSiz.Width(); nMinWdt=nMaxWdt; } + if (!IsAutoGrowHeight()) { nMaxHgt=aAnkSiz.Height(); nMinHgt=nMaxHgt; } + SdrTextAniKind eAniKind=GetTextAniKind(); + SdrTextAniDirection eAniDirection=GetTextAniDirection(); + + // #101684# + BOOL bInEditMode = IsInEditMode(); + + if (!bInEditMode && (eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE)) + { + // Grenzenlose Papiergroesse fuer Laufschrift + if (eAniDirection==SDRTEXTANI_LEFT || eAniDirection==SDRTEXTANI_RIGHT) nMaxWdt=1000000; + if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nMaxHgt=1000000; + } + aPaperMax.Width()=nMaxWdt; + aPaperMax.Height()=nMaxHgt; + } else { + aPaperMax=aMaxSiz; + } + aPaperMin.Width()=nMinWdt; + aPaperMin.Height()=nMinHgt; + } + else + { + // #106879# + // aPaperMin needs to be set to object's size if full width is activated + // for hor or ver writing respectively + if((SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting()) + || (SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())) + { + aPaperMin = aAnkSiz; + } + + aPaperMax=aMaxSiz; + } + + if (pViewMin!=NULL) { + *pViewMin=aViewInit; + + long nXFree=aAnkSiz.Width()-aPaperMin.Width(); + if (eHAdj==SDRTEXTHORZADJUST_LEFT) pViewMin->Right()-=nXFree; + else if (eHAdj==SDRTEXTHORZADJUST_RIGHT) pViewMin->Left()+=nXFree; + else { pViewMin->Left()+=nXFree/2; pViewMin->Right()=pViewMin->Left()+aPaperMin.Width(); } + + long nYFree=aAnkSiz.Height()-aPaperMin.Height(); + if (eVAdj==SDRTEXTVERTADJUST_TOP) pViewMin->Bottom()-=nYFree; + else if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) pViewMin->Top()+=nYFree; + else { pViewMin->Top()+=nYFree/2; pViewMin->Bottom()=pViewMin->Top()+aPaperMin.Height(); } + } + + // Die PaperSize soll in den meisten Faellen von selbst wachsen + // #89459# + if(IsVerticalWriting()) + aPaperMin.Width() = 0; + else + aPaperMin.Height() = 0; // #33102# + + if(eHAdj!=SDRTEXTHORZADJUST_BLOCK || bFitToSize) { + aPaperMin.Width()=0; + } + + // #103516# For complete ver adjust support, set paper min height to 0, here. + if(SDRTEXTVERTADJUST_BLOCK != eVAdj || bFitToSize) + { + aPaperMin.Height() = 0; + } + + if (pPaperMin!=NULL) *pPaperMin=aPaperMin; + if (pPaperMax!=NULL) *pPaperMax=aPaperMax; + if (pViewInit!=NULL) *pViewInit=aViewInit; +} + +void SdrTextObj::EndTextEdit(SdrOutliner& rOutl) +{ + if(rOutl.IsModified()) + { + OutlinerParaObject* pNewText = NULL; + + if(HasTextImpl( &rOutl ) ) + { + // Damit der grauen Feldhintergrund wieder verschwindet + rOutl.UpdateFields(); + + sal_uInt16 nParaAnz = static_cast< sal_uInt16 >( rOutl.GetParagraphCount() ); + pNewText = rOutl.CreateParaObject( 0, nParaAnz ); + } + + // need to end edit mode early since SetOutlinerParaObject already + // uses GetCurrentBoundRect() which needs to take the text into account + // to work correct + mbInEditMode = FALSE; + SetOutlinerParaObject(pNewText); + } + + pEdtOutl = NULL; + rOutl.Clear(); + UINT32 nStat = rOutl.GetControlWord(); + nStat &= ~EE_CNTRL_AUTOPAGESIZE; + rOutl.SetControlWord(nStat); + + // #101684# + mbInEditMode = FALSE; +} + +USHORT SdrTextObj::GetOutlinerViewAnchorMode() const +{ + SdrTextHorzAdjust eH=GetTextHorizontalAdjust(); + SdrTextVertAdjust eV=GetTextVerticalAdjust(); + EVAnchorMode eRet=ANCHOR_TOP_LEFT; + if (IsContourTextFrame()) return (USHORT)eRet; + if (eH==SDRTEXTHORZADJUST_LEFT) { + if (eV==SDRTEXTVERTADJUST_TOP) { + eRet=ANCHOR_TOP_LEFT; + } else if (eV==SDRTEXTVERTADJUST_BOTTOM) { + eRet=ANCHOR_BOTTOM_LEFT; + } else { + eRet=ANCHOR_VCENTER_LEFT; + } + } else if (eH==SDRTEXTHORZADJUST_RIGHT) { + if (eV==SDRTEXTVERTADJUST_TOP) { + eRet=ANCHOR_TOP_RIGHT; + } else if (eV==SDRTEXTVERTADJUST_BOTTOM) { + eRet=ANCHOR_BOTTOM_RIGHT; + } else { + eRet=ANCHOR_VCENTER_RIGHT; + } + } else { + if (eV==SDRTEXTVERTADJUST_TOP) { + eRet=ANCHOR_TOP_HCENTER; + } else if (eV==SDRTEXTVERTADJUST_BOTTOM) { + eRet=ANCHOR_BOTTOM_HCENTER; + } else { + eRet=ANCHOR_VCENTER_HCENTER; + } + } + return (USHORT)eRet; +} + +void SdrTextObj::ImpSetTextEditParams() const +{ + if (pEdtOutl!=NULL) { + FASTBOOL bUpdMerk=pEdtOutl->GetUpdateMode(); + if (bUpdMerk) pEdtOutl->SetUpdateMode(FALSE); + Size aPaperMin; + Size aPaperMax; + Rectangle aEditArea; + TakeTextEditArea(&aPaperMin,&aPaperMax,&aEditArea,NULL); + //SdrFitToSizeType eFit=GetFitToSize(); + //FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); + FASTBOOL bContourFrame=IsContourTextFrame(); + //EVAnchorMode eAM=(EVAnchorMode)GetOutlinerViewAnchorMode(); + //ULONG nViewAnz=pEdtOutl->GetViewCount(); + pEdtOutl->SetMinAutoPaperSize(aPaperMin); + pEdtOutl->SetMaxAutoPaperSize(aPaperMax); + pEdtOutl->SetPaperSize(Size()); + if (bContourFrame) { + Rectangle aAnchorRect; + TakeTextAnchorRect(aAnchorRect); + ImpSetContourPolygon(*pEdtOutl,aAnchorRect, TRUE); + } + if (bUpdMerk) pEdtOutl->SetUpdateMode(TRUE); + } +} + diff --git a/svx/source/svdraw/svdotxfl.cxx b/svx/source/svdraw/svdotxfl.cxx new file mode 100644 index 000000000000..fe21621c1b9a --- /dev/null +++ b/svx/source/svdraw/svdotxfl.cxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <editeng/eeitem.hxx> + +#include <editeng/measfld.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdfield.hxx> + +static BOOL bInit = FALSE; + +// Do not remove this, it is still used in src536a! +void SdrRegisterFieldClasses() +{ + if ( !bInit ) + { + SvxFieldItem::GetClassManager().SV_CLASS_REGISTER(SdrMeasureField); + SvxFieldItem::GetClassManager().SV_CLASS_REGISTER(SvxHeaderField); + SvxFieldItem::GetClassManager().SV_CLASS_REGISTER(SvxFooterField); + SvxFieldItem::GetClassManager().SV_CLASS_REGISTER(SvxDateTimeField); + bInit = TRUE; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////// */ + +FASTBOOL SdrTextObj::CalcFieldValue(const SvxFieldItem& /*rField*/, USHORT /*nPara*/, USHORT /*nPos*/, + FASTBOOL /*bEdit*/, Color*& /*rpTxtColor*/, Color*& /*rpFldColor*/, XubString& /*rRet*/) const +{ + return FALSE; +} + diff --git a/svx/source/svdraw/svdotxln.cxx b/svx/source/svdraw/svdotxln.cxx new file mode 100644 index 000000000000..7d176fbfe811 --- /dev/null +++ b/svx/source/svdraw/svdotxln.cxx @@ -0,0 +1,350 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/datetime.hxx> +#include <svx/svdotext.hxx> +#include "svditext.hxx" +#include <svx/svdmodel.hxx> +#include <editeng/editdata.hxx> +#include <sfx2/lnkbase.hxx> +#include <sfx2/linkmgr.hxx> +#include <tools/urlobj.hxx> +#include <svl/urihelper.hxx> + +// #90477# +#include <tools/tenccvt.hxx> + +#ifndef SVX_LIGHT +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@@@@ @@@@@@ @@@@@@ @@@@@@ @@ @@ @@@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@@@ @@ @@ @@ @@@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@@@@ @@ @@ @@ @@ @@@@@@ @@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@@@ @@ @@ @@ @@ @@@ @@ @@ +// @@@@ @@@@@ @@@@ @@ @@@@@@ @@ @@ @@ @@@@@ @@ @@ @@ @@ @@ +// +// ImpSdrObjTextLink zur Verbindung von SdrTextObj und LinkManager +// +// Einem solchen Link merke ich mir als SdrObjUserData am Objekt. Im Gegensatz +// zum Grafik-Link werden die ObjektDaten jedoch kopiert (fuer Paint, etc.). +// Die Information ob das Objekt ein Link ist besteht genau darin, dass dem +// Objekt ein entsprechender UserData-Record angehaengt ist oder nicht. +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImpSdrObjTextLink: public ::sfx2::SvBaseLink +{ + SdrTextObj* pSdrObj; + +public: + ImpSdrObjTextLink( SdrTextObj* pObj1 ) + : ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE ), + pSdrObj( pObj1 ) + {} + virtual ~ImpSdrObjTextLink(); + + virtual void Closed(); + virtual void DataChanged( const String& rMimeType, + const ::com::sun::star::uno::Any & rValue ); + + BOOL Connect() { return 0 != SvBaseLink::GetRealObject(); } +}; + +ImpSdrObjTextLink::~ImpSdrObjTextLink() +{ +} + +void ImpSdrObjTextLink::Closed() +{ + if (pSdrObj ) + { + // pLink des Objekts auf NULL setzen, da die Link-Instanz ja gerade destruiert wird. + ImpSdrObjTextLinkUserData* pData=pSdrObj->GetLinkUserData(); + if (pData!=NULL) pData->pLink=NULL; + pSdrObj->ReleaseTextLink(); + } + SvBaseLink::Closed(); +} + + +void ImpSdrObjTextLink::DataChanged( const String& /*rMimeType*/, + const ::com::sun::star::uno::Any & /*rValue */) +{ + FASTBOOL bForceReload=FALSE; + SdrModel* pModel = pSdrObj ? pSdrObj->GetModel() : 0; + sfx2::LinkManager* pLinkManager= pModel ? pModel->GetLinkManager() : 0; + if( pLinkManager ) + { + ImpSdrObjTextLinkUserData* pData=pSdrObj->GetLinkUserData(); + if( pData ) + { + String aFile; + String aFilter; + pLinkManager->GetDisplayNames( this, 0,&aFile, 0, &aFilter ); + + if( !pData->aFileName.Equals( aFile ) || + !pData->aFilterName.Equals( aFilter )) + { + pData->aFileName = aFile; + pData->aFilterName = aFilter; + pSdrObj->SetChanged(); + bForceReload = TRUE; + } + } + } + if (pSdrObj ) + pSdrObj->ReloadLinkedText( bForceReload ); +} +#endif // SVX_LIGHT + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@ @@ @@ @@ @@ @@ @@ @@ @@@@@ @@@@@@ @@@@@ @@@@@ @@@@ @@@@@@ @@@@ +// @@ @@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ @@ @@ @@@@@@ @@ @@@@@@ +// @@ @@ @@ @@@ @@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@@ @@ @@ @@ @@ @@ @@@@ @@@@@ @@@@@@ @@ @@ @@@@@ @@ @@ @@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(ImpSdrObjTextLinkUserData,SdrObjUserData); + +ImpSdrObjTextLinkUserData::ImpSdrObjTextLinkUserData(SdrTextObj* pObj1): + SdrObjUserData(SdrInventor,SDRUSERDATA_OBJTEXTLINK,0), + pObj(pObj1), + pLink(NULL), + eCharSet(RTL_TEXTENCODING_DONTKNOW) +{ +} + +ImpSdrObjTextLinkUserData::~ImpSdrObjTextLinkUserData() +{ +#ifndef SVX_LIGHT + delete pLink; +#endif +} + +SdrObjUserData* ImpSdrObjTextLinkUserData::Clone(SdrObject* pObj1) const +{ + ImpSdrObjTextLinkUserData* pData=new ImpSdrObjTextLinkUserData((SdrTextObj*)pObj1); + pData->aFileName =aFileName; + pData->aFilterName=aFilterName; + pData->aFileDate0 =aFileDate0; + pData->eCharSet =eCharSet; + pData->pLink=NULL; + return pData; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrTextObj::SetTextLink(const String& rFileName, const String& rFilterName, rtl_TextEncoding eCharSet) +{ + if(eCharSet == RTL_TEXTENCODING_DONTKNOW) + eCharSet = gsl_getSystemTextEncoding(); + + ImpSdrObjTextLinkUserData* pData=GetLinkUserData(); + if (pData!=NULL) { + ReleaseTextLink(); + } + pData=new ImpSdrObjTextLinkUserData(this); + pData->aFileName=rFileName; + pData->aFilterName=rFilterName; + pData->eCharSet=eCharSet; + InsertUserData(pData); + ImpLinkAnmeldung(); +} + +void SdrTextObj::ReleaseTextLink() +{ + ImpLinkAbmeldung(); + USHORT nAnz=GetUserDataCount(); + for (USHORT nNum=nAnz; nNum>0;) { + nNum--; + SdrObjUserData* pData=GetUserData(nNum); + if (pData->GetInventor()==SdrInventor && pData->GetId()==SDRUSERDATA_OBJTEXTLINK) { + DeleteUserData(nNum); + } + } +} + +FASTBOOL SdrTextObj::ReloadLinkedText( FASTBOOL bForceLoad) +{ + ImpSdrObjTextLinkUserData* pData = GetLinkUserData(); + FASTBOOL bRet = TRUE; + + if( pData ) + { + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + DateTime aFileDT; + BOOL bExists = FALSE, bLoad = FALSE; + + if( pBroker ) + { + bExists = TRUE; + + try + { + INetURLObject aURL( pData->aFileName ); + DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" ); + + ::ucbhelper::Content aCnt( aURL.GetMainURL( INetURLObject::NO_DECODE ), ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); + ::com::sun::star::uno::Any aAny( aCnt.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ) ) ); + ::com::sun::star::util::DateTime aDateTime; + + aAny >>= aDateTime; + ::utl::typeConvert( aDateTime, aFileDT ); + } + catch( ... ) + { + bExists = FALSE; + } + } + + if( bExists ) + { + if( bForceLoad ) + bLoad = TRUE; + else + bLoad = ( aFileDT > pData->aFileDate0 ); + + if( bLoad ) + { + bRet = LoadText( pData->aFileName, pData->aFilterName, pData->eCharSet ); + } + + pData->aFileDate0 = aFileDT; + } + } + + return bRet; +} + +FASTBOOL SdrTextObj::LoadText(const String& rFileName, const String& /*rFilterName*/, rtl_TextEncoding eCharSet) +{ + INetURLObject aFileURL( rFileName ); + BOOL bRet = FALSE; + + if( aFileURL.GetProtocol() == INET_PROT_NOT_VALID ) + { + String aFileURLStr; + + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( rFileName, aFileURLStr ) ) + aFileURL = INetURLObject( aFileURLStr ); + else + aFileURL.SetSmartURL( rFileName ); + } + + DBG_ASSERT( aFileURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" ); + + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aFileURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ ); + + if( pIStm ) + { + // #90477# pIStm->SetStreamCharSet( eCharSet ); + pIStm->SetStreamCharSet(GetSOLoadTextEncoding(eCharSet, (sal_uInt16)pIStm->GetVersion())); + + char cRTF[5]; + cRTF[4] = 0; + pIStm->Read(cRTF, 5); + + BOOL bRTF = cRTF[0] == '{' && cRTF[1] == '\\' && cRTF[2] == 'r' && cRTF[3] == 't' && cRTF[4] == 'f'; + + pIStm->Seek(0); + + if( !pIStm->GetError() ) + { + SetText( *pIStm, aFileURL.GetMainURL( INetURLObject::NO_DECODE ), sal::static_int_cast< USHORT >( bRTF ? EE_FORMAT_RTF : EE_FORMAT_TEXT ) ); + bRet = TRUE; + } + + delete pIStm; + } + + return bRet; +} + +ImpSdrObjTextLinkUserData* SdrTextObj::GetLinkUserData() const +{ + ImpSdrObjTextLinkUserData* pData=NULL; + USHORT nAnz=GetUserDataCount(); + for (USHORT nNum=nAnz; nNum>0 && pData==NULL;) { + nNum--; + pData=(ImpSdrObjTextLinkUserData*)GetUserData(nNum); + if (pData->GetInventor()!=SdrInventor || pData->GetId()!=SDRUSERDATA_OBJTEXTLINK) { + pData=NULL; + } + } + return pData; +} + +void SdrTextObj::ImpLinkAnmeldung() +{ + ImpSdrObjTextLinkUserData* pData=GetLinkUserData(); + sfx2::LinkManager* pLinkManager=pModel!=NULL ? pModel->GetLinkManager() : NULL; + if (pLinkManager!=NULL && pData!=NULL && pData->pLink==NULL) { // Nicht 2x Anmelden + pData->pLink=new ImpSdrObjTextLink(this); +#ifdef GCC + pLinkManager->InsertFileLink(*pData->pLink,OBJECT_CLIENT_FILE,pData->aFileName, + pData->aFilterName.Len() ? + &pData->aFilterName : (const String *)NULL, + (const String *)NULL); +#else + pLinkManager->InsertFileLink(*pData->pLink,OBJECT_CLIENT_FILE,pData->aFileName, + pData->aFilterName.Len() ? &pData->aFilterName : NULL,NULL); +#endif + pData->pLink->Connect(); + } +} + +void SdrTextObj::ImpLinkAbmeldung() +{ + ImpSdrObjTextLinkUserData* pData=GetLinkUserData(); + sfx2::LinkManager* pLinkManager=pModel!=NULL ? pModel->GetLinkManager() : NULL; + if (pLinkManager!=NULL && pData!=NULL && pData->pLink!=NULL) { // Nicht 2x Abmelden + // Bei Remove wird *pLink implizit deleted + pLinkManager->Remove( pData->pLink ); + pData->pLink=NULL; + } +} + diff --git a/svx/source/svdraw/svdotxtr.cxx b/svx/source/svdraw/svdotxtr.cxx new file mode 100644 index 000000000000..bd1564ab3f4e --- /dev/null +++ b/svx/source/svdraw/svdotxtr.cxx @@ -0,0 +1,558 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdotext.hxx> +#include "svditext.hxx" +#include <svx/svdtrans.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdpage.hxx> // fuer Convert +#include <svx/svdmodel.hxx> // fuer Convert +#include <editeng/outliner.hxx> +#include <svx/sdr/properties/itemsettools.hxx> +#include <svx/sdr/properties/properties.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <svl/itemset.hxx> +#include <svditer.hxx> +#include <drawinglayer/processor2d/textaspolygonextractor2d.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/xflclit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnwtit.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ +// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ +// +// Transformationen +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrTextObj::NbcSetSnapRect(const Rectangle& rRect) +{ + if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) { + Rectangle aSR0(GetSnapRect()); + long nWdt0=aSR0.Right()-aSR0.Left(); + long nHgt0=aSR0.Bottom()-aSR0.Top(); + long nWdt1=rRect.Right()-rRect.Left(); + long nHgt1=rRect.Bottom()-rRect.Top(); + SdrTextObj::NbcResize(maSnapRect.TopLeft(),Fraction(nWdt1,nWdt0),Fraction(nHgt1,nHgt0)); + SdrTextObj::NbcMove(Size(rRect.Left()-aSR0.Left(),rRect.Top()-aSR0.Top())); + } else { + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + long nTWdt0=aRect.GetWidth ()-1-nHDist; if (nTWdt0<0) nTWdt0=0; + long nTHgt0=aRect.GetHeight()-1-nVDist; if (nTHgt0<0) nTHgt0=0; + long nTWdt1=rRect.GetWidth ()-1-nHDist; if (nTWdt1<0) nTWdt1=0; + long nTHgt1=rRect.GetHeight()-1-nVDist; if (nTHgt1<0) nTHgt1=0; + aRect=rRect; + ImpJustifyRect(aRect); + if (bTextFrame && (pModel==NULL || !pModel->IsPasteResize())) { // #51139# + if (nTWdt0!=nTWdt1 && IsAutoGrowWidth() ) NbcSetMinTextFrameWidth(nTWdt1); + if (nTHgt0!=nTHgt1 && IsAutoGrowHeight()) NbcSetMinTextFrameHeight(nTHgt1); + if (GetFitToSize()==SDRTEXTFIT_RESIZEATTR) { + NbcResizeTextAttributes(Fraction(nTWdt1,nTWdt0),Fraction(nTHgt1,nTHgt0)); + } + NbcAdjustTextFrameWidthAndHeight(); + } + ImpCheckShear(); + SetRectsDirty(); + } +} + +const Rectangle& SdrTextObj::GetLogicRect() const +{ + return aRect; +} + +void SdrTextObj::NbcSetLogicRect(const Rectangle& rRect) +{ + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + long nTWdt0=aRect.GetWidth ()-1-nHDist; if (nTWdt0<0) nTWdt0=0; + long nTHgt0=aRect.GetHeight()-1-nVDist; if (nTHgt0<0) nTHgt0=0; + long nTWdt1=rRect.GetWidth ()-1-nHDist; if (nTWdt1<0) nTWdt1=0; + long nTHgt1=rRect.GetHeight()-1-nVDist; if (nTHgt1<0) nTHgt1=0; + aRect=rRect; + ImpJustifyRect(aRect); + if (bTextFrame) { + if (nTWdt0!=nTWdt1 && IsAutoGrowWidth() ) NbcSetMinTextFrameWidth(nTWdt1); + if (nTHgt0!=nTHgt1 && IsAutoGrowHeight()) NbcSetMinTextFrameHeight(nTHgt1); + if (GetFitToSize()==SDRTEXTFIT_RESIZEATTR) { + NbcResizeTextAttributes(Fraction(nTWdt1,nTWdt0),Fraction(nTHgt1,nTHgt0)); + } + NbcAdjustTextFrameWidthAndHeight(); + } + SetRectsDirty(); +} + +long SdrTextObj::GetRotateAngle() const +{ + return aGeo.nDrehWink; +} + +long SdrTextObj::GetShearAngle(FASTBOOL /*bVertical*/) const +{ + return aGeo.nShearWink; +} + +void SdrTextObj::NbcMove(const Size& rSiz) +{ + MoveRect(aRect,rSiz); + MoveRect(aOutRect,rSiz); + MoveRect(maSnapRect,rSiz); + SetRectsDirty(sal_True); +} + +void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + FASTBOOL bNoShearMerk=aGeo.nShearWink==0; + FASTBOOL bRota90Merk=bNoShearMerk && aGeo.nDrehWink % 9000 ==0; + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + long nTWdt0=aRect.GetWidth ()-1-nHDist; if (nTWdt0<0) nTWdt0=0; + long nTHgt0=aRect.GetHeight()-1-nVDist; if (nTHgt0<0) nTHgt0=0; + FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0); + FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0); + if (bXMirr || bYMirr) { + Point aRef1(GetSnapRect().Center()); + if (bXMirr) { + Point aRef2(aRef1); + aRef2.Y()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + if (bYMirr) { + Point aRef2(aRef1); + aRef2.X()++; + NbcMirrorGluePoints(aRef1,aRef2); + } + } + + if (aGeo.nDrehWink==0 && aGeo.nShearWink==0) { + ResizeRect(aRect,rRef,xFact,yFact); + if (bYMirr) { + aRect.Justify(); + aRect.Move(aRect.Right()-aRect.Left(),aRect.Bottom()-aRect.Top()); + aGeo.nDrehWink=18000; + aGeo.RecalcSinCos(); + } + } + else + { + // #100663# aRect is NOT initialized for lines (polgon objects with two + // exceptionally handled points). Thus, after this call the text rotaion is + // gone. This error must be present since day one of this old drawing layer. + // It's astonishing that noone discovered it earlier. + // Polygon aPol(Rect2Poly(aRect,aGeo)); + // Polygon aPol(Rect2Poly(GetSnapRect(), aGeo)); + + // #101412# go back to old method, side effects are impossible + // to calculate. + Polygon aPol(Rect2Poly(aRect,aGeo)); + + for(sal_uInt16 a(0); a < aPol.GetSize(); a++) + { + ResizePoint(aPol[a], rRef, xFact, yFact); + } + + if(bXMirr != bYMirr) + { + // Polygon wenden und etwas schieben + Polygon aPol0(aPol); + + aPol[0] = aPol0[1]; + aPol[1] = aPol0[0]; + aPol[2] = aPol0[3]; + aPol[3] = aPol0[2]; + aPol[4] = aPol0[1]; + } + + Poly2Rect(aPol, aRect, aGeo); + } + + if (bRota90Merk) { + FASTBOOL bRota90=aGeo.nDrehWink % 9000 ==0; + if (!bRota90) { // Scheinbar Rundungsfehler: Korregieren + long a=NormAngle360(aGeo.nDrehWink); + if (a<4500) a=0; + else if (a<13500) a=9000; + else if (a<22500) a=18000; + else if (a<31500) a=27000; + else a=0; + aGeo.nDrehWink=a; + aGeo.RecalcSinCos(); + } + if (bNoShearMerk!=(aGeo.nShearWink==0)) { // Shear ggf. korregieren wg. Rundungsfehler + aGeo.nShearWink=0; + aGeo.RecalcTan(); + } + } + + ImpJustifyRect(aRect); + long nTWdt1=aRect.GetWidth ()-1-nHDist; if (nTWdt1<0) nTWdt1=0; + long nTHgt1=aRect.GetHeight()-1-nVDist; if (nTHgt1<0) nTHgt1=0; + if (bTextFrame && (pModel==NULL || !pModel->IsPasteResize())) { // #51139# + if (nTWdt0!=nTWdt1 && IsAutoGrowWidth() ) NbcSetMinTextFrameWidth(nTWdt1); + if (nTHgt0!=nTHgt1 && IsAutoGrowHeight()) NbcSetMinTextFrameHeight(nTHgt1); + if (GetFitToSize()==SDRTEXTFIT_RESIZEATTR) { + NbcResizeTextAttributes(Fraction(nTWdt1,nTWdt0),Fraction(nTHgt1,nTHgt0)); + } + NbcAdjustTextFrameWidthAndHeight(); + } + ImpCheckShear(); + SetRectsDirty(); +} + +void SdrTextObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + SetGlueReallyAbsolute(TRUE); + long dx=aRect.Right()-aRect.Left(); + long dy=aRect.Bottom()-aRect.Top(); + Point aP(aRect.TopLeft()); + RotatePoint(aP,rRef,sn,cs); + aRect.Left()=aP.X(); + aRect.Top()=aP.Y(); + aRect.Right()=aRect.Left()+dx; + aRect.Bottom()=aRect.Top()+dy; + if (aGeo.nDrehWink==0) { + aGeo.nDrehWink=NormAngle360(nWink); + aGeo.nSin=sn; + aGeo.nCos=cs; + } else { + aGeo.nDrehWink=NormAngle360(aGeo.nDrehWink+nWink); + aGeo.RecalcSinCos(); + } + SetRectsDirty(); + NbcRotateGluePoints(rRef,nWink,sn,cs); + SetGlueReallyAbsolute(FALSE); +} + +void SdrTextObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + SetGlueReallyAbsolute(TRUE); + + // #75889# when this is a SdrPathObj aRect maybe not initialized + Polygon aPol(Rect2Poly(aRect.IsEmpty() ? GetSnapRect() : aRect, aGeo)); + + USHORT nPointCount=aPol.GetSize(); + for (USHORT i=0; i<nPointCount; i++) { + ShearPoint(aPol[i],rRef,tn,bVShear); + } + Poly2Rect(aPol,aRect,aGeo); + ImpJustifyRect(aRect); + if (bTextFrame) { + NbcAdjustTextFrameWidthAndHeight(); + } + ImpCheckShear(); + SetRectsDirty(); + NbcShearGluePoints(rRef,nWink,tn,bVShear); + SetGlueReallyAbsolute(FALSE); +} + +void SdrTextObj::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + SetGlueReallyAbsolute(TRUE); + FASTBOOL bNoShearMerk=aGeo.nShearWink==0; + FASTBOOL bRota90Merk=FALSE; + if (bNoShearMerk && + (rRef1.X()==rRef2.X() || rRef1.Y()==rRef2.Y() || + Abs(rRef1.X()-rRef2.X())==Abs(rRef1.Y()-rRef2.Y()))) { + bRota90Merk=aGeo.nDrehWink % 9000 ==0; + } + Polygon aPol(Rect2Poly(aRect,aGeo)); + USHORT i; + USHORT nPntAnz=aPol.GetSize(); + for (i=0; i<nPntAnz; i++) { + MirrorPoint(aPol[i],rRef1,rRef2); + } + // Polygon wenden und etwas schieben + Polygon aPol0(aPol); + aPol[0]=aPol0[1]; + aPol[1]=aPol0[0]; + aPol[2]=aPol0[3]; + aPol[3]=aPol0[2]; + aPol[4]=aPol0[1]; + Poly2Rect(aPol,aRect,aGeo); + + if (bRota90Merk) { + FASTBOOL bRota90=aGeo.nDrehWink % 9000 ==0; + if (bRota90Merk && !bRota90) { // Scheinbar Rundungsfehler: Korregieren + long a=NormAngle360(aGeo.nDrehWink); + if (a<4500) a=0; + else if (a<13500) a=9000; + else if (a<22500) a=18000; + else if (a<31500) a=27000; + else a=0; + aGeo.nDrehWink=a; + aGeo.RecalcSinCos(); + } + } + if (bNoShearMerk!=(aGeo.nShearWink==0)) { // Shear ggf. korregieren wg. Rundungsfehler + aGeo.nShearWink=0; + aGeo.RecalcTan(); + } + + ImpJustifyRect(aRect); + if (bTextFrame) { + NbcAdjustTextFrameWidthAndHeight(); + } + ImpCheckShear(); + SetRectsDirty(); + NbcMirrorGluePoints(rRef1,rRef2); + SetGlueReallyAbsolute(FALSE); +} + +////////////////////////////////////////////////////////////////////////////// + +SdrObject* SdrTextObj::ImpConvertContainedTextToSdrPathObjs(bool bToPoly) const +{ + SdrObject* pRetval = 0; + + if(!ImpCanConvTextToCurve()) + { + // suppress HelpTexts from PresObj's + return 0; + } + + // get primitives + const drawinglayer::primitive2d::Primitive2DSequence xSequence(GetViewContact().getViewIndependentPrimitive2DSequence()); + + if(xSequence.hasElements()) + { + // create an extractor with neutral ViewInformation + const drawinglayer::geometry::ViewInformation2D aViewInformation2D(0); + drawinglayer::processor2d::TextAsPolygonExtractor2D aExtractor(aViewInformation2D); + + // extract text as polygons + aExtractor.process(xSequence); + + // get results + const drawinglayer::processor2d::TextAsPolygonDataNodeVector& rResult = aExtractor.getTarget(); + const sal_uInt32 nResultCount(rResult.size()); + + if(nResultCount) + { + // prepare own target + SdrObjGroup* pGroup = new SdrObjGroup(); + SdrObjList* pObjectList = pGroup->GetSubList(); + + // process results + for(sal_uInt32 a(0); a < nResultCount; a++) + { + const drawinglayer::processor2d::TextAsPolygonDataNode& rCandidate = rResult[a]; + basegfx::B2DPolyPolygon aPolyPolygon(rCandidate.getB2DPolyPolygon()); + + if(aPolyPolygon.count()) + { + // take care of wanted polygon type + if(bToPoly) + { + if(aPolyPolygon.areControlPointsUsed()) + { + aPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(aPolyPolygon); + } + } + else + { + if(!aPolyPolygon.areControlPointsUsed()) + { + aPolyPolygon = basegfx::tools::expandToCurve(aPolyPolygon); + } + } + + // create ItemSet with object attributes + SfxItemSet aAttributeSet(GetObjectItemSet()); + SdrPathObj* pPathObj = 0; + + // always clear objectshadow; this is included in the extraction + aAttributeSet.Put(SdrShadowItem(false)); + + if(rCandidate.getIsFilled()) + { + // set needed items + aAttributeSet.Put(XFillColorItem(String(), Color(rCandidate.getBColor()))); + aAttributeSet.Put(XLineStyleItem(XLINE_NONE)); + aAttributeSet.Put(XFillStyleItem(XFILL_SOLID)); + + // create filled SdrPathObj + pPathObj = new SdrPathObj(OBJ_PATHFILL, aPolyPolygon); + } + else + { + // set needed items + aAttributeSet.Put(XLineColorItem(String(), Color(rCandidate.getBColor()))); + aAttributeSet.Put(XLineStyleItem(XLINE_SOLID)); + aAttributeSet.Put(XLineWidthItem(0)); + aAttributeSet.Put(XFillStyleItem(XFILL_NONE)); + + // create line SdrPathObj + pPathObj = new SdrPathObj(OBJ_PATHLINE, aPolyPolygon); + } + + // copy basic information from original + pPathObj->ImpSetAnchorPos(GetAnchorPos()); + pPathObj->NbcSetLayer(GetLayer()); + + if(GetModel()) + { + pPathObj->SetModel(GetModel()); + pPathObj->NbcSetStyleSheet(GetStyleSheet(), true); + } + + // apply prepared ItemSet and add to target + pPathObj->SetMergedItemSet(aAttributeSet); + pObjectList->InsertObject(pPathObj); + } + } + + // postprocess; if no result and/or only one object, simplify + if(!pObjectList->GetObjCount()) + { + delete pGroup; + } + else if(1 == pObjectList->GetObjCount()) + { + pRetval = pObjectList->RemoveObject(0); + delete pGroup; + } + else + { + pRetval = pGroup; + } + } + } + + return pRetval; +} + +////////////////////////////////////////////////////////////////////////////// + +SdrObject* SdrTextObj::DoConvertToPolyObj(BOOL bBezier) const +{ + return ImpConvertContainedTextToSdrPathObjs(!bBezier); +} + +bool SdrTextObj::ImpCanConvTextToCurve() const +{ + return !IsOutlText(); +} + +SdrObject* SdrTextObj::ImpConvertMakeObj(const basegfx::B2DPolyPolygon& rPolyPolygon, sal_Bool bClosed, sal_Bool bBezier, sal_Bool bNoSetAttr) const +{ + SdrObjKind ePathKind = bClosed ? OBJ_PATHFILL : OBJ_PATHLINE; + basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPolygon); + + // #i37011# + if(!bBezier) + { + aB2DPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(aB2DPolyPolygon); + ePathKind = bClosed ? OBJ_POLY : OBJ_PLIN; + } + + SdrPathObj* pPathObj = new SdrPathObj(ePathKind, aB2DPolyPolygon); + + if(bBezier) + { + // create bezier curves + pPathObj->SetPathPoly(basegfx::tools::expandToCurve(pPathObj->GetPathPoly())); + } + + if(pPathObj) + { + pPathObj->ImpSetAnchorPos(aAnchor); + pPathObj->NbcSetLayer(SdrLayerID(GetLayer())); + + if(pModel) + { + pPathObj->SetModel(pModel); + + if(!bNoSetAttr) + { + sdr::properties::ItemChangeBroadcaster aC(*pPathObj); + + pPathObj->ClearMergedItem(); + pPathObj->SetMergedItemSet(GetObjectItemSet()); + pPathObj->GetProperties().BroadcastItemChange(aC); + pPathObj->NbcSetStyleSheet(GetStyleSheet(), sal_True); + } + } + } + + return pPathObj; +} + +SdrObject* SdrTextObj::ImpConvertAddText(SdrObject* pObj, FASTBOOL bBezier) const +{ + if(!ImpCanConvTextToCurve()) + { + return pObj; + } + + SdrObject* pText = ImpConvertContainedTextToSdrPathObjs(!bBezier); + + if(!pText) + { + return pObj; + } + + if(!pObj) + { + return pText; + } + + if(pText->IsGroupObject()) + { + // is already group object, add partial shape in front + SdrObjList* pOL=pText->GetSubList(); + pOL->InsertObject(pObj,0); + + return pText; + } + else + { + // not yet a group, create one and add partial and new shapes + SdrObjGroup* pGrp=new SdrObjGroup; + SdrObjList* pOL=pGrp->GetSubList(); + pOL->InsertObject(pObj); + pOL->InsertObject(pText); + + return pGrp; + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdouno.cxx b/svx/source/svdraw/svdouno.cxx new file mode 100644 index 000000000000..b98e5ba5c1c6 --- /dev/null +++ b/svx/source/svdraw/svdouno.cxx @@ -0,0 +1,665 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/sdr/contact/viewcontactofunocontrol.hxx> +#include <svx/sdr/contact/viewobjectcontactofunocontrol.hxx> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/types.hxx> +#include <vcl/pdfextoutdevdata.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdmodel.hxx> +#include "svdglob.hxx" // Stringcache +#include "svdstr.hrc" // Objektname +#include <svx/svdetc.hxx> +#include <svx/svdview.hxx> +#include <svx/svdorect.hxx> +#include "svdviter.hxx" +#include <rtl/ref.hxx> +#include <set> +#include <memory> +#include <svx/sdrpagewindow.hxx> +#include <sdrpaintwindow.hxx> +#include <tools/diagnose_ex.h> +#include <svx/svdograf.hxx> + +using namespace ::com::sun::star; +using namespace ::sdr::contact; + +//************************************************************ +// Defines +//************************************************************ + +//************************************************************ +// Hilfsklasse SdrControlEventListenerImpl +//************************************************************ +#include <com/sun/star/lang/XEventListener.hpp> + +#include <cppuhelper/implbase1.hxx> + +// ============================================================================= +class SdrControlEventListenerImpl : public ::cppu::WeakImplHelper1< ::com::sun::star::lang::XEventListener > +{ +protected: + SdrUnoObj* pObj; + +public: + SdrControlEventListenerImpl(SdrUnoObj* _pObj) + : pObj(_pObj) + {} + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + void StopListening(const uno::Reference< lang::XComponent >& xComp); + void StartListening(const uno::Reference< lang::XComponent >& xComp); +}; + +// XEventListener +void SAL_CALL SdrControlEventListenerImpl::disposing( const ::com::sun::star::lang::EventObject& /*Source*/) + throw(::com::sun::star::uno::RuntimeException) +{ + if (pObj) + { + pObj->xUnoControlModel = NULL; + } +} + +void SdrControlEventListenerImpl::StopListening(const uno::Reference< lang::XComponent >& xComp) +{ + if (xComp.is()) + xComp->removeEventListener(this); +} + +void SdrControlEventListenerImpl::StartListening(const uno::Reference< lang::XComponent >& xComp) +{ + if (xComp.is()) + xComp->addEventListener(this); +} + +// ============================================================================= +struct SAL_DLLPRIVATE SdrUnoObjDataHolder +{ + mutable ::rtl::Reference< SdrControlEventListenerImpl > + pEventListener; +}; + +// ============================================================================= +namespace +{ + void lcl_ensureControlVisibility( SdrView* _pView, const SdrUnoObj* _pObject, bool _bVisible ) + { + OSL_PRECOND( _pObject, "lcl_ensureControlVisibility: no object -> no survival!" ); + + SdrPageView* pPageView = _pView ? _pView->GetSdrPageView() : NULL; + DBG_ASSERT( pPageView, "lcl_ensureControlVisibility: no view found!" ); + if ( !pPageView ) + return; + + ViewContact& rUnoControlContact( _pObject->GetViewContact() ); + + for ( sal_uInt32 i = 0; i < pPageView->PageWindowCount(); ++i ) + { + const SdrPageWindow* pPageWindow = pPageView->GetPageWindow( i ); + DBG_ASSERT( pPageWindow, "lcl_ensureControlVisibility: invalid PageViewWindow!" ); + if ( !pPageWindow ) + continue; + + if ( !pPageWindow->HasObjectContact() ) + continue; + + ObjectContact& rPageViewContact( pPageWindow->GetObjectContact() ); + const ViewObjectContact& rViewObjectContact( rUnoControlContact.GetViewObjectContact( rPageViewContact ) ); + const ViewObjectContactOfUnoControl* pUnoControlContact = dynamic_cast< const ViewObjectContactOfUnoControl* >( &rViewObjectContact ); + DBG_ASSERT( pUnoControlContact, "lcl_ensureControlVisibility: wrong ViewObjectContact type!" ); + if ( !pUnoControlContact ) + continue; + + pUnoControlContact->ensureControlVisibility( _bVisible ); + } + } +} + +//************************************************************ +// SdrUnoObj +//************************************************************ + +TYPEINIT1(SdrUnoObj, SdrRectObj); + +SdrUnoObj::SdrUnoObj(const String& rModelName, BOOL _bOwnUnoControlModel) +: m_pImpl( new SdrUnoObjDataHolder ), + bOwnUnoControlModel( _bOwnUnoControlModel ) +{ + bIsUnoObj = TRUE; + + m_pImpl->pEventListener = new SdrControlEventListenerImpl(this); + + // nur ein owner darf eigenstaendig erzeugen + if (rModelName.Len()) + CreateUnoControlModel(rModelName); +} + +SdrUnoObj::SdrUnoObj(const String& rModelName, + const uno::Reference< lang::XMultiServiceFactory >& rxSFac, + BOOL _bOwnUnoControlModel) +: m_pImpl( new SdrUnoObjDataHolder ), + bOwnUnoControlModel( _bOwnUnoControlModel ) +{ + bIsUnoObj = TRUE; + + m_pImpl->pEventListener = new SdrControlEventListenerImpl(this); + + // nur ein owner darf eigenstaendig erzeugen + if (rModelName.Len()) + CreateUnoControlModel(rModelName,rxSFac); +} + +SdrUnoObj::~SdrUnoObj() +{ + try + { + // clean up the control model + uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY); + if (xComp.is()) + { + // is the control model owned by it's environment? + uno::Reference< container::XChild > xContent(xUnoControlModel, uno::UNO_QUERY); + if (xContent.is() && !xContent->getParent().is()) + xComp->dispose(); + else + m_pImpl->pEventListener->StopListening(xComp); + } + } + catch( const uno::Exception& ) + { + OSL_ENSURE( sal_False, "SdrUnoObj::~SdrUnoObj: caught an exception!" ); + } + delete m_pImpl; +} + +void SdrUnoObj::SetModel(SdrModel* pNewModel) +{ + SdrRectObj::SetModel(pNewModel); +} + +void SdrUnoObj::SetPage(SdrPage* pNewPage) +{ + SdrRectObj::SetPage(pNewPage); +} + +void SdrUnoObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bRotateFreeAllowed = FALSE; + rInfo.bRotate90Allowed = FALSE; + rInfo.bMirrorFreeAllowed = FALSE; + rInfo.bMirror45Allowed = FALSE; + rInfo.bMirror90Allowed = FALSE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed = FALSE; + rInfo.bEdgeRadiusAllowed = FALSE; + rInfo.bNoOrthoDesired = FALSE; + rInfo.bCanConvToPath = FALSE; + rInfo.bCanConvToPoly = FALSE; + rInfo.bCanConvToPathLineToArea = FALSE; + rInfo.bCanConvToPolyLineToArea = FALSE; + rInfo.bCanConvToContour = FALSE; +} + +UINT16 SdrUnoObj::GetObjIdentifier() const +{ + return UINT16(OBJ_UNO); +} + +void SdrUnoObj::SetContextWritingMode( const sal_Int16 _nContextWritingMode ) +{ + try + { + uno::Reference< beans::XPropertySet > xModelProperties( GetUnoControlModel(), uno::UNO_QUERY_THROW ); + xModelProperties->setPropertyValue( + ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "ContextWritingMode" ) ), + uno::makeAny( _nContextWritingMode ) + ); + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ---------------------------------------------------------------------------- +namespace +{ + /** helper class to restore graphics at <awt::XView> object after <SdrUnoObj::Paint> + + OD 08.05.2003 #109432# + Restoration of graphics necessary to assure that paint on a window + + @author OD + */ + class RestoreXViewGraphics + { + private: + uno::Reference< awt::XView > m_rXView; + uno::Reference< awt::XGraphics > m_rXGraphics; + + public: + RestoreXViewGraphics( const uno::Reference< awt::XView >& _rXView ) + { + m_rXView = _rXView; + m_rXGraphics = m_rXView->getGraphics(); + } + ~RestoreXViewGraphics() + { + m_rXView->setGraphics( m_rXGraphics ); + } + }; +} + +void SdrUnoObj::TakeObjNameSingul(XubString& rName) const +{ + rName = ImpGetResStr(STR_ObjNameSingulUno); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrUnoObj::TakeObjNamePlural(XubString& rName) const +{ + rName = ImpGetResStr(STR_ObjNamePluralUno); +} + +void SdrUnoObj::operator = (const SdrObject& rObj) +{ + SdrRectObj::operator = (rObj); + + // release the reference to the current control model + SetUnoControlModel(uno::Reference< awt::XControlModel >()); + + aUnoControlModelTypeName = ((SdrUnoObj&) rObj).aUnoControlModelTypeName; + aUnoControlTypeName = ((SdrUnoObj&) rObj).aUnoControlTypeName; + + // copy the uno control model + uno::Reference< awt::XControlModel > xCtrl( ((SdrUnoObj&) rObj).GetUnoControlModel(), uno::UNO_QUERY ); + uno::Reference< util::XCloneable > xClone( xCtrl, uno::UNO_QUERY ); + + if ( xClone.is() ) + { + // copy the model by cloning + uno::Reference< awt::XControlModel > xNewModel( xClone->createClone(), uno::UNO_QUERY ); + DBG_ASSERT( xNewModel.is(), "SdrUnoObj::operator =, no control model!"); + xUnoControlModel = xNewModel; + } + else + { + // copy the model by streaming + uno::Reference< io::XPersistObject > xObj( xCtrl, uno::UNO_QUERY ); + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + + if ( xObj.is() && xFactory.is() ) + { + // creating a pipe + uno::Reference< io::XOutputStream > xOutPipe(xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.io.Pipe")), uno::UNO_QUERY); + uno::Reference< io::XInputStream > xInPipe(xOutPipe, uno::UNO_QUERY); + + // creating the mark streams + uno::Reference< io::XInputStream > xMarkIn(xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.io.MarkableInputStream")), uno::UNO_QUERY); + uno::Reference< io::XActiveDataSink > xMarkSink(xMarkIn, uno::UNO_QUERY); + + uno::Reference< io::XOutputStream > xMarkOut(xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.io.MarkableOutputStream")), uno::UNO_QUERY); + uno::Reference< io::XActiveDataSource > xMarkSource(xMarkOut, uno::UNO_QUERY); + + // connect mark and sink + uno::Reference< io::XActiveDataSink > xSink(xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.io.ObjectInputStream")), uno::UNO_QUERY); + + // connect mark and source + uno::Reference< io::XActiveDataSource > xSource(xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.io.ObjectOutputStream")), uno::UNO_QUERY); + + uno::Reference< io::XObjectOutputStream > xOutStrm(xSource, uno::UNO_QUERY); + uno::Reference< io::XObjectInputStream > xInStrm(xSink, uno::UNO_QUERY); + + if (xMarkSink.is() && xMarkSource.is() && xSink.is() && xSource.is()) + { + xMarkSink->setInputStream(xInPipe); + xMarkSource->setOutputStream(xOutPipe); + xSink->setInputStream(xMarkIn); + xSource->setOutputStream(xMarkOut); + + // write the object to source + xOutStrm->writeObject(xObj); + xOutStrm->closeOutput(); + // read the object + uno::Reference< awt::XControlModel > xModel(xInStrm->readObject(), uno::UNO_QUERY); + xInStrm->closeInput(); + + DBG_ASSERT(xModel.is(), "SdrUnoObj::operator =, keine Model erzeugt"); + + xUnoControlModel = xModel; + } + } + } + + // get service name of the control from the control model + uno::Reference< beans::XPropertySet > xSet(xUnoControlModel, uno::UNO_QUERY); + if (xSet.is()) + { + uno::Any aValue( xSet->getPropertyValue( rtl::OUString::createFromAscii("DefaultControl")) ); + ::rtl::OUString aStr; + + if( aValue >>= aStr ) + aUnoControlTypeName = String(aStr); + } + + uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY); + if (xComp.is()) + m_pImpl->pEventListener->StartListening(xComp); +} + +void SdrUnoObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + SdrRectObj::NbcResize(rRef,xFact,yFact); + + if (aGeo.nShearWink!=0 || aGeo.nDrehWink!=0) + { + // kleine Korrekturen + if (aGeo.nDrehWink>=9000 && aGeo.nDrehWink<27000) + { + aRect.Move(aRect.Left()-aRect.Right(),aRect.Top()-aRect.Bottom()); + } + + aGeo.nDrehWink = 0; + aGeo.nShearWink = 0; + aGeo.nSin = 0.0; + aGeo.nCos = 1.0; + aGeo.nTan = 0.0; + SetRectsDirty(); + } +} + +// ----------------------------------------------------------------------------- + +bool SdrUnoObj::hasSpecialDrag() const +{ + // no special drag; we have no rounding rect and + // do want frame handles + return false; +} + +bool SdrUnoObj::supportsFullDrag() const +{ + // overloaded to have the possibility to enable/disable in debug and + // to ckeck some things out. Current solution is working, so default is + // enabled + static bool bDoSupportFullDrag(true); + + return bDoSupportFullDrag; +} + +SdrObject* SdrUnoObj::getFullDragClone() const +{ + SdrObject* pRetval = 0; + static bool bHandleSpecial(false); + + if(bHandleSpecial) + { + // special handling for SdrUnoObj (FormControl). Create a SdrGrafObj + // for drag containing the graphical representation. This does not work too + // well, so the default is to simply clone + pRetval = new SdrGrafObj(SdrDragView::GetObjGraphic(GetModel(), this), GetLogicRect()); + } + else + { + // call parent (simply clone) + pRetval = SdrRectObj::getFullDragClone(); + } + + return pRetval; +} + +// ----------------------------------------------------------------------------- +void SdrUnoObj::NbcSetLayer( SdrLayerID _nLayer ) +{ + if ( GetLayer() == _nLayer ) + { // redundant call -> not interested in doing anything here + SdrRectObj::NbcSetLayer( _nLayer ); + return; + } + + // we need some special handling here in case we're moved from an invisible layer + // to a visible one, or vice versa + // (relative to a layer. Remember that the visibility of a layer is a view attribute + // - the same layer can be visible in one view, and invisible in another view, at the + // same time) + // 2003-06-03 - #110592# - fs@openoffice.org + + // collect all views in which our old layer is visible + ::std::set< SdrView* > aPreviouslyVisible; + + { + SdrViewIter aIter( this ); + for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() ) + aPreviouslyVisible.insert( pView ); + } + + SdrRectObj::NbcSetLayer( _nLayer ); + + // collect all views in which our new layer is visible + ::std::set< SdrView* > aNewlyVisible; + + { + SdrViewIter aIter( this ); + for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() ) + { + ::std::set< SdrView* >::const_iterator aPrevPos = aPreviouslyVisible.find( pView ); + if ( aPreviouslyVisible.end() != aPrevPos ) + { // in pView, we were visible _before_ the layer change, and are + // visible _after_ the layer change, too + // -> we're not interested in this view at all + aPreviouslyVisible.erase( aPrevPos ); + } + else + { + // in pView, we were visible _before_ the layer change, and are + // _not_ visible after the layer change + // => remember this view, as our visibility there changed + aNewlyVisible.insert( pView ); + } + } + } + + // now aPreviouslyVisible contains all views where we became invisible + ::std::set< SdrView* >::const_iterator aLoopViews; + for ( aLoopViews = aPreviouslyVisible.begin(); + aLoopViews != aPreviouslyVisible.end(); + ++aLoopViews + ) + { + lcl_ensureControlVisibility( *aLoopViews, this, false ); + } + + // and aNewlyVisible all views where we became visible + for ( aLoopViews = aNewlyVisible.begin(); + aLoopViews != aNewlyVisible.end(); + ++aLoopViews + ) + { + lcl_ensureControlVisibility( *aLoopViews, this, true ); + } +} + +void SdrUnoObj::CreateUnoControlModel(const String& rModelName) +{ + DBG_ASSERT(!xUnoControlModel.is(), "model already exists"); + + aUnoControlModelTypeName = rModelName; + + uno::Reference< awt::XControlModel > xModel; + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + if (aUnoControlModelTypeName.Len() && xFactory.is() ) + { + xModel = uno::Reference< awt::XControlModel >(xFactory->createInstance( + aUnoControlModelTypeName), uno::UNO_QUERY); + + if (xModel.is()) + SetChanged(); + } + + SetUnoControlModel(xModel); +} + +void SdrUnoObj::CreateUnoControlModel(const String& rModelName, + const uno::Reference< lang::XMultiServiceFactory >& rxSFac) +{ + DBG_ASSERT(!xUnoControlModel.is(), "model already exists"); + + aUnoControlModelTypeName = rModelName; + + uno::Reference< awt::XControlModel > xModel; + if (aUnoControlModelTypeName.Len() && rxSFac.is() ) + { + xModel = uno::Reference< awt::XControlModel >(rxSFac->createInstance( + aUnoControlModelTypeName), uno::UNO_QUERY); + + if (xModel.is()) + SetChanged(); + } + + SetUnoControlModel(xModel); +} + +void SdrUnoObj::SetUnoControlModel( const uno::Reference< awt::XControlModel >& xModel) +{ + if (xUnoControlModel.is()) + { + uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY); + if (xComp.is()) + m_pImpl->pEventListener->StopListening(xComp); + } + + xUnoControlModel = xModel; + + // control model muss servicename des controls enthalten + if (xUnoControlModel.is()) + { + uno::Reference< beans::XPropertySet > xSet(xUnoControlModel, uno::UNO_QUERY); + if (xSet.is()) + { + uno::Any aValue( xSet->getPropertyValue(String("DefaultControl", gsl_getSystemTextEncoding())) ); + ::rtl::OUString aStr; + if( aValue >>= aStr ) + aUnoControlTypeName = String(aStr); + } + + uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY); + if (xComp.is()) + m_pImpl->pEventListener->StartListening(xComp); + } + + // invalidate all ViewObject contacts + ViewContactOfUnoControl* pVC = NULL; + if ( impl_getViewContact( pVC ) ) + { + // flushViewObjectContacts() removes all existing VOCs for the local DrawHierarchy. This + // is always allowed since they will be re-created on demand (and with the changed model) + GetViewContact().flushViewObjectContacts(true); + } +} + +//------------------------------------------------------------------------ +uno::Reference< awt::XControl > SdrUnoObj::GetUnoControl(const SdrView& _rView, const OutputDevice& _rOut) const +{ + uno::Reference< awt::XControl > xControl; + + SdrPageView* pPageView = _rView.GetSdrPageView(); + OSL_ENSURE( GetPage() == pPageView->GetPage(), "SdrUnoObj::GetUnoControl: This object is not displayed in that particular view!" ); + if ( GetPage() != pPageView->GetPage() ) + return NULL; + + SdrPageWindow* pPageWindow = pPageView ? pPageView->FindPageWindow( _rOut ) : NULL; + OSL_ENSURE( pPageWindow, "SdrUnoObj::GetUnoControl: did not find my SdrPageWindow!" ); + if ( !pPageWindow ) + return NULL; + + ViewObjectContact& rViewObjectContact( GetViewContact().GetViewObjectContact( pPageWindow->GetObjectContact() ) ); + ViewObjectContactOfUnoControl* pUnoContact = dynamic_cast< ViewObjectContactOfUnoControl* >( &rViewObjectContact ); + OSL_ENSURE( pUnoContact, "SdrUnoObj::GetUnoControl: wrong contact type!" ); + if ( pUnoContact ) + xControl = pUnoContact->getControl(); + + return xControl; +} + +//------------------------------------------------------------------------ +uno::Reference< awt::XControl > SdrUnoObj::GetTemporaryControlForWindow( + const Window& _rWindow, uno::Reference< awt::XControlContainer >& _inout_ControlContainer ) const +{ + uno::Reference< awt::XControl > xControl; + + ViewContactOfUnoControl* pVC = NULL; + if ( impl_getViewContact( pVC ) ) + xControl = pVC->getTemporaryControlForWindow( _rWindow, _inout_ControlContainer ); + + return xControl; +} + +//------------------------------------------------------------------------ +bool SdrUnoObj::impl_getViewContact( ViewContactOfUnoControl*& _out_rpContact ) const +{ + ViewContact& rViewContact( GetViewContact() ); + _out_rpContact = dynamic_cast< ViewContactOfUnoControl* >( &rViewContact ); + DBG_ASSERT( _out_rpContact, "SdrUnoObj::impl_getViewContact: could not find my ViewContact!" ); + return ( _out_rpContact != NULL ); +} + +//------------------------------------------------------------------------ +::sdr::contact::ViewContact* SdrUnoObj::CreateObjectSpecificViewContact() +{ + return new ::sdr::contact::ViewContactOfUnoControl( *this ); +} + +// ----------------------------------------------------------------------------- +// eof diff --git a/svx/source/svdraw/svdoutl.cxx b/svx/source/svdraw/svdoutl.cxx new file mode 100644 index 000000000000..79e74a3382b8 --- /dev/null +++ b/svx/source/svdraw/svdoutl.cxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/svdoutl.hxx> +#include <editeng/outliner.hxx> +#include <svx/svdotext.hxx> +#include <editeng/editstat.hxx> +#include <svx/svdmodel.hxx> +#include <editeng/eeitem.hxx> +#include <svl/itempool.hxx> + +DBG_NAME(SdrOutliner) +/************************************************************************* +|* +|* Ctor +|* +\************************************************************************/ +SdrOutliner::SdrOutliner( SfxItemPool* pItemPool, USHORT nMode ) +: Outliner( pItemPool, nMode ), + //mpPaintInfoRec( NULL ) + mpVisualizedPage(0) +{ + DBG_CTOR(SdrOutliner,NULL); +} + + +/************************************************************************* +|* +|* Dtor +|* +\************************************************************************/ +SdrOutliner::~SdrOutliner() +{ + DBG_DTOR(SdrOutliner,NULL); +} + + +/************************************************************************* +|* +|* +|* +\************************************************************************/ +void SdrOutliner::SetTextObj( const SdrTextObj* pObj ) +{ + if( pObj && pObj != mpTextObj.get() ) + { + SetUpdateMode(FALSE); + USHORT nOutlinerMode2 = OUTLINERMODE_OUTLINEOBJECT; + if ( !pObj->IsOutlText() ) + nOutlinerMode2 = OUTLINERMODE_TEXTOBJECT; + Init( nOutlinerMode2 ); + + SetGlobalCharStretching(100,100); + + ULONG nStat = GetControlWord(); + nStat &= ~( EE_CNTRL_STRETCHING | EE_CNTRL_AUTOPAGESIZE ); + SetControlWord(nStat); + + Size aNullSize; + Size aMaxSize( 100000,100000 ); + SetMinAutoPaperSize( aNullSize ); + SetMaxAutoPaperSize( aMaxSize ); + SetPaperSize( aMaxSize ); + ClearPolygon(); + } + + mpTextObj.reset( const_cast< SdrTextObj* >(pObj) ); +} + +/************************************************************************* +|* +|* +|* +\************************************************************************/ +void SdrOutliner::SetTextObjNoInit( const SdrTextObj* pObj ) +{ + mpTextObj.reset( const_cast< SdrTextObj* >(pObj) ); +} + +/************************************************************************* +|* +|* +|* +\************************************************************************/ +XubString SdrOutliner::CalcFieldValue(const SvxFieldItem& rField, USHORT nPara, USHORT nPos, + Color*& rpTxtColor, Color*& rpFldColor) +{ + FASTBOOL bOk = FALSE; + XubString aRet; + + if(mpTextObj.is()) + bOk = static_cast< SdrTextObj* >( mpTextObj.get())->CalcFieldValue(rField, nPara, nPos, FALSE, rpTxtColor, rpFldColor, aRet); + + if (!bOk) + aRet = Outliner::CalcFieldValue(rField, nPara, nPos, rpTxtColor, rpFldColor); + + return aRet; +} + +const SdrTextObj* SdrOutliner::GetTextObj() const +{ + if( mpTextObj.is() ) + return static_cast< SdrTextObj* >( mpTextObj.get() ); + else + return 0; +} diff --git a/svx/source/svdraw/svdoutlinercache.cxx b/svx/source/svdraw/svdoutlinercache.cxx new file mode 100644 index 000000000000..429b459d3271 --- /dev/null +++ b/svx/source/svdraw/svdoutlinercache.cxx @@ -0,0 +1,115 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + + +#include "svdoutlinercache.hxx" +#include <svx/svdoutl.hxx> +#include <svx/svdmodel.hxx> + +extern SdrOutliner* SdrMakeOutliner( USHORT nOutlinerMode, SdrModel* pModel ); + +SdrOutlinerCache::SdrOutlinerCache( SdrModel* pModel ) +: mpModel( pModel ), + mpModeOutline( NULL ), + mpModeText( NULL ) +{ +} + +SdrOutliner* SdrOutlinerCache::createOutliner( sal_uInt16 nOutlinerMode ) +{ + SdrOutliner* pOutliner = NULL; + + if( (OUTLINERMODE_OUTLINEOBJECT == nOutlinerMode) && mpModeOutline ) + { + pOutliner = mpModeOutline; + mpModeOutline = NULL; + } + else if( (OUTLINERMODE_TEXTOBJECT == nOutlinerMode) && mpModeText ) + { + pOutliner = mpModeText; + mpModeText = NULL; + } + else + { + pOutliner = SdrMakeOutliner( nOutlinerMode, mpModel ); + Outliner& aDrawOutliner = mpModel->GetDrawOutliner(); + pOutliner->SetCalcFieldValueHdl( aDrawOutliner.GetCalcFieldValueHdl() ); + } + + return pOutliner; +} + +SdrOutlinerCache::~SdrOutlinerCache() +{ + if( mpModeOutline ) + { + delete mpModeOutline; + mpModeOutline = NULL; + } + + if( mpModeText ) + { + delete mpModeText; + mpModeText = NULL; + } +} + +void SdrOutlinerCache::disposeOutliner( SdrOutliner* pOutliner ) +{ + if( pOutliner ) + { + USHORT nOutlMode = pOutliner->GetOutlinerMode(); + + if( (OUTLINERMODE_OUTLINEOBJECT == nOutlMode) && (NULL == mpModeOutline) ) + { + mpModeOutline = pOutliner; + pOutliner->Clear(); + pOutliner->SetVertical( false ); + + // #101088# Deregister on outliner, might be reused from outliner cache + pOutliner->SetNotifyHdl( Link() ); + } + else if( (OUTLINERMODE_TEXTOBJECT == nOutlMode) && (NULL == mpModeText) ) + { + mpModeText = pOutliner; + pOutliner->Clear(); + pOutliner->SetVertical( false ); + + // #101088# Deregister on outliner, might be reused from outliner cache + pOutliner->SetNotifyHdl( Link() ); + } + else + { + delete pOutliner; + } + } +} + + diff --git a/svx/source/svdraw/svdovirt.cxx b/svx/source/svdraw/svdovirt.cxx new file mode 100644 index 000000000000..c97af7abc37c --- /dev/null +++ b/svx/source/svdraw/svdovirt.cxx @@ -0,0 +1,659 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdovirt.hxx> +#include <svx/xpool.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdhdl.hxx> +#include <svx/sdr/contact/viewcontactofvirtobj.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <svx/svdograf.hxx> +#include <svx/svddrgv.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sdr::properties::BaseProperties& SdrVirtObj::GetProperties() const +{ + return rRefObj.GetProperties(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// AW, OD 2004-05-03 #i27224# +sdr::contact::ViewContact* SdrVirtObj::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfVirtObj(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrVirtObj,SdrObject); + +SdrVirtObj::SdrVirtObj(SdrObject& rNewObj): + rRefObj(rNewObj) +{ + bVirtObj=TRUE; // Ja, ich bin ein virtuelles Objekt + rRefObj.AddReference(*this); + bClosedObj=rRefObj.IsClosedObj(); +} + +SdrVirtObj::SdrVirtObj(SdrObject& rNewObj, const Point& rAnchorPos): + rRefObj(rNewObj) +{ + aAnchor=rAnchorPos; + bVirtObj=TRUE; // Ja, ich bin ein virtuelles Objekt + rRefObj.AddReference(*this); + bClosedObj=rRefObj.IsClosedObj(); +} + +SdrVirtObj::~SdrVirtObj() +{ + rRefObj.DelReference(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const SdrObject& SdrVirtObj::GetReferencedObj() const +{ + return rRefObj; +} + +SdrObject& SdrVirtObj::ReferencedObj() +{ + return rRefObj; +} + +void __EXPORT SdrVirtObj::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& /*rHint*/) +{ + bClosedObj=rRefObj.IsClosedObj(); + SetRectsDirty(); // hier noch Optimieren. + + // Only a repaint here, rRefObj may have changed and broadcasts + ActionChanged(); + // BroadcastObjectChange(); +} + +void SdrVirtObj::NbcSetAnchorPos(const Point& rAnchorPos) +{ + aAnchor=rAnchorPos; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrVirtObj::SetModel(SdrModel* pNewModel) +{ + SdrObject::SetModel(pNewModel); + rRefObj.SetModel(pNewModel); +} + +void SdrVirtObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rRefObj.TakeObjInfo(rInfo); +} + +UINT32 SdrVirtObj::GetObjInventor() const +{ + return rRefObj.GetObjInventor(); +} + +UINT16 SdrVirtObj::GetObjIdentifier() const +{ + return rRefObj.GetObjIdentifier(); +} + +SdrObjList* SdrVirtObj::GetSubList() const +{ + return rRefObj.GetSubList(); +} + +const Rectangle& SdrVirtObj::GetCurrentBoundRect() const +{ + ((SdrVirtObj*)this)->aOutRect=rRefObj.GetCurrentBoundRect(); // Hier noch optimieren + ((SdrVirtObj*)this)->aOutRect+=aAnchor; + return aOutRect; +} + +const Rectangle& SdrVirtObj::GetLastBoundRect() const +{ + ((SdrVirtObj*)this)->aOutRect=rRefObj.GetLastBoundRect(); // Hier noch optimieren + ((SdrVirtObj*)this)->aOutRect+=aAnchor; + return aOutRect; +} + +void SdrVirtObj::RecalcBoundRect() +{ + aOutRect=rRefObj.GetCurrentBoundRect(); + aOutRect+=aAnchor; +} + +void SdrVirtObj::SetChanged() +{ + SdrObject::SetChanged(); +} + +SdrObject* SdrVirtObj::Clone() const +{ + SdrObject* pObj=new SdrVirtObj(((SdrVirtObj*)this)->rRefObj); // Nur eine weitere Referenz + return pObj; +} + +void SdrVirtObj::operator=(const SdrObject& rObj) +{ // ???anderes Objekt referenzieren??? + SdrObject::operator=(rObj); + aAnchor=((SdrVirtObj&)rObj).aAnchor; +} + +void SdrVirtObj::TakeObjNameSingul(XubString& rName) const +{ + rRefObj.TakeObjNameSingul(rName); + rName.Insert(sal_Unicode('['), 0); + rName += sal_Unicode(']'); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +void SdrVirtObj::TakeObjNamePlural(XubString& rName) const +{ + rRefObj.TakeObjNamePlural(rName); + rName.Insert(sal_Unicode('['), 0); + rName += sal_Unicode(']'); +} + +void operator +=(PolyPolygon& rPoly, const Point& rOfs) +{ + if (rOfs.X()!=0 || rOfs.Y()!=0) { + USHORT i,j; + for (j=0; j<rPoly.Count(); j++) { + Polygon aP1(rPoly.GetObject(j)); + for (i=0; i<aP1.GetSize(); i++) { + aP1[i]+=rOfs; + } + rPoly.Replace(aP1,j); + } + } +} + +basegfx::B2DPolyPolygon SdrVirtObj::TakeXorPoly() const +{ + basegfx::B2DPolyPolygon aPolyPolygon(rRefObj.TakeXorPoly()); + + if(aAnchor.X() || aAnchor.Y()) + { + aPolyPolygon.transform(basegfx::tools::createTranslateB2DHomMatrix(aAnchor.X(), aAnchor.Y())); + } + + return aPolyPolygon; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_uInt32 SdrVirtObj::GetHdlCount() const +{ + return rRefObj.GetHdlCount(); +} + +SdrHdl* SdrVirtObj::GetHdl(sal_uInt32 nHdlNum) const +{ + SdrHdl* pHdl=rRefObj.GetHdl(nHdlNum); + + // #i73248# + // GetHdl() at SdrObject is not guaranteed to return an object + if(pHdl) + { + Point aP(pHdl->GetPos()+aAnchor); + pHdl->SetPos(aP); + } + + return pHdl; +} + +sal_uInt32 SdrVirtObj::GetPlusHdlCount(const SdrHdl& rHdl) const +{ + return rRefObj.GetPlusHdlCount(rHdl); +} + +SdrHdl* SdrVirtObj::GetPlusHdl(const SdrHdl& rHdl, sal_uInt32 nPlNum) const +{ + SdrHdl* pHdl=rRefObj.GetPlusHdl(rHdl,nPlNum); + pHdl->SetPos(pHdl->GetPos() + aAnchor); + return pHdl; +} + +void SdrVirtObj::AddToHdlList(SdrHdlList& rHdlList) const +{ + // #i73248# + // SdrObject::AddToHdlList(rHdlList) is not a good thing to call + // since at SdrPathObj, only AddToHdlList may be used and the call + // will instead use the standard implementation which uses GetHdlCount() + // and GetHdl instead. This is not wrong, but may be much less effective + // and may not be prepared to GetHdl returning NULL + + // get handles using AddToHdlList from ref object + SdrHdlList aLocalList(0); + rRefObj.AddToHdlList(aLocalList); + const sal_uInt32 nHdlCount(aLocalList.GetHdlCount()); + + if(nHdlCount) + { + // translate handles and add them to dest list. They are temporarily part of + // two lists then + const Point aOffset(GetOffset()); + + for(sal_uInt32 a(0L); a < nHdlCount; a++) + { + SdrHdl* pCandidate = aLocalList.GetHdl(a); + pCandidate->SetPos(pCandidate->GetPos() + aOffset); + rHdlList.AddHdl(pCandidate); + } + + // remove them from source list, else they will be deleted when + // source list is deleted + while(aLocalList.GetHdlCount()) + { + aLocalList.RemoveHdl(aLocalList.GetHdlCount() - 1L); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrVirtObj::hasSpecialDrag() const +{ + return rRefObj.hasSpecialDrag(); +} + +bool SdrVirtObj::supportsFullDrag() const +{ + return false; +} + +SdrObject* SdrVirtObj::getFullDragClone() const +{ + static bool bSpecialHandling(false); + SdrObject* pRetval = 0; + + if(bSpecialHandling) + { + // special handling for VirtObj. Do not create another + // reference to rRefObj, this would allow to change that + // one on drag. Instead, create a SdrGrafObj for drag containing + // the graphical representation + pRetval = new SdrGrafObj(SdrDragView::GetObjGraphic(GetModel(), this), GetLogicRect()); + } + else + { + SdrObject& rReferencedObject = ((SdrVirtObj*)this)->ReferencedObj(); + pRetval = new SdrGrafObj(SdrDragView::GetObjGraphic(GetModel(), &rReferencedObject), GetLogicRect()); + } + + return pRetval; +} + +bool SdrVirtObj::beginSpecialDrag(SdrDragStat& rDrag) const +{ + return rRefObj.beginSpecialDrag(rDrag); +} + +bool SdrVirtObj::applySpecialDrag(SdrDragStat& rDrag) +{ + return rRefObj.applySpecialDrag(rDrag); +} + +basegfx::B2DPolyPolygon SdrVirtObj::getSpecialDragPoly(const SdrDragStat& rDrag) const +{ + return rRefObj.getSpecialDragPoly(rDrag); + // Offset handlen !!!!!! fehlt noch !!!!!!! +} + +String SdrVirtObj::getSpecialDragComment(const SdrDragStat& rDrag) const +{ + return rRefObj.getSpecialDragComment(rDrag); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrVirtObj::BegCreate(SdrDragStat& rStat) +{ + return rRefObj.BegCreate(rStat); +} + +FASTBOOL SdrVirtObj::MovCreate(SdrDragStat& rStat) +{ + return rRefObj.MovCreate(rStat); +} + +FASTBOOL SdrVirtObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + return rRefObj.EndCreate(rStat,eCmd); +} + +FASTBOOL SdrVirtObj::BckCreate(SdrDragStat& rStat) +{ + return rRefObj.BckCreate(rStat); +} + +void SdrVirtObj::BrkCreate(SdrDragStat& rStat) +{ + rRefObj.BrkCreate(rStat); +} + +basegfx::B2DPolyPolygon SdrVirtObj::TakeCreatePoly(const SdrDragStat& rDrag) const +{ + return rRefObj.TakeCreatePoly(rDrag); + // Offset handlen !!!!!! fehlt noch !!!!!!! +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrVirtObj::NbcMove(const Size& rSiz) +{ + MovePoint(aAnchor,rSiz); + SetRectsDirty(); +} + +void SdrVirtObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + rRefObj.NbcResize(rRef-aAnchor,xFact,yFact); + SetRectsDirty(); +} + +void SdrVirtObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + rRefObj.NbcRotate(rRef-aAnchor,nWink,sn,cs); + SetRectsDirty(); +} + +void SdrVirtObj::NbcMirror(const Point& rRef1, const Point& rRef2) +{ + rRefObj.NbcMirror(rRef1-aAnchor,rRef2-aAnchor); + SetRectsDirty(); +} + +void SdrVirtObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + rRefObj.NbcShear(rRef-aAnchor,nWink,tn,bVShear); + SetRectsDirty(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrVirtObj::Move(const Size& rSiz) +{ + if (rSiz.Width()!=0 || rSiz.Height()!=0) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcMove(rSiz); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} + +void SdrVirtObj::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + if (xFact.GetNumerator()!=xFact.GetDenominator() || yFact.GetNumerator()!=yFact.GetDenominator()) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + rRefObj.Resize(rRef-aAnchor,xFact,yFact); + SetRectsDirty(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrVirtObj::Rotate(const Point& rRef, long nWink, double sn, double cs) +{ + if (nWink!=0) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + rRefObj.Rotate(rRef-aAnchor,nWink,sn,cs); + SetRectsDirty(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrVirtObj::Mirror(const Point& rRef1, const Point& rRef2) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + rRefObj.Mirror(rRef1-aAnchor,rRef2-aAnchor); + SetRectsDirty(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +void SdrVirtObj::Shear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) +{ + if (nWink!=0) { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + rRefObj.Shear(rRef-aAnchor,nWink,tn,bVShear); + SetRectsDirty(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrVirtObj::RecalcSnapRect() +{ + aSnapRect=rRefObj.GetSnapRect(); + aSnapRect+=aAnchor; +} + +const Rectangle& SdrVirtObj::GetSnapRect() const +{ + ((SdrVirtObj*)this)->aSnapRect=rRefObj.GetSnapRect(); + ((SdrVirtObj*)this)->aSnapRect+=aAnchor; + return aSnapRect; +} + +void SdrVirtObj::SetSnapRect(const Rectangle& rRect) +{ + { + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + Rectangle aR(rRect); + aR-=aAnchor; + rRefObj.SetSnapRect(aR); + SetRectsDirty(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } +} + +void SdrVirtObj::NbcSetSnapRect(const Rectangle& rRect) +{ + Rectangle aR(rRect); + aR-=aAnchor; + SetRectsDirty(); + rRefObj.NbcSetSnapRect(aR); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const Rectangle& SdrVirtObj::GetLogicRect() const +{ + ((SdrVirtObj*)this)->aSnapRect=rRefObj.GetLogicRect(); // !!! Missbrauch von aSnapRect !!! + ((SdrVirtObj*)this)->aSnapRect+=aAnchor; // Wenns mal Aerger gibt, muss ein weiteres Rectangle Member her (oder Heap) + return aSnapRect; +} + +void SdrVirtObj::SetLogicRect(const Rectangle& rRect) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + Rectangle aR(rRect); + aR-=aAnchor; + rRefObj.SetLogicRect(aR); + SetRectsDirty(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +void SdrVirtObj::NbcSetLogicRect(const Rectangle& rRect) +{ + Rectangle aR(rRect); + aR-=aAnchor; + SetRectsDirty(); + rRefObj.NbcSetLogicRect(aR); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +long SdrVirtObj::GetRotateAngle() const +{ + return rRefObj.GetRotateAngle(); +} + +long SdrVirtObj::GetShearAngle(FASTBOOL bVertical) const +{ + return rRefObj.GetShearAngle(bVertical); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_uInt32 SdrVirtObj::GetSnapPointCount() const +{ + return rRefObj.GetSnapPointCount(); +} + +Point SdrVirtObj::GetSnapPoint(sal_uInt32 i) const +{ + Point aP(rRefObj.GetSnapPoint(i)); + aP+=aAnchor; + return aP; +} + +sal_Bool SdrVirtObj::IsPolyObj() const +{ + return rRefObj.IsPolyObj(); +} + +sal_uInt32 SdrVirtObj::GetPointCount() const +{ + return rRefObj.GetPointCount(); +} + +Point SdrVirtObj::GetPoint(sal_uInt32 i) const +{ + return Point(rRefObj.GetPoint(i) + aAnchor); +} + +void SdrVirtObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i) +{ + Point aP(rPnt); + aP-=aAnchor; + rRefObj.SetPoint(aP,i); + SetRectsDirty(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObjGeoData* SdrVirtObj::NewGeoData() const +{ + return rRefObj.NewGeoData(); +} + +void SdrVirtObj::SaveGeoData(SdrObjGeoData& rGeo) const +{ + rRefObj.SaveGeoData(rGeo); +} + +void SdrVirtObj::RestGeoData(const SdrObjGeoData& rGeo) +{ + rRefObj.RestGeoData(rGeo); + SetRectsDirty(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrObjGeoData* SdrVirtObj::GetGeoData() const +{ + return rRefObj.GetGeoData(); +} + +void SdrVirtObj::SetGeoData(const SdrObjGeoData& rGeo) +{ + Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); + rRefObj.SetGeoData(rGeo); + SetRectsDirty(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrVirtObj::NbcReformatText() +{ + rRefObj.NbcReformatText(); +} + +void SdrVirtObj::ReformatText() +{ + rRefObj.ReformatText(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +FASTBOOL SdrVirtObj::HasMacro() const +{ + return rRefObj.HasMacro(); +} + +SdrObject* SdrVirtObj::CheckMacroHit(const SdrObjMacroHitRec& rRec) const +{ + return rRefObj.CheckMacroHit(rRec); // Todo: Positionsversatz +} + +Pointer SdrVirtObj::GetMacroPointer(const SdrObjMacroHitRec& rRec) const +{ + return rRefObj.GetMacroPointer(rRec); // Todo: Positionsversatz +} + +void SdrVirtObj::PaintMacro(OutputDevice& rOut, const Rectangle& rDirtyRect, const SdrObjMacroHitRec& rRec) const +{ + rRefObj.PaintMacro(rOut,rDirtyRect,rRec); // Todo: Positionsversatz +} + +FASTBOOL SdrVirtObj::DoMacro(const SdrObjMacroHitRec& rRec) +{ + return rRefObj.DoMacro(rRec); // Todo: Positionsversatz +} + +XubString SdrVirtObj::GetMacroPopupComment(const SdrObjMacroHitRec& rRec) const +{ + return rRefObj.GetMacroPopupComment(rRec); // Todo: Positionsversatz +} + +const Point SdrVirtObj::GetOffset() const +{ + // #i73248# default offset of SdrVirtObj is aAnchor + return aAnchor; +} + +// eof diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx new file mode 100644 index 000000000000..8da0b248f38b --- /dev/null +++ b/svx/source/svdraw/svdpage.cxx @@ -0,0 +1,2020 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdpage.hxx> + +// HACK +#include <sot/storage.hxx> +#include <sot/clsids.hxx> +#include <sot/storage.hxx> +#include <svx/svdview.hxx> +#include <string.h> +#ifndef _STRING_H +#define _STRING_H +#endif +#include <vcl/svapp.hxx> + +#include <tools/diagnose_ex.h> + +#include <svx/svdetc.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdograf.hxx> // fuer SwapInAll() +#include <svx/svdoedge.hxx> // Zum kopieren der Konnektoren +#include <svx/svdoole2.hxx> // Sonderbehandlung OLE beim SdrExchangeFormat +#include "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 <vcl/salbtype.hxx> // FRound +#include <svx/sdr/contact/viewcontactofsdrpage.hxx> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <algorithm> +#include <svl/smplhint.hxx> + +using namespace ::com::sun::star; + +namespace { +void DumpObjectList (const ::std::vector<SdrObjectWeakRef>& rContainer) +{ + ::std::vector<SdrObjectWeakRef>::const_iterator iObject (rContainer.begin()); + ::std::vector<SdrObjectWeakRef>::const_iterator iEnd (rContainer.end()); + for (int nIndex=0 ; iObject!=iEnd; ++iObject,++nIndex) + { + const SdrObject* pObject = iObject->get(); + OSL_TRACE("%d : %x, %s", nIndex, + pObject, + ::rtl::OUStringToOString(pObject->GetName(),RTL_TEXTENCODING_UTF8).getStr()); + } +} +} + + +class SdrObjList::WeakSdrObjectContainerType + : public ::std::vector<SdrObjectWeakRef> +{ +public: + WeakSdrObjectContainerType (const sal_Int32 nInitialSize) + : ::std::vector<SdrObjectWeakRef>(nInitialSize) {}; +}; + + + +static const sal_Int32 InitialObjectContainerCapacity (64); +DBG_NAME(SdrObjList) + +TYPEINIT0(SdrObjList); + +SdrObjList::SdrObjList(SdrModel* pNewModel, SdrPage* pNewPage, SdrObjList* pNewUpList): + maList(), + mpNavigationOrder(), + mbIsNavigationOrderDirty(false) +{ + DBG_CTOR(SdrObjList,NULL); + maList.reserve(InitialObjectContainerCapacity); + pModel=pNewModel; + pPage=pNewPage; + pUpList=pNewUpList; + bObjOrdNumsDirty=FALSE; + bRectsDirty=FALSE; + pOwnerObj=NULL; + eListKind=SDROBJLIST_UNKNOWN; +} + +SdrObjList::SdrObjList(const SdrObjList& rSrcList): + maList(), + mpNavigationOrder(), + mbIsNavigationOrderDirty(false) +{ + DBG_CTOR(SdrObjList,NULL); + maList.reserve(InitialObjectContainerCapacity); + pModel=NULL; + pPage=NULL; + pUpList=NULL; + bObjOrdNumsDirty=FALSE; + bRectsDirty=FALSE; + pOwnerObj=NULL; + eListKind=SDROBJLIST_UNKNOWN; + *this=rSrcList; +} + +SdrObjList::~SdrObjList() +{ + DBG_DTOR(SdrObjList,NULL); + + // #111111# + // 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(); // Containerinhalt loeschen! +} + +void SdrObjList::operator=(const SdrObjList& rSrcList) +{ + Clear(); + eListKind=rSrcList.eListKind; + CopyObjects(rSrcList); +} + +void SdrObjList::CopyObjects(const SdrObjList& rSrcList) +{ + Clear(); + bObjOrdNumsDirty=FALSE; + bRectsDirty =FALSE; + ULONG nCloneErrCnt=0; + ULONG nAnz=rSrcList.GetObjCount(); + SdrInsertReason aReason(SDRREASON_COPY); + ULONG no; + for (no=0; no<nAnz; no++) { + SdrObject* pSO=rSrcList.GetObj(no); + + // #116235# + //SdrObject* pDO=pSO->Clone(pPage,pModel); + SdrObject* pDO = pSO->Clone(); + pDO->SetModel(pModel); + pDO->SetPage(pPage); + + if (pDO!=NULL) { + NbcInsertObject(pDO,CONTAINER_APPEND,&aReason); + } else { + nCloneErrCnt++; + } + } + // und nun zu den Konnektoren + // Die neuen Objekte werden auf die der rSrcList abgebildet + // und so die Objektverbindungen hergestellt. + // Aehnliche Implementation an folgenden Stellen: + // void SdrObjList::CopyObjects(const SdrObjList& rSrcList) + // SdrModel* SdrExchangeView::GetMarkedObjModel() const + // FASTBOOL SdrExchangeView::Paste(const SdrModel& rMod,...) + // void SdrEditView::CopyMarked() + if (nCloneErrCnt==0) { + for (no=0; no<nAnz; no++) { + const SdrObject* pSrcOb=rSrcList.GetObj(no); + 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; // Listenuebergreifend + if (pSrcNode2!=NULL && pSrcNode2->GetObjList()!=pSrcEdge->GetObjList()) pSrcNode2=NULL; // ist (noch) nicht + if (pSrcNode1!=NULL || pSrcNode2!=NULL) { + SdrObject* pEdgeObjTmp=GetObj(no); + SdrEdgeObj* pDstEdge=PTR_CAST(SdrEdgeObj,pEdgeObjTmp); + if (pDstEdge!=NULL) { + if (pSrcNode1!=NULL) { + ULONG nDstNode1=pSrcNode1->GetOrdNum(); + SdrObject* pDstNode1=GetObj(nDstNode1); + if (pDstNode1!=NULL) { // Sonst grober Fehler! + pDstEdge->ConnectToNode(TRUE,pDstNode1); + } else { + DBG_ERROR("SdrObjList::operator=(): pDstNode1==NULL!"); + } + } + if (pSrcNode2!=NULL) { + ULONG nDstNode2=pSrcNode2->GetOrdNum(); + SdrObject* pDstNode2=GetObj(nDstNode2); + if (pDstNode2!=NULL) { // Node war sonst wohl nicht markiert + pDstEdge->ConnectToNode(FALSE,pDstNode2); + } else { + DBG_ERROR("SdrObjList::operator=(): pDstNode2==NULL!"); + } + } + } else { + DBG_ERROR("SdrObjList::operator=(): pDstEdge==NULL!"); + } + } + } + } + } else { +#ifdef DBG_UTIL + ByteString aStr("SdrObjList::operator=(): Fehler beim Clonen "); + + if(nCloneErrCnt == 1) + { + aStr += "eines Zeichenobjekts."; + } + else + { + aStr += "von "; + aStr += ByteString::CreateFromInt32( nCloneErrCnt ); + aStr += " Zeichenobjekten."; + } + + aStr += " Objektverbindungen werden nicht mitkopiert."; + + DBG_ERROR(aStr.GetBuffer()); +#endif + } +} + +void SdrObjList::Clear() +{ + sal_Bool bObjectsRemoved(sal_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 = sal_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; + ULONG nAnz=GetObjCount(); + for (ULONG no=0; no<nAnz; no++) { + SdrObject* pObj=GetObj(no); + pObj->SetPage(pPage); + } + } +} + +SdrModel* SdrObjList::GetModel() const +{ + return pModel; +} + +void SdrObjList::SetModel(SdrModel* pNewModel) +{ + if (pModel!=pNewModel) { + pModel=pNewModel; + ULONG nAnz=GetObjCount(); + for (ULONG i=0; i<nAnz; i++) { + SdrObject* pObj=GetObj(i); + pObj->SetModel(pModel); + } + } +} + +void SdrObjList::RecalcObjOrdNums() +{ + ULONG nAnz=GetObjCount(); + for (ULONG no=0; no<nAnz; no++) { + SdrObject* pObj=GetObj(no); + pObj->SetOrdNum(no); + } + bObjOrdNumsDirty=FALSE; +} + +void SdrObjList::RecalcRects() +{ + aOutRect=Rectangle(); + aSnapRect=aOutRect; + ULONG nAnz=GetObjCount(); + ULONG i; + for (i=0; i<nAnz; 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) const +{ + sdr::contact::ViewContact* pParent = rChild.GetViewContact().GetParentContact(); + + if(pParent) + { + pParent->ActionChildInserted(rChild.GetViewContact()); + } +} + +void SdrObjList::NbcInsertObject(SdrObject* pObj, ULONG nPos, const SdrInsertReason* /*pReason*/) +{ + DBG_ASSERT(pObj!=NULL,"SdrObjList::NbcInsertObject(NULL)"); + if (pObj!=NULL) { + DBG_ASSERT(!pObj->IsInserted(),"ZObjekt hat bereits Inserted-Status"); + ULONG nAnz=GetObjCount(); + if (nPos>nAnz) nPos=nAnz; + InsertObjectIntoContainer(*pObj,nPos); + + if (nPos<nAnz) bObjOrdNumsDirty=TRUE; + pObj->SetOrdNum(nPos); + pObj->SetObjList(this); + pObj->SetPage(pPage); + + // #110094# 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); // Ruft u.a. den UserCall + } +} + +void SdrObjList::InsertObject(SdrObject* pObj, ULONG nPos, const SdrInsertReason* pReason) +{ + DBG_ASSERT(pObj!=NULL,"SdrObjList::InsertObject(NULL)"); + + if(pObj) + { + // #69055# 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); + + // Falls das Objekt in eine Gruppe eingefuegt wird + // und nicht mit seinen Bruedern ueberlappt, muss es + // einen eigenen Redraw bekommen + if(pOwnerObj) + { + // only repaint here + pOwnerObj->ActionChanged(); + } + + if(pModel) + { + // Hier muss ein anderer Broadcast her! + // Repaint ab Objekt Nummer ... (Achtung: GroupObj) + if(pObj->GetPage()) + { + SdrHint aHint(*pObj); + + aHint.SetKind(HINT_OBJINSERTED); + pModel->Broadcast(aHint); + } + + pModel->SetChanged(); + } + } +} + +SdrObject* SdrObjList::NbcRemoveObject(ULONG nObjNum) +{ + if (nObjNum >= maList.size()) + { + OSL_ASSERT(nObjNum<maList.size()); + return NULL; + } + + ULONG nAnz=GetObjCount(); + SdrObject* pObj=maList[nObjNum]; + RemoveObjectFromContainer(nObjNum); + + // flushViewObjectContacts() clears the VOC's and those invalidate + pObj->GetViewContact().flushViewObjectContacts(true); + + DBG_ASSERT(pObj!=NULL,"Object zum Removen nicht gefunden"); + if (pObj!=NULL) { + DBG_ASSERT(pObj->IsInserted(),"ZObjekt hat keinen Inserted-Status"); + pObj->SetInserted(FALSE); // Ruft u.a. den UserCall + pObj->SetObjList(NULL); + pObj->SetPage(NULL); + if (!bObjOrdNumsDirty) { // Optimierung fuer den Fall, dass das letzte Obj rausgenommen wird + if (nObjNum!=ULONG(nAnz-1)) { + bObjOrdNumsDirty=TRUE; + } + } + SetRectsDirty(); + } + return pObj; +} + +SdrObject* SdrObjList::RemoveObject(ULONG nObjNum) +{ + if (nObjNum >= maList.size()) + { + OSL_ASSERT(nObjNum<maList.size()); + return NULL; + } + + ULONG nAnz=GetObjCount(); + SdrObject* pObj=maList[nObjNum]; + RemoveObjectFromContainer(nObjNum); + + DBG_ASSERT(pObj!=NULL,"Object zum Removen nicht gefunden"); + if(pObj) + { + // flushViewObjectContacts() clears the VOC's and those invalidate + pObj->GetViewContact().flushViewObjectContacts(true); + + DBG_ASSERT(pObj->IsInserted(),"ZObjekt hat keinen Inserted-Status"); + if (pModel!=NULL) { + // Hier muss ein anderer Broadcast her! + if (pObj->GetPage()!=NULL) { + SdrHint aHint(*pObj); + aHint.SetKind(HINT_OBJREMOVED); + pModel->Broadcast(aHint); + } + pModel->SetChanged(); + } + pObj->SetInserted(FALSE); // Ruft u.a. den UserCall + pObj->SetObjList(NULL); + pObj->SetPage(NULL); + if (!bObjOrdNumsDirty) { // Optimierung fuer den Fall, dass das letzte Obj rausgenommen wird + if (nObjNum!=ULONG(nAnz-1)) { + bObjOrdNumsDirty=TRUE; + } + } + SetRectsDirty(); + + if(pOwnerObj && !GetObjCount()) + { + // empty group created; it needs to be repainted since it's + // visualisation changes + pOwnerObj->ActionChanged(); + } + } + return pObj; +} + +SdrObject* SdrObjList::NbcReplaceObject(SdrObject* pNewObj, ULONG 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: Object zum Removen nicht gefunden"); + if (pObj!=NULL) { + DBG_ASSERT(pObj->IsInserted(),"SdrObjList::ReplaceObject: ZObjekt hat keinen Inserted-Status"); + 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); + + // #110094# 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, ULONG 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: Object zum Removen nicht gefunden"); + if (pObj!=NULL) { + DBG_ASSERT(pObj->IsInserted(),"SdrObjList::ReplaceObject: ZObjekt hat keinen Inserted-Status"); + if (pModel!=NULL) { + // Hier muss ein anderer Broadcast her! + 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); + + // #110094# Inform the parent about change to allow invalidations at + // evtl. existing parent visualisations + impChildInserted(*pNewObj); + + pNewObj->SetInserted(TRUE); + if (pModel!=NULL) { + // Hier muss ein anderer Broadcast her! + if (pNewObj->GetPage()!=NULL) { + SdrHint aHint(*pNewObj); + aHint.SetKind(HINT_OBJINSERTED); + pModel->Broadcast(aHint); + } + pModel->SetChanged(); + } + SetRectsDirty(); + } + return pObj; +} + +SdrObject* SdrObjList::NbcSetObjectOrdNum(ULONG nOldObjNum, ULONG 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::NbcSetObjectOrdNum: Object nicht gefunden"); + if (pObj!=NULL) { + DBG_ASSERT(pObj->IsInserted(),"SdrObjList::NbcSetObjectOrdNum: ZObjekt hat keinen Inserted-Status"); + RemoveObjectFromContainer(nOldObjNum); + + InsertObjectIntoContainer(*pObj,nNewObjNum); + + // #110094# 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; + } + return pObj; +} + +SdrObject* SdrObjList::SetObjectOrdNum(ULONG nOldObjNum, ULONG 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 nicht gefunden"); + if (pObj!=NULL) { + DBG_ASSERT(pObj->IsInserted(),"SdrObjList::SetObjectOrdNum: ZObjekt hat keinen Inserted-Status"); + RemoveObjectFromContainer(nOldObjNum); + InsertObjectIntoContainer(*pObj,nNewObjNum); + + // #110094#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) + { + // Hier muss ein anderer Broadcast her! + if (pObj->GetPage()!=NULL) pModel->Broadcast(SdrHint(*pObj)); + pModel->SetChanged(); + } + } + return pObj; +} + +const Rectangle& SdrObjList::GetAllObjSnapRect() const +{ + if (bRectsDirty) { + ((SdrObjList*)this)->RecalcRects(); + ((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 representate an invalid state, thus + // it's a step in the right direction. + if (bRectsDirty || aOutRect.IsEmpty()) + { + ((SdrObjList*)this)->RecalcRects(); + ((SdrObjList*)this)->bRectsDirty=FALSE; + } + return aOutRect; +} + +void SdrObjList::NbcReformatAllTextObjects() +{ + ULONG nAnz=GetObjCount(); + ULONG nNum=0; + + Printer* pPrinter = NULL; + + if (pModel) + { + if (pModel->GetRefDevice() && pModel->GetRefDevice()->GetOutDevType() == OUTDEV_PRINTER) + { + // Kein RefDevice oder RefDevice kein Printer + pPrinter = (Printer*) pModel->GetRefDevice(); + } + } + + while (nNum<nAnz) + { + SdrObject* pObj = GetObj(nNum); + if (pPrinter && + pObj->GetObjInventor() == SdrInventor && + pObj->GetObjIdentifier() == OBJ_OLE2 && + !( (SdrOle2Obj*) pObj )->IsEmpty() ) + { + //const SvInPlaceObjectRef& xObjRef = ((SdrOle2Obj*) pObj)->GetObjRef(); + //TODO/LATER: PrinterChangeNotification needed + //if( xObjRef.Is() && ( xObjRef->GetMiscStatus() & SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE ) ) + // xObjRef->OnDocumentPrinterChanged(pPrinter); + } + + pObj->NbcReformatText(); + nAnz=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 itselfs. + #103122# +*/ +void SdrObjList::ReformatAllEdgeObjects() +{ + const sal_uInt32 nCount=GetObjCount(); + sal_uInt32 nObj; + + for( nObj = 0; nObj < nCount; nObj++ ) + { + SdrObject* pObj = GetObj(nObj); + if( pObj->ISA(SdrEdgeObj) ) + static_cast<SdrEdgeObj*>(pObj)->Reformat(); + } +} + +void SdrObjList::BurnInStyleSheetAttributes() +{ + for(sal_uInt32 a(0L); a < GetObjCount(); a++) + { + GetObj(a)->BurnInStyleSheetAttributes(); + } +} + +ULONG SdrObjList::GetObjCount() const +{ + return maList.size(); +} + + + + +SdrObject* SdrObjList::GetObj(ULONG nNum) const +{ + if (nNum >= maList.size()) + { + OSL_ASSERT(nNum<maList.size()); + return NULL; + } + else + return maList[nNum]; +} + + + + +FASTBOOL SdrObjList::IsReadOnly() const +{ + FASTBOOL bRet=FALSE; + if (pPage!=NULL && pPage!=this) bRet=pPage->IsReadOnly(); + return bRet; +} + +ULONG SdrObjList::CountAllObjects() const +{ + ULONG nCnt=GetObjCount(); + ULONG nAnz=nCnt; + for (USHORT nNum=0; nNum<nAnz; nNum++) { + SdrObjList* pSubOL=GetObj(nNum)->GetSubList(); + if (pSubOL!=NULL) { + nCnt+=pSubOL->CountAllObjects(); + } + } + return nCnt; +} + +void SdrObjList::ForceSwapInObjects() const +{ + ULONG nObjAnz=GetObjCount(); + for (ULONG nObjNum=nObjAnz; nObjNum>0;) { + SdrObject* pObj=GetObj(--nObjNum); + SdrGrafObj* pGrafObj=PTR_CAST(SdrGrafObj,pObj); + if (pGrafObj!=NULL) { + pGrafObj->ForceSwapIn(); + } + SdrObjList* pOL=pObj->GetSubList(); + if (pOL!=NULL) { + pOL->ForceSwapInObjects(); + } + } +} + +void SdrObjList::ForceSwapOutObjects() const +{ + ULONG nObjAnz=GetObjCount(); + for (ULONG nObjNum=nObjAnz; nObjNum>0;) { + SdrObject* pObj=GetObj(--nObjNum); + SdrGrafObj* pGrafObj=PTR_CAST(SdrGrafObj,pObj); + if (pGrafObj!=NULL) { + pGrafObj->ForceSwapOut(); + } + SdrObjList* pOL=pObj->GetSubList(); + if (pOL!=NULL) { + pOL->ForceSwapOutObjects(); + } + } +} + +void SdrObjList::FlattenGroups() +{ + sal_Int32 nObj = GetObjCount(); + sal_Int32 i; + for( i=nObj-1; i>=0; --i) + UnGroupObj(i); +} + +void SdrObjList::UnGroupObj( ULONG nObjNum ) +{ + // if the given object is no group, this method is a noop + SdrObject* pUngroupObj = GetObj( nObjNum ); + if( pUngroupObj ) + { + SdrObjList* pSrcLst = pUngroupObj->GetSubList(); + //sal_Int32 nCount( 0 ); + 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 + sal_Int32 nInsertPos( pUngroupGroup->GetOrdNum() ); + + SdrObject* pObj; + sal_Int32 i, nAnz = pSrcLst->GetObjCount(); + for( i=0; i<nAnz; ++i ) + { + pObj = pSrcLst->RemoveObject(0); + SdrInsertReason aReason(SDRREASON_VIEWCALL, pUngroupGroup); + InsertObject(pObj, nInsertPos, &aReason); + ++nInsertPos; + } + + RemoveObject(nInsertPos); + } + } +#ifdef DBG_UTIL + else + DBG_ERROR("SdrObjList::UnGroupObj: object index invalid"); +#endif +} + + + + +bool SdrObjList::HasObjectNavigationOrder (void) const +{ + return mpNavigationOrder.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 (mpNavigationOrder.get() == NULL) + { + mpNavigationOrder.reset(new WeakSdrObjectContainerType(maList.size())); + ::std::copy( + maList.begin(), + maList.end(), + mpNavigationOrder->begin()); + } + OSL_ASSERT(mpNavigationOrder.get()!=NULL); + OSL_ASSERT( mpNavigationOrder->size() == maList.size()); + + SdrObjectWeakRef aReference (&rObject); + + // Look up the object whose navigation position is to be changed. + WeakSdrObjectContainerType::iterator iObject (::std::find( + mpNavigationOrder->begin(), + mpNavigationOrder->end(), + aReference)); + if (iObject == mpNavigationOrder->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(mpNavigationOrder->begin(), iObject); + if (nOldPosition != nNewPosition) + { + mpNavigationOrder->erase(iObject); + sal_uInt32 nInsertPosition (nNewPosition); + // Adapt insertion position for the just erased object. + if (nNewPosition >= nOldPosition) + nInsertPosition -= 1; + if (nInsertPosition >= mpNavigationOrder->size()) + mpNavigationOrder->push_back(aReference); + else + mpNavigationOrder->insert(mpNavigationOrder->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 mpNavigationOrder. + if (nNavigationPosition >= mpNavigationOrder->size()) + { + OSL_ASSERT(nNavigationPosition < mpNavigationOrder->size()); + } + else + return (*mpNavigationOrder)[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 (void) +{ + mpNavigationOrder.reset(); + mbIsNavigationOrderDirty = true; +} + + + + +bool SdrObjList::RecalcNavigationPositions (void) +{ + bool bUpToDate (false); + + if (mbIsNavigationOrderDirty) + { + if (mpNavigationOrder.get() != NULL) + { + mbIsNavigationOrderDirty = false; + + WeakSdrObjectContainerType::iterator iObject; + WeakSdrObjectContainerType::const_iterator iEnd (mpNavigationOrder->end()); + sal_uInt32 nIndex (0); + for (iObject=mpNavigationOrder->begin(); iObject!=iEnd; ++iObject,++nIndex) + (*iObject)->SetNavigationPosition(nIndex); + + bUpToDate = true; + } + } + + return mpNavigationOrder.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 (mpNavigationOrder.get() == NULL) + mpNavigationOrder.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; + (*mpNavigationOrder)[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(mpNavigationOrder->size()); + mpNavigationOrder->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( + mpNavigationOrder->begin(), + mpNavigationOrder->end(), + aReference)); + if (iObject != mpNavigationOrder->end()) + mpNavigationOrder->erase(iObject); + + mpNavigationOrder->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( + mpNavigationOrder->begin(), + mpNavigationOrder->end(), + aReference)); + if (iObject != mpNavigationOrder->end()) + mpNavigationOrder->erase(iObject); + mbIsNavigationOrderDirty = true; + } + + maList.erase(maList.begin()+nObjectPosition); + bObjOrdNumsDirty=TRUE; +} + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPageGridFrameList::Clear() +{ + USHORT nAnz=GetCount(); + for (USHORT i=0; i<nAnz; i++) { + delete GetObject(i); + } + aList.Clear(); +} + +////////////////////////////////////////////////////////////////////////////// +// #111111# 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); + } +} + +////////////////////////////////////////////////////////////////////////////// +// #110094# 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(XFILL_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; + } + } + } +} + +const SfxItemSet& SdrPageProperties::GetItemSet() const +{ + return *mpProperties; +} + +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); +} + +SfxStyleSheet* SdrPageProperties::GetStyleSheet() const +{ + return mpStyleSheet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrPage,SdrObjList); +DBG_NAME(SdrPage) +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), + mbSwappingLocked(false), + mbPageBorderOnlyLeftRight(false) +{ + DBG_CTOR(SdrPage,NULL); + 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), + mbSwappingLocked(rSrcPage.mbSwappingLocked), + mbPageBorderOnlyLeftRight(rSrcPage.mbPageBorderOnlyLeftRight) +{ + DBG_CTOR(SdrPage,NULL); + aPrefVisiLayers.SetAll(); + eListKind = (mbMaster) ? SDROBJLIST_MASTERPAGE : SDROBJLIST_DRAWPAGE; + + // copy things from source + // Warning: this leads to slicing (see issue 93186) and has to be + // removed as soon as possible. + *this = rSrcPage; + OSL_ENSURE(mpSdrPageProperties, + "SdrPage::SdrPage: operator= did not create needed SdrPageProperties (!)"); + + // be careful and correct eListKind, a member of SdrObjList which + // will be changed by the SdrOIbjList::operator= before... + eListKind = (mbMaster) ? SDROBJLIST_MASTERPAGE : SDROBJLIST_DRAWPAGE; + + // The previous assignment to *this may have resulted in a call to + // createUnoPage at a partially initialized (sliced) SdrPage object. + // Due to the vtable being not yet fully set-up at this stage, + // createUnoPage() may have been called at the wrong class. + // To force a call to the right createUnoPage() at a later time when the + // new object is full constructed mxUnoPage is disposed now. + uno::Reference<lang::XComponent> xComponent (mxUnoPage, uno::UNO_QUERY); + if (xComponent.is()) + { + mxUnoPage = NULL; + xComponent->dispose(); + } +} + +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(); + } + + // #111111# + // 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); + } + + // #111111# + // 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(); + + // #110094# + if(mpViewContact) + { + delete mpViewContact; + mpViewContact = 0L; + } + + { + delete mpSdrPageProperties; + mpSdrPageProperties = 0; + } + + DBG_DTOR(SdrPage,NULL); +} + +void SdrPage::operator=(const SdrPage& rSrcPage) +{ + if(mpViewContact) + { + delete mpViewContact; + mpViewContact = 0L; + } + + // Joe also sets some parameters for the class this one + // is derived from. SdrObjList does the same bad handling of + // copy constructor and operator=, so i better let it stand here. + pPage = this; + + // copy all the local parameters to make this instance + // a valid copy od source page before copying and inserting + // the contained objects + mbMaster = rSrcPage.mbMaster; + mbSwappingLocked = rSrcPage.mbSwappingLocked; + 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(); + } + //aMasters = rSrcPage.aMasters; + + mbObjectsNotPersistent = rSrcPage.mbObjectsNotPersistent; + + { + // #i111122# delete SdrPageProperties when model is different + if(mpSdrPageProperties && GetModel() != rSrcPage.GetModel()) + { + delete mpSdrPageProperties; + mpSdrPageProperties = 0; + } + + if(!mpSdrPageProperties) + { + mpSdrPageProperties = new SdrPageProperties(*this); + } + else + { + mpSdrPageProperties->ClearItem(0); + } + + if(!IsMasterPage()) + { + mpSdrPageProperties->PutItemSet(rSrcPage.getSdrPageProperties().GetItemSet()); + } + + mpSdrPageProperties->SetStyleSheet(rSrcPage.getSdrPageProperties().GetStyleSheet()); + } + + // Now copy the contained obejcts (by cloning them) + SdrObjList::operator=(rSrcPage); +} + +SdrPage* SdrPage::Clone() const +{ + return Clone(NULL); +} + +SdrPage* SdrPage::Clone(SdrModel* pNewModel) const +{ + if (pNewModel==NULL) pNewModel=pModel; + SdrPage* pPage2=new SdrPage(*pNewModel); + *pPage2=*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); +} + +INT32 SdrPage::GetWdt() const +{ + return nWdt; +} + +void SdrPage::SetOrientation(Orientation eOri) +{ + // Quadratisch ist und bleibt immer Portrait + 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 +{ + // Quadratisch ist Portrait + Orientation eRet=ORIENTATION_PORTRAIT; + Size aSiz(GetSize()); + if (aSiz.Width()>aSiz.Height()) eRet=ORIENTATION_LANDSCAPE; + return eRet; +} + +INT32 SdrPage::GetHgt() const +{ + return nHgt; +} + +void SdrPage::SetBorder(INT32 nLft, INT32 nUpp, INT32 nRgt, 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(INT32 nBorder) +{ + if(nBordLft != nBorder) + { + nBordLft = nBorder; + SetChanged(); + } +} + +void SdrPage::SetUppBorder(INT32 nBorder) +{ + if(nBordUpp != nBorder) + { + nBordUpp = nBorder; + SetChanged(); + } +} + +void SdrPage::SetRgtBorder(INT32 nBorder) +{ + if(nBordRgt != nBorder) + { + nBordRgt=nBorder; + SetChanged(); + } +} + +void SdrPage::SetLwrBorder(INT32 nBorder) +{ + if(nBordLwr != nBorder) + { + nBordLwr=nBorder; + SetChanged(); + } +} + +INT32 SdrPage::GetLftBorder() const +{ + return nBordLft; +} + +INT32 SdrPage::GetUppBorder() const +{ + return nBordUpp; +} + +INT32 SdrPage::GetRgtBorder() const +{ + return nBordRgt; +} + +INT32 SdrPage::GetLwrBorder() const +{ + return nBordLwr; +} + +void SdrPage::SetModel(SdrModel* pNewModel) +{ + SdrModel* pOldModel=pModel; + SdrObjList::SetModel(pNewModel); + if (pNewModel!=pOldModel) + { + if (pNewModel!=NULL) { + pLayerAdmin->SetParent(&pNewModel->GetLayerAdmin()); + } else { + pLayerAdmin->SetParent(NULL); + } + pLayerAdmin->SetModel(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(); + } +} + +USHORT SdrPage::GetPageNum() const +{ + if (!mbInserted) + return 0; + + if (mbMaster) { + if (pModel && pModel->IsMPgNumsDirty()) + ((SdrModel*)pModel)->RecalcPageNums(TRUE); + } else { + if (pModel && pModel->IsPagNumsDirty()) + ((SdrModel*)pModel)->RecalcPageNums(FALSE); + } + return nPageNum; +} + +void SdrPage::SetChanged() +{ + // #110094#-11 + // 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(); +} + +// #115423# 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; +} + +XubString SdrPage::GetLayoutName() const +{ + // Die wollte Dieter haben. + return String(); +} + +void SdrPage::SetInserted( bool bIns ) +{ + if( mbInserted != bIns ) + { + mbInserted = bIns; + + SdrObjListIter aIter( *this, IM_FLAT ); + while ( aIter.IsMore() ) + { + SdrObject* pObj = aIter.Next(); + if ( pObj->ISA(SdrOle2Obj) ) + { + if( mbInserted ) + ( (SdrOle2Obj*) pObj)->Connect(); + else + ( (SdrOle2Obj*) pObj)->Disconnect(); + } + } + } +} + + +uno::Reference< uno::XInterface > SdrPage::getUnoPage() +{ + // try weak reference first + 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(); +} + +FASTBOOL SdrPage::HasTransparentObjects( BOOL bCheckForAlphaChannel ) const +{ + FASTBOOL bRet = FALSE; + + for( ULONG n = 0, nCount = GetObjCount(); ( n < nCount ) && !bRet; n++ ) + if( GetObj( n )->IsTransparent( bCheckForAlphaChannel ) ) + bRet = TRUE; + + return bRet; +} + +/** 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(XFILL_NONE == ((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; +} + +// #110094# 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(); + } +} + +// NYI: Dummy implementations for declarations in svdpage.hxx +Bitmap SdrPage::GetBitmap(const SetOfByte& /*rVisibleLayers*/, FASTBOOL /*bTrimBorders*/) const +{ + DBG_ASSERT(0, "SdrPage::GetBitmap(): not yet implemented."); + return Bitmap(); +} +GDIMetaFile SdrPage::GetMetaFile(const SetOfByte& /*rVisibleLayers*/, FASTBOOL /*bTrimBorders*/) +{ + DBG_ASSERT(0, "SdrPage::GetMetaFile(): not yet implemented."); + return GDIMetaFile(); +} + +bool SdrPage::isHandoutMasterPage() const +{ + return mbMaster && GetModel() && GetModel()->GetMasterPageCount() + && GetModel()->GetMasterPage(0) == this; +} + +////////////////////////////////////////////////////////////////////////////// +// sdr::Comment interface + +const sdr::Comment& SdrPage::GetCommentByIndex(sal_uInt32 nIndex) +{ + DBG_ASSERT(nIndex < maComments.size(), "SdrPage::GetCommentByIndex: Access out of range (!)"); + return maComments[nIndex]; +} + +void SdrPage::AddComment(const sdr::Comment& rNew) +{ + maComments.push_back(rNew); + ::std::sort(maComments.begin(), maComments.end()); +} + +void SdrPage::ReplaceCommentByIndex(sal_uInt32 nIndex, const sdr::Comment& rNew) +{ + DBG_ASSERT(nIndex < maComments.size(), "SdrPage::GetCommentByIndex: Access out of range (!)"); + + if(maComments[nIndex] != rNew) + { + maComments[nIndex] = rNew; + ::std::sort(maComments.begin(), maComments.end()); + } +} + +////////////////////////////////////////////////////////////////////////////// +// 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); + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdpagv.cxx b/svx/source/svdraw/svdpagv.cxx new file mode 100644 index 000000000000..bad1401c2305 --- /dev/null +++ b/svx/source/svdraw/svdpagv.cxx @@ -0,0 +1,1122 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/svdpagv.hxx> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <comphelper/processfactory.hxx> +#include <svx/svdoutl.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdview.hxx> + +#include <svx/svdedxv.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdpagv.hxx> +#include <editeng/outliner.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdview.hxx> +#include "svditer.hxx" +#include <svx/svdogrp.hxx> +#include <svx/svdtypes.hxx> + +#include <svx/svdotext.hxx> // fuer PaintOutlinerView +#include <svx/svdoole2.hxx> + +// #110094# +#include <svx/sdr/contact/objectcontactofpageview.hxx> +#include <svx/svdogrp.hxx> +#include <svx/sdr/contact/viewobjectcontactredirector.hxx> +#include <svx/fmview.hxx> + +// for search on vector +#include <algorithm> + +using namespace ::rtl; +using namespace ::com::sun::star; +#include <svx/sdrpagewindow.hxx> +#include <sdrpaintwindow.hxx> + +TYPEINIT1(SdrPageView, SfxListener); +DBG_NAME(SdrPageView); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// interface to SdrPageWindow + +SdrPageWindow* SdrPageView::FindPageWindow(SdrPaintWindow& rPaintWindow) const +{ + for(SdrPageWindowVector::const_iterator a = maPageWindows.begin(); a != maPageWindows.end(); a++) + { + if(&((*a)->GetPaintWindow()) == &rPaintWindow) + { + return *a; + } + } + + return 0L; +} + +const SdrPageWindow* SdrPageView::FindPatchedPageWindow( const OutputDevice& _rOutDev ) const +{ + for ( SdrPageWindowVector::const_iterator loop = maPageWindows.begin(); + loop != maPageWindows.end(); + ++loop + ) + { + const SdrPageWindow& rPageWindow( *(*loop) ); + const SdrPaintWindow& rPaintWindow( rPageWindow.GetOriginalPaintWindow() ? *rPageWindow.GetOriginalPaintWindow() : rPageWindow.GetPaintWindow() ); + if ( &rPaintWindow.GetOutputDevice() == &_rOutDev ) + { + return &rPageWindow; + } + } + + return NULL; +} + +SdrPageWindow* SdrPageView::FindPageWindow(const OutputDevice& rOutDev) const +{ + for(SdrPageWindowVector::const_iterator a = maPageWindows.begin(); a != maPageWindows.end(); a++) + { + if(&((*a)->GetPaintWindow().GetOutputDevice()) == &rOutDev) + { + return *a; + } + } + + return 0L; +} + +SdrPageWindow* SdrPageView::GetPageWindow(sal_uInt32 nIndex) const +{ + // #126416# + if(nIndex < maPageWindows.size()) + { + return maPageWindows[nIndex]; + } + + return 0L; +} + +void SdrPageView::ClearPageWindows() +{ + // #126416# + for(SdrPageWindowVector::const_iterator a = maPageWindows.begin(); a != maPageWindows.end(); a++) + { + delete *a; + } + + maPageWindows.clear(); +} + +void SdrPageView::AppendPageWindow(SdrPageWindow& rNew) +{ + maPageWindows.push_back(&rNew); +} + +SdrPageWindow* SdrPageView::RemovePageWindow(sal_uInt32 nPos) +{ + if(nPos < maPageWindows.size()) + { + SdrPageWindowVector::iterator aAccess = maPageWindows.begin() + nPos; + // #114376# remember return value + SdrPageWindow* pErasedSdrPageWindow = *aAccess; + maPageWindows.erase(aAccess); + return pErasedSdrPageWindow; + } + + return 0L; +} + +SdrPageWindow* SdrPageView::RemovePageWindow(SdrPageWindow& rOld) +{ + const SdrPageWindowVector::iterator aFindResult = ::std::find(maPageWindows.begin(), maPageWindows.end(), &rOld); + + if(aFindResult != maPageWindows.end()) + { + // #114376# remember return value + SdrPageWindow* pSdrPageWindow = *aFindResult; + maPageWindows.erase(aFindResult); + return pSdrPageWindow; + } + + return 0L; +} + +////////////////////////////////////////////////////////////////////////////// + +SdrPageView::SdrPageView(SdrPage* pPage1, SdrView& rNewView) +: mrView(rNewView), + // #103911# col_auto color lets the view takes the default SvxColorConfig entry + maDocumentColor( COL_AUTO ), + maBackgroundColor(COL_AUTO ), // #i48367# also react on autocolor + mpPreparedPageWindow(0) // #i72752# +{ + DBG_CTOR(SdrPageView,NULL); + mpPage = pPage1; + + if(mpPage) + { + aPgOrg.X()=mpPage->GetLftBorder(); + aPgOrg.Y()=mpPage->GetUppBorder(); + } + mbHasMarked = sal_False; + aLayerVisi.SetAll(); + aLayerPrn.SetAll(); + + mbVisible = sal_False; + pAktList = NULL; + pAktGroup = NULL; + SetAktGroupAndList(NULL, mpPage); + + StartListening(*rNewView.GetModel()); + + for(sal_uInt32 a(0L); a < rNewView.PaintWindowCount(); a++) + { + AddPaintWindowToPageView(*rNewView.GetPaintWindow(a)); + } +} + +SdrPageView::~SdrPageView() +{ + DBG_DTOR(SdrPageView,NULL); + + // cleanup window vector + ClearPageWindows(); +} + +SdrPageWindow& SdrPageView::CreateNewPageWindowEntry(SdrPaintWindow& rPaintWindow) +{ + // MIB 3.7.08: Das WinRec muss sofort in die Liste eingetragen werden, + // weil sich das InsertControlContainer darauf verlaesst + //SdrPageViewWinRec* pRec = new SdrPageViewWinRec( *this, pOut ); + //pWinList->Insert(pRec); + SdrPageWindow& rWindow = *(new SdrPageWindow(*this, rPaintWindow)); + AppendPageWindow(rWindow); + + return rWindow; +} + +void SdrPageView::AddPaintWindowToPageView(SdrPaintWindow& rPaintWindow) +{ + if(!FindPageWindow(rPaintWindow)) + { + CreateNewPageWindowEntry(rPaintWindow); + } +} + +void SdrPageView::RemovePaintWindowFromPageView(SdrPaintWindow& rPaintWindow) +{ + SdrPageWindow* pCandidate = FindPageWindow(rPaintWindow); + + if(pCandidate) + { + pCandidate = RemovePageWindow(*pCandidate); + + if(pCandidate) + { + delete pCandidate; + } + } +} + +::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlContainer > SdrPageView::GetControlContainer( const OutputDevice& _rDevice ) const +{ + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlContainer > xReturn; + const SdrPageWindow* pCandidate = FindPatchedPageWindow( _rDevice ); + + if ( pCandidate ) + xReturn = pCandidate->GetControlContainer( true ); + + return xReturn; +} + +void __EXPORT SdrPageView::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& /*rHint*/) +{ + // not really interested in +} + +void SdrPageView::ModelHasChanged() +{ + if (GetAktGroup()!=NULL) CheckAktGroup(); +} + +sal_Bool SdrPageView::IsReadOnly() const +{ + return (0L == GetPage() || GetView().GetModel()->IsReadOnly() || GetPage()->IsReadOnly() || GetObjList()->IsReadOnly()); +} + +void SdrPageView::Show() +{ + if(!IsVisible()) + { + mbVisible = sal_True; + InvalidateAllWin(); + + for(sal_uInt32 a(0L); a < GetView().PaintWindowCount(); a++) + { + AddPaintWindowToPageView(*GetView().GetPaintWindow(a)); + } + } +} + +void SdrPageView::Hide() +{ + if(IsVisible()) + { + InvalidateAllWin(); + mbVisible = sal_False; + ClearPageWindows(); + } +} + +Rectangle SdrPageView::GetPageRect() const +{ + if (GetPage()==NULL) return Rectangle(); + return Rectangle(Point(),Size(GetPage()->GetWdt()+1,GetPage()->GetHgt()+1)); +} + +void SdrPageView::InvalidateAllWin() +{ + if(IsVisible() && GetPage()) + { + Rectangle aRect(Point(0,0),Size(GetPage()->GetWdt()+1,GetPage()->GetHgt()+1)); + aRect.Union(GetPage()->GetAllObjBoundRect()); + GetView().InvalidateAllWin(aRect); + } +} + +void SdrPageView::InvalidateAllWin(const Rectangle& rRect, sal_Bool bPlus1Pix) +{ + if(IsVisible()) + { + GetView().InvalidateAllWin(rRect, bPlus1Pix); + } +} + +void SdrPageView::PaintOutlinerView(OutputDevice* pOut, const Rectangle& rRect) const +{ + if (GetView().pTextEditOutliner==NULL) return; + //const SdrObject* pTextObjTmp=GetView().GetTextEditObject(); + //const SdrTextObj* pText=PTR_CAST(SdrTextObj,pTextObjTmp); + //FASTBOOL bTextFrame=pText!=NULL && pText->IsTextFrame(); + ULONG nViewAnz=GetView().pTextEditOutliner->GetViewCount(); + for (ULONG i=0; i<nViewAnz; i++) { + OutlinerView* pOLV=GetView().pTextEditOutliner->GetView(i); + if (pOLV->GetWindow()==pOut) { + GetView().ImpPaintOutlinerView(*pOLV, rRect); + return; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPageView::PrePaint() +{ + const sal_uInt32 nCount(PageWindowCount()); + + for(sal_uInt32 a(0); a < nCount; a++) + { + SdrPageWindow* pCandidate = GetPageWindow(a); + + if(pCandidate) + { + pCandidate->PrePaint(); + } + } +} + +void SdrPageView::CompleteRedraw(SdrPaintWindow& rPaintWindow, const Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector) const +{ + if(GetPage()) + { + SdrPageWindow* pPageWindow = FindPageWindow(rPaintWindow); + sal_Bool bIsTempTarget(sal_False); + + if(!pPageWindow) + { + // create temp PageWindow + pPageWindow = new SdrPageWindow(*((SdrPageView*)this), rPaintWindow); + bIsTempTarget = sal_True; + } + + // do the redraw + pPageWindow->PrepareRedraw(rReg); + pPageWindow->RedrawAll(pRedirector); + + // get rid of temp PageWindow + if(bIsTempTarget) + { + delete pPageWindow; + pPageWindow = 0L; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i74769# use SdrPaintWindow directly + +void SdrPageView::setPreparedPageWindow(SdrPageWindow* pKnownTarget) +{ + // #i72752# remember prepared SdrPageWindow + mpPreparedPageWindow = pKnownTarget; +} + +void SdrPageView::DrawLayer(SdrLayerID nID, OutputDevice* pGivenTarget, sdr::contact::ViewObjectContactRedirector* pRedirector) const +{ + if(GetPage()) + { + if(pGivenTarget) + { + const SdrPageWindow* pKnownTarget = FindPageWindow(*pGivenTarget); + + if(pKnownTarget) + { + // paint known target + pKnownTarget->RedrawLayer(&nID, pRedirector); + } + else + { + // #i72752# DrawLayer() uses a OutputDevice different from BeginDrawLayer. This happens + // e.g. when SW paints a single text line in text edit mode. Try to use it + SdrPageWindow* pPreparedTarget = mpPreparedPageWindow; + + if(pPreparedTarget) + { + // if we have a prepared target, do not use a new SdrPageWindow since this + // works but is expensive. Just use a temporary PaintWindow + SdrPaintWindow aTemporaryPaintWindow(mrView, *pGivenTarget); + + // Copy existing paint region to use the same as prepared in BeginDrawLayer + SdrPaintWindow& rExistingPaintWindow = pPreparedTarget->GetPaintWindow(); + const Region& rExistingRegion = rExistingPaintWindow.GetRedrawRegion(); + aTemporaryPaintWindow.SetRedrawRegion(rExistingRegion); + + // patch the ExistingPageWindow + pPreparedTarget->patchPaintWindow(aTemporaryPaintWindow); + + // redraw the layer + pPreparedTarget->RedrawLayer(&nID, pRedirector); + + // restore the ExistingPageWindow + pPreparedTarget->unpatchPaintWindow(); + } + else + { + OSL_ENSURE(false, "SdrPageView::DrawLayer: Creating temporary SdrPageWindow (ObjectContact), this should never be needed (!)"); + + // None of the known OutputDevices is the target of this paint, use + // a temporary SdrPageWindow for this Redraw. + SdrPaintWindow aTemporaryPaintWindow(mrView, *pGivenTarget); + SdrPageWindow aTemporaryPageWindow(*((SdrPageView*)this), aTemporaryPaintWindow); + + // #i72752# + // Copy existing paint region if other PageWindows exist, this was created by + // PrepareRedraw() from BeginDrawLayer(). Needs to be used e.g. when suddenly SW + // paints into an unknown device other than the view was created for (e.g. VirtualDevice) + if(PageWindowCount()) + { + SdrPageWindow* pExistingPageWindow = GetPageWindow(0L); + SdrPaintWindow& rExistingPaintWindow = pExistingPageWindow->GetPaintWindow(); + const Region& rExistingRegion = rExistingPaintWindow.GetRedrawRegion(); + aTemporaryPaintWindow.SetRedrawRegion(rExistingRegion); + } + + aTemporaryPageWindow.RedrawLayer(&nID, pRedirector); + } + } + } + else + { + // paint in all known windows + for(sal_uInt32 a(0L); a < PageWindowCount(); a++) + { + SdrPageWindow* pTarget = GetPageWindow(a); + pTarget->RedrawLayer(&nID, pRedirector); + } + } + } +} + +void SdrPageView::SetDesignMode( bool _bDesignMode ) const +{ + for ( sal_uInt32 i = 0L; i < PageWindowCount(); ++i ) + { + const SdrPageWindow& rPageViewWindow = *GetPageWindow(i); + rPageViewWindow.SetDesignMode( _bDesignMode ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef OS2 +#define RGBCOLOR(r,g,b) ((ULONG)(((BYTE)(b) | ((USHORT)(g)<<8)) | (((ULONG)(BYTE)(r))<<16))) +#endif + +void SdrPageView::DrawPageViewGrid(OutputDevice& rOut, const Rectangle& rRect, Color aColor) +{ + if (GetPage()==NULL) + return; + + long nx1=GetView().aGridBig.Width(); + long nx2=GetView().aGridFin.Width(); + long ny1=GetView().aGridBig.Height(); + long ny2=GetView().aGridFin.Height(); + + if (nx1==0) nx1=nx2; + if (nx2==0) nx2=nx1; + if (ny1==0) ny1=ny2; + if (ny2==0) ny2=ny1; + if (nx1==0) { nx1=ny1; nx2=ny2; } + if (ny1==0) { ny1=nx1; ny2=nx2; } + if (nx1<0) nx1=-nx1; + if (nx2<0) nx2=-nx2; + if (ny1<0) ny1=-ny1; + if (ny2<0) ny2=-ny2; + + if (nx1!=0) + { + // no more global output size, use window size instead to decide grid sizes + long nScreenWdt = rOut.GetOutputSizePixel().Width(); + // old: long nScreenWdt=System::GetDesktopRectPixel().GetWidth(); + + // Grid bei kleinen Zoomstufen etwas erweitern + //Size a1PixSiz(rOut.PixelToLogic(Size(1,1))); + long nMinDotPix=2; + long nMinLinPix=4; + + if (nScreenWdt>=1600) + { + nMinDotPix=4; + nMinLinPix=8; + } + else if (nScreenWdt>=1024) + { + nMinDotPix=3; + nMinLinPix=6; + } + else + { // z.B. 640x480 + nMinDotPix=2; + nMinLinPix=4; + } + Size aMinDotDist(rOut.PixelToLogic(Size(nMinDotPix,nMinDotPix))); + //Size a3PixSiz(rOut.PixelToLogic(Size(2,2))); + Size aMinLinDist(rOut.PixelToLogic(Size(nMinLinPix,nMinLinPix))); + FASTBOOL bHoriSolid=nx2<aMinDotDist.Width(); + FASTBOOL bVertSolid=ny2<aMinDotDist.Height(); + // Linienabstand vergroessern (mind. 4 Pixel) + // Vergroesserung: *2 *5 *10 *20 *50 *100 ... + int nTgl=0; + long nVal0=nx1; + while (nx1<aMinLinDist.Width()) + { + long a=nx1; + + if (nTgl==0) nx1*=2; + if (nTgl==1) nx1=nVal0*5; // => nx1*=2.5 + if (nTgl==2) nx1*=2; + + nVal0=a; + nTgl++; if (nTgl>=3) nTgl=0; + } + nTgl=0; + nVal0=ny1; + while (ny1<aMinLinDist.Height()) + { + long a=ny1; + + if (nTgl==0) ny1*=2; + if (nTgl==1) ny1=nVal0*5; // => ny1*=2.5 + if (nTgl==2) ny1*=2; + + nVal0=a; + nTgl++; + + if (nTgl>=3) nTgl=0; + } + // Keine Zwischenpunkte, wenn... + //if (nx2<a2PixSiz.Width()) nx2=nx1; + //if (ny2<a2PixSiz.Height()) ny2=ny1; + + FASTBOOL bHoriFine=nx2<nx1; + FASTBOOL bVertFine=ny2<ny1; + FASTBOOL bHoriLines=bHoriSolid || bHoriFine || !bVertFine; + FASTBOOL bVertLines=bVertSolid || bVertFine; + + Color aColorMerk( rOut.GetLineColor() ); + rOut.SetLineColor( aColor ); + + bool bMap0=rOut.IsMapModeEnabled(); +#ifdef WIN // SetPixel-Profiling fuer Windows + COLORREF aWinColRef=PALETTERGB(aColor.GetRed()>>8,aColor.GetGreen()>>8,aColor.GetBlue()>>8); + HDC aWinhDC=Sysdepen::GethDC(rOut); +#endif + + long nWrX=0;//aWriterPageOffset.X(); + long nWrY=0;//aWriterPageOffset.Y(); + Point aOrg(aPgOrg); + long x1=GetPage()->GetLftBorder()+1+nWrX; + long x2=GetPage()->GetWdt()-GetPage()->GetRgtBorder()-1+nWrY; + long y1=GetPage()->GetUppBorder()+1+nWrX; + long y2=GetPage()->GetHgt()-GetPage()->GetLwrBorder()-1+nWrY; + const SdrPageGridFrameList* pFrames=GetPage()->GetGridFrameList(this,NULL); + //USHORT nBufSiz=1024; // 4k Buffer = max. 512 Punkte + // #90353# long* pBuf = NULL; + USHORT nGridPaintAnz=1; + if (pFrames!=NULL) nGridPaintAnz=pFrames->GetCount(); + for (USHORT nGridPaintNum=0; nGridPaintNum<nGridPaintAnz; nGridPaintNum++) { + if (pFrames!=NULL) { + const SdrPageGridFrame& rGF=(*pFrames)[nGridPaintNum]; + nWrX=rGF.GetPaperRect().Left(); + nWrY=rGF.GetPaperRect().Top(); + x1=rGF.GetUserArea().Left(); + x2=rGF.GetUserArea().Right(); + y1=rGF.GetUserArea().Top(); + y2=rGF.GetUserArea().Bottom(); + aOrg=rGF.GetUserArea().TopLeft(); + aOrg-=rGF.GetPaperRect().TopLeft(); + } + if (!rRect.IsEmpty()) { + Size a1PixSiz(rOut.PixelToLogic(Size(1,1))); + long nX1Pix=a1PixSiz.Width(); // 1 Pixel Toleranz drauf + long nY1Pix=a1PixSiz.Height(); + if (x1<rRect.Left() -nX1Pix) x1=rRect.Left() -nX1Pix; + if (x2>rRect.Right() +nX1Pix) x2=rRect.Right() +nX1Pix; + if (y1<rRect.Top() -nY1Pix) y1=rRect.Top() -nY1Pix; + if (y2>rRect.Bottom()+nY1Pix) y2=rRect.Bottom()+nY1Pix; + } + Point aPnt; + + long xBigOrg=aOrg.X()+nWrX; + while (xBigOrg>=x1) xBigOrg-=nx1; + while (xBigOrg<x1) xBigOrg+=nx1; + long xFinOrg=xBigOrg; + while (xFinOrg>=x1) xFinOrg-=nx2; + while (xFinOrg<x1) xFinOrg+=nx2; + + long yBigOrg=aOrg.Y()+nWrY; + while (yBigOrg>=y1) yBigOrg-=ny1; + while (yBigOrg<y1) yBigOrg+=ny1; + long yFinOrg=yBigOrg; + while (yFinOrg>=y1) yFinOrg-=ny2; + while (yFinOrg<y1) yFinOrg+=ny2; + + if( x1 <= x2 && y1 <= y2 ) + { + if( bHoriLines ) + { + ULONG nGridFlags = ( bHoriSolid ? GRID_HORZLINES : GRID_DOTS ); + UINT16 nSteps = sal_uInt16(nx1 / nx2); + UINT32 nRestPerStepMul1000 = nSteps ? ( ((nx1 * 1000L)/ nSteps) - (nx2 * 1000L) ) : 0; + UINT32 nStepOffset = 0; + UINT16 nPointOffset = 0; + + for(UINT16 a=0;a<nSteps;a++) + { + // Zeichnen + rOut.DrawGrid( + Rectangle( xFinOrg + (a * nx2) + nPointOffset, yBigOrg, x2, y2 ), + Size( nx1, ny1 ), nGridFlags ); + + // Schritt machen + nStepOffset += nRestPerStepMul1000; + while(nStepOffset >= 1000) + { + nStepOffset -= 1000; + nPointOffset++; + } + } + } + + if( bVertLines ) + { + ULONG nGridFlags = ( bVertSolid ? GRID_VERTLINES : GRID_DOTS ); + UINT16 nSteps = sal_uInt16(ny1 / ny2); + UINT32 nRestPerStepMul1000 = nSteps ? ( ((ny1 * 1000L)/ nSteps) - (ny2 * 1000L) ) : 0; + UINT32 nStepOffset = 0; + UINT16 nPointOffset = 0; + + for(UINT16 a=0;a<nSteps;a++) + { + // Zeichnen + rOut.DrawGrid( + Rectangle( xBigOrg, yFinOrg + (a * ny2) + nPointOffset, x2, y2 ), + Size( nx1, ny1 ), nGridFlags ); + + // Schritt machen + nStepOffset += nRestPerStepMul1000; + while(nStepOffset >= 1000) + { + nStepOffset -= 1000; + nPointOffset++; + } + } + + // rOut.DrawGrid( Rectangle( xo + xBigOrg, yo + yFinOrg, x2, y2 ), Size( nx1, ny2 ), nGridFlags ); + } + } + } + + rOut.EnableMapMode(bMap0); + rOut.SetLineColor(aColorMerk); + } +} + +void SdrPageView::AdjHdl() +{ + GetView().AdjustMarkHdl(); +} + +void SdrPageView::SetLayer(const XubString& rName, SetOfByte& rBS, sal_Bool bJa) +{ + if(!GetPage()) + return; + + SdrLayerID nID = GetPage()->GetLayerAdmin().GetLayerID(rName, sal_True); + + if(SDRLAYER_NOTFOUND != nID) + rBS.Set(nID, bJa); +} + +sal_Bool SdrPageView::IsLayer(const XubString& rName, const SetOfByte& rBS) const +{ + if(!GetPage()) + return sal_False; + + sal_Bool bRet(sal_False); + + if(rName.Len()) + { + SdrLayerID nId = GetPage()->GetLayerAdmin().GetLayerID(rName, sal_True); + + if(SDRLAYER_NOTFOUND != nId) + { + bRet = rBS.IsSet(nId); + } + } + + return bRet; +} + +void SdrPageView::SetAllLayers(SetOfByte& rB, sal_Bool bJa) +{ + if(bJa) + { + rB.SetAll(); + rB.Clear(SDRLAYER_NOTFOUND); + } + else + { + rB.ClearAll(); + } +} + +sal_Bool SdrPageView::IsObjMarkable(SdrObject* pObj) const +{ + if(pObj) + { + // Vom Markieren ausgeschlossen? + if(pObj->IsMarkProtect()) + { + return sal_False; + } + + // only visible are markable + if( !pObj->IsVisible() ) + { + return sal_False; + } + + // #112440# + if(pObj->ISA(SdrObjGroup)) + { + // If object is a Group object, visibility depends evtl. on + // multiple layers. If one object is markable, Group is markable. + SdrObjList* pObjList = ((SdrObjGroup*)pObj)->GetSubList(); + + if(pObjList && pObjList->GetObjCount()) + { + sal_Bool bGroupIsMarkable(sal_False); + + for(sal_uInt32 a(0L); !bGroupIsMarkable && a < pObjList->GetObjCount(); a++) + { + SdrObject* pCandidate = pObjList->GetObj(a); + + // call recursively + if(IsObjMarkable(pCandidate)) + { + bGroupIsMarkable = sal_True; + } + } + + return bGroupIsMarkable; + } + else + { + // #i43302# + // Allow empty groups to be selected to be able to delete them + return sal_True; + } + } + else + { + // Der Layer muss sichtbar und darf nicht gesperrt sein + SdrLayerID nL = pObj->GetLayer(); + return (aLayerVisi.IsSet(BYTE(nL)) && !aLayerLock.IsSet(BYTE(nL))); + } + } + + return sal_False; +} + +void SdrPageView::SetPageOrigin(const Point& rOrg) +{ + if (rOrg!=aPgOrg) { + aPgOrg=rOrg; + if (GetView().IsGridVisible()) { + InvalidateAllWin(); + } + } +} + +void SdrPageView::ImpInvalidateHelpLineArea(USHORT nNum) const +{ + if (GetView().IsHlplVisible() && nNum<aHelpLines.GetCount()) { + const SdrHelpLine& rHL=aHelpLines[nNum]; + + for(sal_uInt32 a(0L); a < GetView().PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = GetView().GetPaintWindow(a); + + if(pCandidate->OutputToWindow()) + { + OutputDevice& rOutDev = pCandidate->GetOutputDevice(); + Rectangle aR(rHL.GetBoundRect(rOutDev)); + Size aSiz(rOutDev.PixelToLogic(Size(1,1))); + aR.Left() -= aSiz.Width(); + aR.Right() += aSiz.Width(); + aR.Top() -= aSiz.Height(); + aR.Bottom() += aSiz.Height(); + ((SdrView&)GetView()).InvalidateOneWin((Window&)rOutDev, aR); + } + } + } +} + +void SdrPageView::SetHelpLines(const SdrHelpLineList& rHLL) +{ + aHelpLines=rHLL; + InvalidateAllWin(); +} + +void SdrPageView::SetHelpLine(USHORT nNum, const SdrHelpLine& rNewHelpLine) +{ + if (nNum<aHelpLines.GetCount() && aHelpLines[nNum]!=rNewHelpLine) { + FASTBOOL bNeedRedraw=TRUE; + if (aHelpLines[nNum].GetKind()==rNewHelpLine.GetKind()) { + switch (rNewHelpLine.GetKind()) { + case SDRHELPLINE_VERTICAL : if (aHelpLines[nNum].GetPos().X()==rNewHelpLine.GetPos().X()) bNeedRedraw=FALSE; break; + case SDRHELPLINE_HORIZONTAL: if (aHelpLines[nNum].GetPos().Y()==rNewHelpLine.GetPos().Y()) bNeedRedraw=FALSE; break; + default: break; + } // switch + } + if (bNeedRedraw) ImpInvalidateHelpLineArea(nNum); + aHelpLines[nNum]=rNewHelpLine; + if (bNeedRedraw) ImpInvalidateHelpLineArea(nNum); + } +} + +void SdrPageView::DeleteHelpLine(USHORT nNum) +{ + if (nNum<aHelpLines.GetCount()) { + ImpInvalidateHelpLineArea(nNum); + aHelpLines.Delete(nNum); + } +} + +void SdrPageView::InsertHelpLine(const SdrHelpLine& rHL, USHORT nNum) +{ + if (nNum>aHelpLines.GetCount()) nNum=aHelpLines.GetCount(); + aHelpLines.Insert(rHL,nNum); + if (GetView().IsHlplVisible()) { + if (GetView().IsHlplFront()) { + // Hier optimieren ... + ImpInvalidateHelpLineArea(nNum); + } else { + ImpInvalidateHelpLineArea(nNum); + } + } +} + +// Betretene Gruppe und Liste setzen +void SdrPageView::SetAktGroupAndList(SdrObject* pNewGroup, SdrObjList* pNewList) +{ + if(pAktGroup != pNewGroup) + { + pAktGroup = pNewGroup; + } + if(pAktList != pNewList) + { + pAktList = pNewList; + } +} + +sal_Bool SdrPageView::EnterGroup(SdrObject* pObj) +{ + sal_Bool bRet(sal_False); + + if(pObj && pObj->IsGroupObject()) + { + sal_Bool bGlueInvalidate(GetView().ImpIsGlueVisible()); + + if(bGlueInvalidate) + { + GetView().GlueInvalidate(); + } + + // deselect all + GetView().UnmarkAll(); + + // set current group and list + SdrObjList* pNewObjList = pObj->GetSubList(); + SetAktGroupAndList(pObj, pNewObjList); + + // select contained object if only one object is contained, + // else select nothing and let the user decide what to do next + if(pNewObjList && pNewObjList->GetObjCount() == 1) + { + SdrObject* pFirstObject = pNewObjList->GetObj(0L); + + if(GetView().GetSdrPageView()) + { + GetView().MarkObj(pFirstObject, GetView().GetSdrPageView()); + } + } + + // build new handles + GetView().AdjustMarkHdl(); + + // invalidate only when view wants to visualize group entering + if(GetView().DoVisualizeEnteredGroup()) + { + InvalidateAllWin(); + } + + if (bGlueInvalidate) + { + GetView().GlueInvalidate(); + } + + bRet = sal_True; + } + + return bRet; +} + +void SdrPageView::LeaveOneGroup() +{ + if(GetAktGroup()) + { + BOOL bGlueInvalidate = (GetView().ImpIsGlueVisible()); + + if(bGlueInvalidate) + GetView().GlueInvalidate(); + + SdrObject* pLastGroup = GetAktGroup(); + SdrObject* pParentGroup = GetAktGroup()->GetUpGroup(); + SdrObjList* pParentList = GetPage(); + + if(pParentGroup) + pParentList = pParentGroup->GetSubList(); + + // Alles deselektieren + GetView().UnmarkAll(); + + // Zuweisungen, pAktGroup und pAktList muessen gesetzt sein + SetAktGroupAndList(pParentGroup, pParentList); + + // gerade verlassene Gruppe selektieren + if(pLastGroup) + if(GetView().GetSdrPageView()) + GetView().MarkObj(pLastGroup, GetView().GetSdrPageView()); + + GetView().AdjustMarkHdl(); + + // invalidate only when view wants to visualize group entering + if(GetView().DoVisualizeEnteredGroup()) + InvalidateAllWin(); + + if(bGlueInvalidate) + GetView().GlueInvalidate(); + } +} + +void SdrPageView::LeaveAllGroup() +{ + if(GetAktGroup()) + { + BOOL bGlueInvalidate = (GetView().ImpIsGlueVisible()); + + if(bGlueInvalidate) + GetView().GlueInvalidate(); + + SdrObject* pLastGroup = GetAktGroup(); + + // Alles deselektieren + GetView().UnmarkAll(); + + // Zuweisungen, pAktGroup und pAktList muessen gesetzt sein + SetAktGroupAndList(NULL, GetPage()); + + // Oberste letzte Gruppe finden und selektieren + if(pLastGroup) + { + while(pLastGroup->GetUpGroup()) + pLastGroup = pLastGroup->GetUpGroup(); + + if(GetView().GetSdrPageView()) + GetView().MarkObj(pLastGroup, GetView().GetSdrPageView()); + } + + GetView().AdjustMarkHdl(); + + // invalidate only when view wants to visualize group entering + if(GetView().DoVisualizeEnteredGroup()) + InvalidateAllWin(); + + if(bGlueInvalidate) + GetView().GlueInvalidate(); + } +} + +USHORT SdrPageView::GetEnteredLevel() const +{ + USHORT nAnz=0; + SdrObject* pGrp=GetAktGroup(); + while (pGrp!=NULL) { + nAnz++; + pGrp=pGrp->GetUpGroup(); + } + return nAnz; +} + +XubString SdrPageView::GetActualGroupName() const +{ + if(GetAktGroup()) + { + XubString aStr(GetAktGroup()->GetName()); + + if(!aStr.Len()) + aStr += sal_Unicode('?'); + + return aStr; + } + else + return String(); +} + +XubString SdrPageView::GetActualPathName(sal_Unicode cSep) const +{ + XubString aStr; + BOOL bNamFnd(FALSE); + SdrObject* pGrp = GetAktGroup(); + + while(pGrp) + { + XubString aStr1(pGrp->GetName()); + + if(!aStr1.Len()) + aStr1 += sal_Unicode('?'); + else + bNamFnd = TRUE; + + aStr += aStr1; + pGrp = pGrp->GetUpGroup(); + + if(pGrp) + aStr += cSep; + } + + if(!bNamFnd && GetAktGroup()) + { + aStr = String(); + aStr += sal_Unicode('('); + aStr += String::CreateFromInt32( GetEnteredLevel() ); + aStr += sal_Unicode(')'); + } + + return aStr; +} + +void SdrPageView::CheckAktGroup() +{ + SdrObject* pGrp=GetAktGroup(); + while (pGrp!=NULL && + (!pGrp->IsInserted() || pGrp->GetObjList()==NULL || + pGrp->GetPage()==NULL || pGrp->GetModel()==NULL)) { // irgendwas daneben? + pGrp=pGrp->GetUpGroup(); + } + if (pGrp!=GetAktGroup()) { + if (pGrp!=NULL) EnterGroup(pGrp); + else LeaveAllGroup(); + } +} + +// #103834# Set background color for svx at SdrPageViews +void SdrPageView::SetApplicationBackgroundColor(Color aBackgroundColor) +{ + maBackgroundColor = aBackgroundColor; +} + +// #109585# +Color SdrPageView::GetApplicationBackgroundColor() const +{ + return maBackgroundColor; +} + +// #103911# Set document color for svx at SdrPageViews +void SdrPageView::SetApplicationDocumentColor(Color aDocumentColor) +{ + maDocumentColor = aDocumentColor; +} + +Color SdrPageView::GetApplicationDocumentColor() const +{ + return maDocumentColor; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdpntv.cxx b/svx/source/svdraw/svdpntv.cxx new file mode 100755 index 000000000000..998c687608fc --- /dev/null +++ b/svx/source/svdraw/svdpntv.cxx @@ -0,0 +1,1540 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <com/sun/star/awt/XWindow.hpp> +#include <svx/svdpntv.hxx> +#include <vcl/msgbox.hxx> +#include <sdrpaintwindow.hxx> +#include <svtools/grfmgr.hxx> +#include <svx/svdmodel.hxx> + +#ifdef DBG_UTIL +#include <svdibrow.hxx> +#endif +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svl/smplhint.hxx> + +#include <svx/svdpntv.hxx> +#include <editeng/editdata.hxx> +#include <svx/svdmrkv.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdview.hxx> +#include <svx/svdglue.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdattrx.hxx> +#include "svdibrow.hxx" +#include "svditer.hxx" +#include <svx/svdouno.hxx> +#include <svx/sdr/overlay/overlayobjectlist.hxx> +#include <svx/sdr/overlay/overlayrollingrectangle.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/svdglue.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdview.hxx> +#include <svx/sxlayitm.hxx> +#include <svl/itemiter.hxx> +#include <editeng/eeitem.hxx> +#include <svl/whiter.hxx> +#include <svl/style.hxx> +#include <svx/sdrpagewindow.hxx> +#include <svx/svdouno.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XControl.hpp> + +// #i38135# +#include <svx/sdr/contact/objectcontact.hxx> +#include <svx/sdr/animation/objectanimator.hxx> +#include <svx/sdr/contact/viewcontact.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #114409#-3 Migrate Encirclement +class ImplEncirclementOverlay +{ + // The OverlayObjects + ::sdr::overlay::OverlayObjectList maObjects; + + // The remembered second position in logical coodinates + basegfx::B2DPoint maSecondPosition; + +public: + ImplEncirclementOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos); + ~ImplEncirclementOverlay(); + + void SetSecondPosition(const basegfx::B2DPoint& rNewPosition); +}; + +ImplEncirclementOverlay::ImplEncirclementOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos) +: maSecondPosition(rStartPos) +{ + for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); + + if(pTargetOverlay) + { + ::sdr::overlay::OverlayRollingRectangleStriped* aNew = new ::sdr::overlay::OverlayRollingRectangleStriped( + rStartPos, rStartPos, false); + pTargetOverlay->add(*aNew); + maObjects.append(*aNew); + } + } +} + +ImplEncirclementOverlay::~ImplEncirclementOverlay() +{ + // The OverlayObjects are cleared using the destructor of OverlayObjectList. + // That destructor calls clear() at the list which removes all objects from the + // OverlayManager and deletes them. +} + +void ImplEncirclementOverlay::SetSecondPosition(const basegfx::B2DPoint& rNewPosition) +{ + if(rNewPosition != maSecondPosition) + { + // apply to OverlayObjects + for(sal_uInt32 a(0L); a < maObjects.count(); a++) + { + ::sdr::overlay::OverlayRollingRectangleStriped& rCandidate = (::sdr::overlay::OverlayRollingRectangleStriped&)maObjects.getOverlayObject(a); + rCandidate.setSecondPosition(rNewPosition); + } + + // remember new position + maSecondPosition = rNewPosition; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// interface to SdrPaintWindow + +SdrPaintWindow* SdrPaintView::FindPaintWindow(const OutputDevice& rOut) const +{ + for(SdrPaintWindowVector::const_iterator a = maPaintWindows.begin(); a != maPaintWindows.end(); a++) + { + if(&((*a)->GetOutputDevice()) == &rOut) + { + return *a; + } + } + + return 0L; +} + +SdrPaintWindow* SdrPaintView::GetPaintWindow(sal_uInt32 nIndex) const +{ + if(nIndex < maPaintWindows.size()) + { + return maPaintWindows[nIndex]; + } + + return 0L; +} + +void SdrPaintView::AppendPaintWindow(SdrPaintWindow& rNew) +{ + maPaintWindows.push_back(&rNew); +} + +SdrPaintWindow* SdrPaintView::RemovePaintWindow(SdrPaintWindow& rOld) +{ + SdrPaintWindow* pRetval = 0L; + const SdrPaintWindowVector::iterator aFindResult = ::std::find(maPaintWindows.begin(), maPaintWindows.end(), &rOld); + + if(aFindResult != maPaintWindows.end()) + { + // remember return value, aFindResult is no longer valid after deletion + pRetval = *aFindResult; + maPaintWindows.erase(aFindResult); + } + + return pRetval; +} + +OutputDevice* SdrPaintView::GetFirstOutputDevice() const +{ + if(PaintWindowCount()) + { + return &(GetPaintWindow(0)->GetOutputDevice()); + } + + return 0L; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1( SvxViewHint, SfxHint ); + +SvxViewHint::SvxViewHint (HintType eHintType) + : meHintType(eHintType) +{ +} + +SvxViewHint::HintType SvxViewHint::GetHintType (void) const +{ + return meHintType; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT2(SdrPaintView,SfxListener,SfxRepeatTarget); + +DBG_NAME(SdrPaintView); + +void SdrPaintView::ImpClearVars() +{ +#ifdef DBG_UTIL + pItemBrowser=NULL; +#endif + bPageVisible=TRUE; + bPageBorderVisible=TRUE; + bBordVisible=TRUE; + bGridVisible=TRUE; + bGridFront =FALSE; + bHlplVisible=TRUE; + bHlplFront =TRUE; + bGlueVisible=FALSE; + bGlueVisible2=FALSE; + bGlueVisible3=FALSE; + bGlueVisible4=FALSE; + bSwapAsynchron=FALSE; + bPrintPreview=FALSE; + mbPreviewRenderer=FALSE; + + eAnimationMode = SDR_ANIMATION_ANIMATE; + bAnimationPause = FALSE; + + nHitTolPix=2; + nMinMovPix=3; + nHitTolLog=0; + nMinMovLog=0; + pActualOutDev=NULL; + pDragWin=NULL; + bRestoreColors=TRUE; + pDefaultStyleSheet=NULL; + bSomeObjChgdFlag=FALSE; + nGraphicManagerDrawMode = GRFMGR_DRAW_STANDARD; + aComeBackTimer.SetTimeout(1); + aComeBackTimer.SetTimeoutHdl(LINK(this,SdrPaintView,ImpComeBackHdl)); + String aNam; // System::GetUserName() just return an empty string + + if (pMod) + SetDefaultStyleSheet(pMod->GetDefaultStyleSheet(), TRUE); + + aNam.ToUpperAscii(); + + maGridColor = Color( COL_BLACK ); + BrkEncirclement(); +} + +SdrPaintView::SdrPaintView(SdrModel* pModel1, OutputDevice* pOut) +: mpEncirclementOverlay(0L), + mpPageView(0L), + aDefaultAttr(pModel1->GetItemPool()), + mbBufferedOutputAllowed(false), + mbBufferedOverlayAllowed(false), + mbPagePaintingAllowed(true), + mbHideOle(false), + mbHideChart(false), + mbHideDraw(false), + mbHideFormControl(false) +{ + DBG_CTOR(SdrPaintView,NULL); + pMod=pModel1; + ImpClearVars(); + + if(pOut) + { + AddWindowToPaintView(pOut); + } + + // Flag zur Visualisierung von Gruppen + bVisualizeEnteredGroup = TRUE; + + maColorConfig.AddListener(this); + onChangeColorConfig(); +} + +SdrPaintView::~SdrPaintView() +{ + DBG_DTOR(SdrPaintView,NULL); + if (pDefaultStyleSheet) + EndListening(*pDefaultStyleSheet); + + maColorConfig.RemoveListener(this); + ClearPageView(); + +#ifdef DBG_UTIL + if(pItemBrowser) + { + delete pItemBrowser; + } +#endif + + // delete existing SdrPaintWindows + while(maPaintWindows.size()) + { + delete maPaintWindows.back(); + maPaintWindows.pop_back(); + } + + // #114409#-3 Migrate HelpLine + BrkEncirclement(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void __EXPORT SdrPaintView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + //If the stylesheet has been destroyed + if (&rBC == pDefaultStyleSheet) + { + if (rHint.ISA(SfxSimpleHint) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING) + pDefaultStyleSheet = NULL; + return; + } + + BOOL bObjChg=!bSomeObjChgdFlag; // TRUE= auswerten fuer ComeBack-Timer + if (bObjChg) { + SdrHint* pSdrHint=PTR_CAST(SdrHint,&rHint); + if (pSdrHint!=NULL) { + SdrHintKind eKind=pSdrHint->GetKind(); + if (eKind==HINT_OBJCHG || eKind==HINT_OBJINSERTED || eKind==HINT_OBJREMOVED) { + if (bObjChg) { + bSomeObjChgdFlag=TRUE; + aComeBackTimer.Start(); + } + } + if (eKind==HINT_PAGEORDERCHG) { + const SdrPage* pPg=pSdrHint->GetPage(); + + if(pPg && !pPg->IsInserted()) + { + if(mpPageView && mpPageView->GetPage() == pPg) + { + HideSdrPage(); + } + } + } + } + } +} + +void SdrPaintView::ConfigurationChanged( ::utl::ConfigurationBroadcaster* , sal_uInt32 ) +{ + onChangeColorConfig(); + InvalidateAllWin(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +IMPL_LINK_INLINE_START(SdrPaintView,ImpComeBackHdl,Timer*,EMPTYARG) +{ + if (bSomeObjChgdFlag) { + bSomeObjChgdFlag=FALSE; + ModelHasChanged(); + } + return 0; +} +IMPL_LINK_INLINE_END(SdrPaintView,ImpComeBackHdl,Timer*,pTimer) + +void SdrPaintView::FlushComeBackTimer() const +{ + if (bSomeObjChgdFlag) { + // casting auf nonconst + ((SdrPaintView*)this)->ImpComeBackHdl(&((SdrPaintView*)this)->aComeBackTimer); + ((SdrPaintView*)this)->aComeBackTimer.Stop(); + } +} + +void SdrPaintView::ModelHasChanged() +{ + // Auch alle PageViews benachrichtigen + if(mpPageView && !mpPageView->GetPage()->IsInserted()) + { + HideSdrPage(); + } + + // test mpPageView here again, HideSdrPage() may have invalidated it. + if(mpPageView) + { + mpPageView->ModelHasChanged(); + } + +#ifdef DBG_UTIL + if(pItemBrowser) + { + pItemBrowser->SetDirty(); + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrPaintView::IsAction() const +{ + return IsEncirclement(); +} + +void SdrPaintView::MovAction(const Point& rPnt) +{ + if (IsEncirclement()) + { + MovEncirclement(rPnt); + } +} + +void SdrPaintView::EndAction() +{ + if(IsEncirclement()) + { + EndEncirclement(); + } +} + +void SdrPaintView::BckAction() +{ + BrkEncirclement(); +} + +void SdrPaintView::BrkAction() +{ + BrkEncirclement(); +} + +void SdrPaintView::TakeActionRect(Rectangle& rRect) const +{ + if(IsEncirclement()) + { + rRect = Rectangle(aDragStat.GetStart(),aDragStat.GetNow()); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// info about TextEdit. Default is sal_False. +bool SdrPaintView::IsTextEdit() const +{ + return false; +} + +// info about TextEditPageView. Default is 0L. +SdrPageView* SdrPaintView::GetTextEditPageView() const +{ + return 0L; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +USHORT SdrPaintView::ImpGetMinMovLogic(short nMinMov, const OutputDevice* pOut) const +{ + if (nMinMov>=0) return USHORT(nMinMov); + if (pOut==NULL) + { + pOut = GetFirstOutputDevice(); + } + if (pOut!=NULL) { + return short(-pOut->PixelToLogic(Size(nMinMov,0)).Width()); + } else { + return 0; + } +} + +USHORT SdrPaintView::ImpGetHitTolLogic(short nHitTol, const OutputDevice* pOut) const +{ + if (nHitTol>=0) return USHORT(nHitTol); + if (pOut==NULL) + { + pOut = GetFirstOutputDevice(); + } + if (pOut!=NULL) { + return short(-pOut->PixelToLogic(Size(nHitTol,0)).Width()); + } else { + return 0; + } +} + +void SdrPaintView::TheresNewMapMode() +{ + if (pActualOutDev!=NULL) { + nHitTolLog=(USHORT)((OutputDevice*)pActualOutDev)->PixelToLogic(Size(nHitTolPix,0)).Width(); + nMinMovLog=(USHORT)((OutputDevice*)pActualOutDev)->PixelToLogic(Size(nMinMovPix,0)).Width(); + } +} + +void SdrPaintView::SetActualWin(const OutputDevice* pWin) +{ + pActualOutDev=pWin; + TheresNewMapMode(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPaintView::BegEncirclement(const Point& rPnt) +{ + BrkAction(); + + DBG_ASSERT(0L == mpEncirclementOverlay, "SdrSnapView::BegSetPageOrg: There exists a ImplPageOriginOverlay (!)"); + basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); + mpEncirclementOverlay = new ImplEncirclementOverlay(*this, aStartPos); + + aDragStat.Reset(rPnt); + aDragStat.SetMinMove(ImpGetMinMovLogic(-2,0L)); + aDragStat.NextPoint(); +} + +void SdrPaintView::MovEncirclement(const Point& rPnt) +{ + if(IsEncirclement() && aDragStat.CheckMinMoved(rPnt)) + { + aDragStat.NextMove(rPnt); + + DBG_ASSERT(mpEncirclementOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + basegfx::B2DPoint aNewPos(rPnt.X(), rPnt.Y()); + mpEncirclementOverlay->SetSecondPosition(aNewPos); + } +} + +Rectangle SdrPaintView::EndEncirclement(sal_Bool bNoJustify) +{ + Rectangle aRetval; + + if(IsEncirclement()) + { + if(aDragStat.IsMinMoved()) + { + aRetval = Rectangle(aDragStat.GetStart(), aDragStat.GetNow()); + + if(!bNoJustify) + { + aRetval.Justify(); + } + } + + // cleanup + BrkEncirclement(); + } + + return aRetval; +} + +void SdrPaintView::BrkEncirclement() +{ + if(IsEncirclement()) + { + DBG_ASSERT(mpEncirclementOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + delete mpEncirclementOverlay; + mpEncirclementOverlay = 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPaintView::ClearPageView() +{ + BrkAction(); + + if(mpPageView) + { + InvalidateAllWin(); + delete mpPageView; + mpPageView = 0L; + } +} + +SdrPageView* SdrPaintView::ShowSdrPage(SdrPage* pPage) +{ + if(pPage && (!mpPageView || mpPageView->GetPage() != pPage)) + { + if(mpPageView) + { + InvalidateAllWin(); + delete mpPageView; + } + + mpPageView = new SdrPageView(pPage, *((SdrView*)this)); + mpPageView->Show(); + } + + return mpPageView; +} + +void SdrPaintView::HideSdrPage() +{ + if(mpPageView) + { + mpPageView->Hide(); + delete mpPageView; + mpPageView = 0L; + } +} + +void SdrPaintView::AddWindowToPaintView(OutputDevice* pNewWin) +{ + DBG_ASSERT(pNewWin, "SdrPaintView::AddWindowToPaintView: No OutputDevice(!)"); + SdrPaintWindow* pNewPaintWindow = new SdrPaintWindow(*this, *pNewWin); + AppendPaintWindow(*pNewPaintWindow); + + if(mpPageView) + { + mpPageView->AddPaintWindowToPageView(*pNewPaintWindow); + } + +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) + pItemBrowser->ForceParent(); +#endif +} + +void SdrPaintView::DeleteWindowFromPaintView(OutputDevice* pOldWin) +{ + DBG_ASSERT(pOldWin, "SdrPaintView::DeleteWindowFromPaintView: No OutputDevice(!)"); + SdrPaintWindow* pCandidate = FindPaintWindow(*pOldWin); + + if(pCandidate) + { + if(mpPageView) + { + mpPageView->RemovePaintWindowFromPageView(*pCandidate); + } + + RemovePaintWindow(*pCandidate); + delete pCandidate; + } + +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) + pItemBrowser->ForceParent(); +#endif +} + +void SdrPaintView::SetLayerVisible(const XubString& rName, BOOL bShow) +{ + if(mpPageView) + { + mpPageView->SetLayerVisible(rName,bShow); + } + + InvalidateAllWin(); +} + +bool SdrPaintView::IsLayerVisible(const XubString& rName) const +{ + if(mpPageView) + { + return mpPageView->IsLayerVisible(rName); + } + + return false; +} + +void SdrPaintView::SetAllLayersVisible(BOOL bShow) +{ + if(mpPageView) + { + mpPageView->SetAllLayersVisible(bShow); + } + + InvalidateAllWin(); +} + +void SdrPaintView::SetLayerLocked(const XubString& rName, BOOL bLock) +{ + if(mpPageView) + { + mpPageView->SetLayerLocked(rName,bLock); + } +} + +bool SdrPaintView::IsLayerLocked(const XubString& rName) const +{ + if(mpPageView) + { + return mpPageView->IsLayerLocked(rName); + } + + return false; +} + +void SdrPaintView::SetAllLayersLocked(BOOL bLock) +{ + if(mpPageView) + { + mpPageView->SetAllLayersLocked(bLock); + } +} + +void SdrPaintView::SetLayerPrintable(const XubString& rName, BOOL bPrn) +{ + if(mpPageView) + { + mpPageView->SetLayerPrintable(rName,bPrn); + } +} + +bool SdrPaintView::IsLayerPrintable(const XubString& rName) const +{ + if(mpPageView) + { + return mpPageView->IsLayerPrintable(rName); + } + + return false; +} + +void SdrPaintView::SetAllLayersPrintable(BOOL bPrn) +{ + if(mpPageView) + { + mpPageView->SetAllLayersPrintable(bPrn); + } +} + +void SdrPaintView::PrePaint() +{ + if(mpPageView) + { + mpPageView->PrePaint(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #define SVX_REPAINT_TIMER_TEST + +void SdrPaintView::CompleteRedraw(OutputDevice* pOut, const Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector) +{ +#ifdef SVX_REPAINT_TIMER_TEST +#define REMEMBERED_TIMES_COUNT (10) + static bool bDoTimerTest(false); + static bool bTimesInited(false); + static sal_uInt32 nRepeatCount(10L); + static double fLastTimes[REMEMBERED_TIMES_COUNT]; + const sal_uInt32 nStartTime(Time::GetSystemTicks()); + sal_uInt32 count(1L); + sal_uInt32 a; + + if(bDoTimerTest) + { + count = nRepeatCount; + } + + for(a = 0L; a < count; a++) + { +#endif // SVX_REPAINT_TIMER_TEST + + // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region + // rReg may be made more granular (fine) with using it. Normally, rReg + // does come from Window::Paint() anyways and thus is based on a single + // rectangle which was derived from exactly that repaint region + Region aOptimizedRepaintRegion(rReg); + + if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType()) + { + Window* pWindow = (Window*)pOut; + + if(pWindow->IsInPaint()) + { + if(!pWindow->GetPaintRegion().IsEmpty()) + { + aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion()); + +#ifdef DBG_UTIL + // #i74769# test-paint repaint region + static bool bDoPaintForVisualControl(false); + if(bDoPaintForVisualControl) + { + RegionHandle aRegionHandle(aOptimizedRepaintRegion.BeginEnumRects()); + Rectangle aRegionRectangle; + + while(aOptimizedRepaintRegion.GetEnumRects(aRegionHandle, aRegionRectangle)) + { + pWindow->SetLineColor(COL_LIGHTGREEN); + pWindow->SetFillColor(); + pWindow->DrawRect(aRegionRectangle); + } + + aOptimizedRepaintRegion.EndEnumRects(aRegionHandle); + } +#endif + } + } + } + + SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut); + OSL_ENSURE(pPaintWindow, "SdrPaintView::CompleteRedraw: No OutDev (!)"); + + DoCompleteRedraw(*pPaintWindow, aOptimizedRepaintRegion, pRedirector); + EndCompleteRedraw(*pPaintWindow, true); + +#ifdef SVX_REPAINT_TIMER_TEST + } + + if(bDoTimerTest) + { + const sal_uInt32 nStopTime(Time::GetSystemTicks()); + const sal_uInt32 nNeededTime(nStopTime - nStartTime); + const double fTimePerPaint((double)nNeededTime / (double)nRepeatCount); + + if(!bTimesInited) + { + for(a = 0L; a < REMEMBERED_TIMES_COUNT; a++) + { + fLastTimes[a] = fTimePerPaint; + } + + bTimesInited = true; + } + else + { + for(a = 1L; a < REMEMBERED_TIMES_COUNT; a++) + { + fLastTimes[a - 1L] = fLastTimes[a]; + } + + fLastTimes[REMEMBERED_TIMES_COUNT - 1L] = fTimePerPaint; + } + + double fAddedTimes(0.0); + + for(a = 0L; a < REMEMBERED_TIMES_COUNT; a++) + { + fAddedTimes += fLastTimes[a]; + } + + const double fAverageTimePerPaint(fAddedTimes / (double)REMEMBERED_TIMES_COUNT); + + fprintf(stderr, "-----------(start result)----------\n"); + fprintf(stderr, "StartTime : %u, StopTime: %u, NeededTime: %u, TimePerPaint: %f\n", nStartTime, nStopTime, nNeededTime, fTimePerPaint); + fprintf(stderr, "Remembered times: "); + + for(a = 0L; a < REMEMBERED_TIMES_COUNT; a++) + { + fprintf(stderr, "%d: %f ", a, fLastTimes[a]); + } + + fprintf(stderr, "\n"); + fprintf(stderr, "AverageTimePerPaint: %f\n", fAverageTimePerPaint); + fprintf(stderr, "-----------(stop result)----------\n"); + } +#endif // SVX_REPAINT_TIMER_TEST +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i72889# + +SdrPaintWindow* SdrPaintView::BeginCompleteRedraw(OutputDevice* pOut) +{ + OSL_ENSURE(pOut, "SdrPaintView::BeginCompleteRedraw: No OutDev (!)"); + SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut); + + if(pPaintWindow) + { + // draw preprocessing, only for known devices + // prepare PreRendering + pPaintWindow->PreparePreRenderDevice(); + } + else + { + // None of the known OutputDevices is the target of this paint, use + // a temporary SdrPaintWindow for this Redraw. + pPaintWindow = new SdrPaintWindow(*this, *pOut); + pPaintWindow->setTemporaryTarget(true); + } + + return pPaintWindow; +} + +void SdrPaintView::DoCompleteRedraw(SdrPaintWindow& rPaintWindow, const Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector) +{ + // redraw all PageViews with the target. This may expand the RedrawRegion + // at the PaintWindow, plus taking care of FormLayer expansion + if(mpPageView) + { + mpPageView->CompleteRedraw(rPaintWindow, rReg, pRedirector); + } +} + +void SdrPaintView::EndCompleteRedraw(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer) +{ + if(rPaintWindow.getTemporaryTarget()) + { + // get rid of temp target again + delete (&rPaintWindow); + } + else + { + // draw postprocessing, only for known devices + // it is necessary to always paint FormLayer + if(bPaintFormLayer) + { + ImpFormLayerDrawing(rPaintWindow); + } + + // look for active TextEdit. As long as this cannot be painted to a VDev, + // it cannot get part of buffering. In that case, output evtl. prerender + // early and paint text edit to window. + const bool bTextEditActive(IsTextEdit() && GetTextEditPageView()); + + if(bTextEditActive) + { + // output PreRendering and destroy it so that it is not used for FormLayer + // or overlay + rPaintWindow.OutputPreRenderDevice(rPaintWindow.GetRedrawRegion()); + + // draw old text edit stuff before overlay to have it as part of the background + // ATM. This will be changed to have the text editing on the overlay, bit it + // is not an easy thing to do, see BegTextEdit and the OutlinerView stuff used... + if(bTextEditActive) + { + ImpTextEditDrawing(rPaintWindow); + } + + // draw Overlay directly to window. This will save the contents of the window + // in the RedrawRegion to the overlay background buffer, too. + // This may lead to problems when reading from the screen is slow from the + // graphics driver/graphiccard combination. + rPaintWindow.DrawOverlay(rPaintWindow.GetRedrawRegion(), false); + } + else + { + // draw Overlay, also to PreRender device if exists + rPaintWindow.DrawOverlay(rPaintWindow.GetRedrawRegion(), true); + + // output PreRendering + rPaintWindow.OutputPreRenderDevice(rPaintWindow.GetRedrawRegion()); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrPaintWindow* SdrPaintView::BeginDrawLayers(OutputDevice* pOut, const Region& rReg, bool bDisableIntersect) +{ + // #i74769# use BeginCompleteRedraw() as common base + SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut); + OSL_ENSURE(pPaintWindow, "SdrPaintView::BeginDrawLayers: No SdrPaintWindow (!)"); + + if(mpPageView) + { + SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow); + + if(pKnownTarget) + { + // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region + // rReg may be made more granular (fine) with using it. Normally, rReg + // does come from Window::Paint() anyways and thus is based on a single + // rectangle which was derived from exactly that repaint region + Region aOptimizedRepaintRegion(rReg); + + // #i76114# Intersecting the region with the Window's paint region is disabled + // for print preview in Calc, because the intersection can be empty (if the paint + // region is outside of the table area of the page), and then no clip region + // would be set. + if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType() && !bDisableIntersect) + { + Window* pWindow = (Window*)pOut; + + if(pWindow->IsInPaint()) + { + if(!pWindow->GetPaintRegion().IsEmpty()) + { + aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion()); + +#ifdef DBG_UTIL + // #i74769# test-paint repaint region + static bool bDoPaintForVisualControl(false); + if(bDoPaintForVisualControl) + { + RegionHandle aRegionHandle(aOptimizedRepaintRegion.BeginEnumRects()); + Rectangle aRegionRectangle; + + while(aOptimizedRepaintRegion.GetEnumRects(aRegionHandle, aRegionRectangle)) + { + pWindow->SetLineColor(COL_LIGHTGREEN); + pWindow->SetFillColor(); + pWindow->DrawRect(aRegionRectangle); + } + + aOptimizedRepaintRegion.EndEnumRects(aRegionHandle); + } +#endif + } + } + } + + // prepare redraw + pKnownTarget->PrepareRedraw(aOptimizedRepaintRegion); + + // remember prepared SdrPageWindow + mpPageView->setPreparedPageWindow(pKnownTarget); + } + } + + return pPaintWindow; +} + +void SdrPaintView::EndDrawLayers(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer) +{ + // #i74769# use EndCompleteRedraw() as common base + EndCompleteRedraw(rPaintWindow, bPaintFormLayer); + + if(mpPageView) + { + // forget prepared SdrPageWindow + mpPageView->setPreparedPageWindow(0); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPaintView::ImpTextEditDrawing(SdrPaintWindow& rPaintWindow) const +{ + // draw old text edit stuff + if(IsTextEdit()) + { + SdrPageView* pPageView = GetTextEditPageView(); + + if(pPageView) + { + // paint TextEdit directly to the destination OutDev + const Region& rRedrawRegion = rPaintWindow.GetRedrawRegion(); + const Rectangle aCheckRect(rRedrawRegion.GetBoundRect()); + pPageView->PaintOutlinerView(&rPaintWindow.GetOutputDevice(), aCheckRect); + } + } +} + +void SdrPaintView::ImpFormLayerDrawing(SdrPaintWindow& rPaintWindow) const +{ + if(mpPageView) + { + SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(rPaintWindow); + + if(pKnownTarget) + { + const SdrModel& rModel = *(GetModel()); + const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin(); + const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName(), sal_False); + + // BUFFERED use GetTargetOutputDevice() now, it may be targeted to VDevs, too + // need to set PreparedPageWindow to make DrawLayer use the correct ObjectContact + mpPageView->setPreparedPageWindow(pKnownTarget); + mpPageView->DrawLayer(nControlLayerId, &rPaintWindow.GetTargetOutputDevice()); + mpPageView->setPreparedPageWindow(0); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrPaintView::KeyInput(const KeyEvent& /*rKEvt*/, Window* /*pWin*/) +{ + return FALSE; +} + +void SdrPaintView::GlueInvalidate() const +{ + const sal_uInt32 nWindowCount(PaintWindowCount()); + + for(sal_uInt32 nWinNum(0L); nWinNum < nWindowCount; nWinNum++) + { + SdrPaintWindow* pPaintWindow = GetPaintWindow(nWinNum); + + if(pPaintWindow->OutputToWindow()) + { + OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); + + if(mpPageView) + { + const SdrObjList* pOL=mpPageView->GetObjList(); + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG nObjNum=0; nObjNum<nObjAnz; nObjNum++) { + const SdrObject* pObj=pOL->GetObj(nObjNum); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + if (pGPL!=NULL && pGPL->GetCount()!=0) { + pGPL->Invalidate((Window&)rOutDev, pObj); + } + } + } + } + } +} + +void SdrPaintView::InvalidateAllWin() +{ + const sal_uInt32 nWindowCount(PaintWindowCount()); + + for(sal_uInt32 a(0L); a < nWindowCount; a++) + { + SdrPaintWindow* pPaintWindow = GetPaintWindow(a); + + if(pPaintWindow->OutputToWindow()) + { + InvalidateOneWin((Window&)pPaintWindow->GetOutputDevice()); + } + } +} + +void SdrPaintView::InvalidateAllWin(const Rectangle& rRect, BOOL bPlus1Pix) +{ + const sal_uInt32 nWindowCount(PaintWindowCount()); + + for(sal_uInt32 a(0L); a < nWindowCount; a++) + { + SdrPaintWindow* pPaintWindow = GetPaintWindow(a); + + if(pPaintWindow->OutputToWindow()) + { + OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); + Rectangle aRect(rRect); + + if(bPlus1Pix) + { + Size aPixSiz(1,1); + Size aSiz(rOutDev.PixelToLogic(aPixSiz)); + aRect.Left ()-=aSiz.Width(); + aRect.Top ()-=aSiz.Height(); + aRect.Right ()+=aSiz.Width(); + aRect.Bottom()+=aSiz.Height(); + } + + Point aOrg(rOutDev.GetMapMode().GetOrigin()); + aOrg.X()=-aOrg.X(); aOrg.Y()=-aOrg.Y(); + Rectangle aOutRect(aOrg, rOutDev.GetOutputSize()); + + if (aRect.IsOver(aOutRect)) + { + InvalidateOneWin((Window&)rOutDev, aRect); + } + } + } +} + +void SdrPaintView::InvalidateOneWin(Window& rWin) +{ + // #111096# + // do not erase background, that causes flicker (!) + rWin.Invalidate(INVALIDATE_NOERASE); +} + +void SdrPaintView::InvalidateOneWin(Window& rWin, const Rectangle& rRect) +{ + // #111096# + // do not erase background, that causes flicker (!) + rWin.Invalidate(rRect, INVALIDATE_NOERASE); +} + +void SdrPaintView::LeaveOneGroup() +{ + if(mpPageView) + { + mpPageView->LeaveOneGroup(); + } +} + +void SdrPaintView::LeaveAllGroup() +{ + if(mpPageView) + { + mpPageView->LeaveAllGroup(); + } +} + +bool SdrPaintView::IsGroupEntered() const +{ + if(mpPageView) + { + return (mpPageView->GetEnteredLevel() != 0); + } + + return false; +} + +void SdrPaintView::SetNotPersistDefaultAttr(const SfxItemSet& rAttr, BOOL /*bReplaceAll*/) +{ + // bReplaceAll hat hier keinerlei Wirkung + BOOL bMeasure=ISA(SdrView) && ((SdrView*)this)->IsMeasureTool(); + const SfxPoolItem *pPoolItem=NULL; + if (rAttr.GetItemState(SDRATTR_LAYERID,TRUE,&pPoolItem)==SFX_ITEM_SET) { + SdrLayerID nLayerId=((const SdrLayerIdItem*)pPoolItem)->GetValue(); + const SdrLayer* pLayer=pMod->GetLayerAdmin().GetLayerPerID(nLayerId); + if (pLayer!=NULL) { + if (bMeasure) aMeasureLayer=pLayer->GetName(); + else aAktLayer=pLayer->GetName(); + } + } + if (rAttr.GetItemState(SDRATTR_LAYERNAME,TRUE,&pPoolItem)==SFX_ITEM_SET) { + if (bMeasure) aMeasureLayer=((const SdrLayerNameItem*)pPoolItem)->GetValue(); + else aAktLayer=((const SdrLayerNameItem*)pPoolItem)->GetValue(); + } +} + +void SdrPaintView::MergeNotPersistDefaultAttr(SfxItemSet& rAttr, BOOL /*bOnlyHardAttr*/) const +{ + // bOnlyHardAttr hat hier keinerlei Wirkung + BOOL bMeasure=ISA(SdrView) && ((SdrView*)this)->IsMeasureTool(); + const XubString& aNam=bMeasure?aMeasureLayer:aAktLayer; + rAttr.Put(SdrLayerNameItem(aNam)); + SdrLayerID nLayer=pMod->GetLayerAdmin().GetLayerID(aNam,TRUE); + if (nLayer!=SDRLAYER_NOTFOUND) { + rAttr.Put(SdrLayerIdItem(nLayer)); + } +} + +void SdrPaintView::SetDefaultAttr(const SfxItemSet& rAttr, BOOL bReplaceAll) +{ +#ifdef DBG_UTIL + { + BOOL bHasEEFeatureItems=FALSE; + SfxItemIter aIter(rAttr); + const SfxPoolItem* pItem=aIter.FirstItem(); + while (!bHasEEFeatureItems && pItem!=NULL) { + if (!IsInvalidItem(pItem)) { + USHORT nW=pItem->Which(); + if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=TRUE; + } + pItem=aIter.NextItem(); + } + + if(bHasEEFeatureItems) + { + String aMessage; + aMessage.AppendAscii("SdrPaintView::SetDefaultAttr(): Das setzen von EE_FEATURE-Items an der SdrView macht keinen Sinn! Es fuehrt nur zu Overhead und nicht mehr lesbaren Dokumenten."); + InfoBox(NULL, aMessage).Execute(); + } + } +#endif + if (bReplaceAll) aDefaultAttr.Set(rAttr); + else aDefaultAttr.Put(rAttr,FALSE); // FALSE= InvalidItems nicht als Default, sondern als "Loecher" betrachten + SetNotPersistDefaultAttr(rAttr,bReplaceAll); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif +} + +void SdrPaintView::SetDefaultStyleSheet(SfxStyleSheet* pStyleSheet, BOOL bDontRemoveHardAttr) +{ + if (pDefaultStyleSheet) + EndListening(*pDefaultStyleSheet); + pDefaultStyleSheet=pStyleSheet; + if (pDefaultStyleSheet) + StartListening(*pDefaultStyleSheet); + + if (pStyleSheet!=NULL && !bDontRemoveHardAttr) { + SfxWhichIter aIter(pStyleSheet->GetItemSet()); + USHORT nWhich=aIter.FirstWhich(); + while (nWhich!=0) { + if (pStyleSheet->GetItemSet().GetItemState(nWhich,TRUE)==SFX_ITEM_SET) { + aDefaultAttr.ClearItem(nWhich); + } + nWhich=aIter.NextWhich(); + } + } +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif +} + +/* new interface src537 */ +BOOL SdrPaintView::GetAttributes(SfxItemSet& rTargetSet, BOOL bOnlyHardAttr) const +{ + if(bOnlyHardAttr || !pDefaultStyleSheet) + { + rTargetSet.Put(aDefaultAttr, FALSE); + } + else + { + // sonst DefStyleSheet dazumergen + rTargetSet.Put(pDefaultStyleSheet->GetItemSet(), FALSE); + rTargetSet.Put(aDefaultAttr, FALSE); + } + MergeNotPersistDefaultAttr(rTargetSet, bOnlyHardAttr); + return TRUE; +} + +BOOL SdrPaintView::SetAttributes(const SfxItemSet& rSet, BOOL bReplaceAll) +{ + SetDefaultAttr(rSet,bReplaceAll); + return TRUE; +} + +SfxStyleSheet* SdrPaintView::GetStyleSheet() const // SfxStyleSheet* SdrPaintView::GetStyleSheet(BOOL& rOk) const +{ + //rOk=TRUE; + return GetDefaultStyleSheet(); +} + +BOOL SdrPaintView::SetStyleSheet(SfxStyleSheet* pStyleSheet, BOOL bDontRemoveHardAttr) +{ + SetDefaultStyleSheet(pStyleSheet,bDontRemoveHardAttr); + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef DBG_UTIL +void SdrPaintView::ShowItemBrowser(BOOL bShow) +{ + if (bShow) { + if (pItemBrowser==NULL) { + pItemBrowser=new SdrItemBrowser(*(SdrView*)this); + pItemBrowser->SetFloatingMode(TRUE); + } + pItemBrowser->Show(); + pItemBrowser->GrabFocus(); + } else { + if (pItemBrowser!=NULL) { + pItemBrowser->Hide(); + delete pItemBrowser; + pItemBrowser=NULL; + } + } +} +#endif + +void SdrPaintView::MakeVisible(const Rectangle& rRect, Window& rWin) +{ + MapMode aMap(rWin.GetMapMode()); + Size aActualSize(rWin.GetOutputSize()); + + if( aActualSize.Height() > 0 && aActualSize.Width() > 0 ) + { + Size aNewSize(rRect.GetSize()); + BOOL bNewScale=FALSE; + BOOL bNeedMoreX=aNewSize.Width()>aActualSize.Width(); + BOOL bNeedMoreY=aNewSize.Height()>aActualSize.Height(); + if (bNeedMoreX || bNeedMoreY) + { + bNewScale=TRUE; + // Neuen MapMode (Size+Org) setzen und dabei alles invalidieren + Fraction aXFact(aNewSize.Width(),aActualSize.Width()); + Fraction aYFact(aNewSize.Height(),aActualSize.Height()); + if (aYFact>aXFact) aXFact=aYFact; + aXFact*=aMap.GetScaleX(); + aXFact.ReduceInaccurate(10); // Um Ueberlaeufe und BigInt-Mapping zu vermeiden + aMap.SetScaleX(aXFact); + aMap.SetScaleY(aYFact); + rWin.SetMapMode(aMap); + aActualSize=rWin.GetOutputSize(); + } + Point aOrg(aMap.GetOrigin()); + long dx=0,dy=0; + long l=-aOrg.X(); + long r=-aOrg.X()+aActualSize.Width()-1; + long o=-aOrg.Y(); + long u=-aOrg.Y()+aActualSize.Height()-1; + if (l>rRect.Left()) dx=rRect.Left()-l; + else if (r<rRect.Right()) dx=rRect.Right()-r; + if (o>rRect.Top()) dy=rRect.Top()-o; + else if (u<rRect.Bottom()) dy=rRect.Bottom()-u; + aMap.SetOrigin(Point(aOrg.X()-dx,aOrg.Y()-dy)); + if (!bNewScale) { + if (dx!=0 || dy!=0) { + rWin.Scroll(-dx,-dy); + rWin.SetMapMode(aMap); + rWin.Update(); + } + } else { + rWin.SetMapMode(aMap); + InvalidateOneWin(rWin); + } + } +} + +void SdrPaintView::DoConnect(SdrOle2Obj* /*pOleObj*/) +{ +} + +void SdrPaintView::SetAnimationEnabled( BOOL bEnable ) +{ + SetAnimationMode( bEnable ? SDR_ANIMATION_ANIMATE : SDR_ANIMATION_DISABLE ); +} + +void SdrPaintView::SetAnimationPause( bool bSet ) +{ + if((bool)bAnimationPause != bSet) + { + bAnimationPause = bSet; + + if(mpPageView) + { + for(sal_uInt32 b(0L); b < mpPageView->PageWindowCount(); b++) + { + const SdrPageWindow& rPageWindow = *(mpPageView->GetPageWindow(b)); + sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact(); + sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator(); + + if(rAnimator.IsPaused() != bSet) + { + rAnimator.SetPaused(bSet); + } + } + } + } +} + +void SdrPaintView::SetAnimationMode( const SdrAnimationMode eMode ) +{ + eAnimationMode = eMode; +} + +void SdrPaintView::VisAreaChanged(const OutputDevice* pOut) +{ + if(mpPageView) + { + if (pOut) + { + SdrPageWindow* pWindow = mpPageView->FindPageWindow(*((OutputDevice*)pOut)); + + if(pWindow) + { + VisAreaChanged(*pWindow); + } + } + else + { + for(sal_uInt32 a(0L); a < mpPageView->PageWindowCount(); a++) + { + VisAreaChanged(*mpPageView->GetPageWindow(a)); + } + } + } +} + +void SdrPaintView::VisAreaChanged(const SdrPageWindow& /*rWindow*/) +{ + // notify SfxListener + Broadcast(SvxViewHint(SvxViewHint::SVX_HINT_VIEWCHANGED)); +} + +const svtools::ColorConfig& SdrPaintView::getColorConfig() const +{ + return maColorConfig; +} + +void SdrPaintView::onChangeColorConfig() +{ + SetGridColor( Color( maColorConfig.GetColorValue( svtools::DRAWGRID ).nColor ) ); +} + +void SdrPaintView::SetGridColor( Color aColor ) +{ + maGridColor = aColor; +} + +Color SdrPaintView::GetGridColor() const +{ + return maGridColor; +} + +// #103834# Set background color for svx at SdrPageViews +void SdrPaintView::SetApplicationBackgroundColor(Color aBackgroundColor) +{ + if(mpPageView) + { + mpPageView->SetApplicationBackgroundColor(aBackgroundColor); + } +} + +// #103911# Set document color for svx at SdrPageViews +void SdrPaintView::SetApplicationDocumentColor(Color aDocumentColor) +{ + if(mpPageView) + { + mpPageView->SetApplicationDocumentColor(aDocumentColor); + } +} + +// #114898# +bool SdrPaintView::IsBufferedOutputAllowed() const +{ + return (mbBufferedOutputAllowed && maDrawinglayerOpt.IsPaintBuffer()); +} + +// #114898# +void SdrPaintView::SetBufferedOutputAllowed(bool bNew) +{ + if(bNew != (bool)mbBufferedOutputAllowed) + { + mbBufferedOutputAllowed = bNew; + } +} + +bool SdrPaintView::IsBufferedOverlayAllowed() const +{ + return (mbBufferedOverlayAllowed && maDrawinglayerOpt.IsOverlayBuffer()); +} + +void SdrPaintView::SetBufferedOverlayAllowed(bool bNew) +{ + if(bNew != (bool)mbBufferedOverlayAllowed) + { + mbBufferedOverlayAllowed = bNew; + } +} + +sal_Bool SdrPaintView::IsPagePaintingAllowed() const +{ + return mbPagePaintingAllowed; +} + +void SdrPaintView::SetPagePaintingAllowed(bool bNew) +{ + if(bNew != (bool)mbPagePaintingAllowed) + { + mbPagePaintingAllowed = bNew; + } +} + +// #i38135# Sets the timer for Object animations and restarts. +void SdrPaintView::SetAnimationTimer(sal_uInt32 nTime) +{ + if(mpPageView) + { + // first, reset all timers at all windows to 0L + for(sal_uInt32 a(0L); a < mpPageView->PageWindowCount(); a++) + { + const SdrPageWindow& rPageWindow = *mpPageView->GetPageWindow(a); + sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact(); + sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator(); + rAnimator.SetTime(nTime); + } + } +} + +// eof diff --git a/svx/source/svdraw/svdpoev.cxx b/svx/source/svdraw/svdpoev.cxx new file mode 100644 index 000000000000..27e2884bb90c --- /dev/null +++ b/svx/source/svdraw/svdpoev.cxx @@ -0,0 +1,745 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdpoev.hxx> +#include <math.h> +#include <svx/svdpagv.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdundo.hxx> +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include <svx/svdtrans.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <vcl/salbtype.hxx> // FRound + +#include <svx/polypolygoneditor.hxx> + +using namespace sdr; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPolyEditView::ImpResetPolyPossibilityFlags() +{ + eMarkedPointsSmooth=SDRPATHSMOOTH_DONTCARE; + eMarkedSegmentsKind=SDRPATHSEGMENT_DONTCARE; + bSetMarkedPointsSmoothPossible=FALSE; + bSetMarkedSegmentsKindPossible=FALSE; +} + +void SdrPolyEditView::ImpClearVars() +{ + ImpResetPolyPossibilityFlags(); +} + +SdrPolyEditView::SdrPolyEditView(SdrModel* pModel1, OutputDevice* pOut): + SdrEditView(pModel1,pOut) +{ + ImpClearVars(); +} + +SdrPolyEditView::~SdrPolyEditView() +{ +} + +void SdrPolyEditView::ImpCheckPolyPossibilities() +{ + ImpResetPolyPossibilityFlags(); + const ULONG nMarkAnz(GetMarkedObjectCount()); + + if(nMarkAnz && !ImpIsFrameHandles()) + { + bool b1stSmooth(true); + bool b1stSegm(true); + bool bCurve(false); + bool bSmoothFuz(false); + bool bSegmFuz(false); + basegfx::B2VectorContinuity eSmooth = basegfx::CONTINUITY_NONE; + + for(ULONG nMarkNum(0L); nMarkNum < nMarkAnz; nMarkNum++) + { + SdrMark* pM = GetSdrMarkByIndex(nMarkNum); + CheckPolyPossibilitiesHelper( pM, b1stSmooth, b1stSegm, bCurve, bSmoothFuz, bSegmFuz, eSmooth ); + } + } +} + +void SdrPolyEditView::CheckPolyPossibilitiesHelper( SdrMark* pM, bool& b1stSmooth, bool& b1stSegm, bool& bCurve, bool& bSmoothFuz, bool& bSegmFuz, basegfx::B2VectorContinuity& eSmooth ) +{ + SdrObject* pObj = pM->GetMarkedSdrObj(); + SdrUShortCont* pPts = pM->GetMarkedPoints(); + SdrPathObj* pPath = PTR_CAST(SdrPathObj,pObj); + + if(pPath && pPts) + { + const sal_uInt32 nMarkedPntAnz(pPts->GetCount()); + + if(nMarkedPntAnz) + { + bool bClosed(pPath->IsClosed()); + bSetMarkedPointsSmoothPossible = true; + + if(bClosed) + { + bSetMarkedSegmentsKindPossible = true; + } + + for(sal_uInt32 nMarkedPntNum(0L); nMarkedPntNum < nMarkedPntAnz; nMarkedPntNum++) + { + sal_uInt32 nNum(pPts->GetObject(nMarkedPntNum)); + sal_uInt32 nPolyNum, nPntNum; + + if(PolyPolygonEditor::GetRelativePolyPoint(pPath->GetPathPoly(), nNum, nPolyNum, nPntNum)) + { + const basegfx::B2DPolygon aLocalPolygon(pPath->GetPathPoly().getB2DPolygon(nPolyNum)); + bool bCanSegment(bClosed || nPntNum < aLocalPolygon.count() - 1L); + + if(!bSetMarkedSegmentsKindPossible && bCanSegment) + { + bSetMarkedSegmentsKindPossible = true; + } + + if(!bSmoothFuz) + { + if (b1stSmooth) + { + b1stSmooth = false; + eSmooth = basegfx::tools::getContinuityInPoint(aLocalPolygon, nPntNum); + } + else + { + bSmoothFuz = (eSmooth != basegfx::tools::getContinuityInPoint(aLocalPolygon, nPntNum)); + } + } + + if(!bSegmFuz) + { + if(bCanSegment) + { + bool bCrv(aLocalPolygon.isNextControlPointUsed(nPntNum)); + + if(b1stSegm) + { + b1stSegm = false; + bCurve = bCrv; + } + else + { + bSegmFuz = (bCrv != bCurve); + } + } + } + } + } + + if(!b1stSmooth && !bSmoothFuz) + { + if(basegfx::CONTINUITY_NONE == eSmooth) + { + eMarkedPointsSmooth = SDRPATHSMOOTH_ANGULAR; + } + + if(basegfx::CONTINUITY_C1 == eSmooth) + { + eMarkedPointsSmooth = SDRPATHSMOOTH_ASYMMETRIC; + } + + if(basegfx::CONTINUITY_C2 == eSmooth) + { + eMarkedPointsSmooth = SDRPATHSMOOTH_SYMMETRIC; + } + } + + if(!b1stSegm && !bSegmFuz) + { + eMarkedSegmentsKind = (bCurve) ? SDRPATHSEGMENT_CURVE : SDRPATHSEGMENT_LINE; + } + } + } +} + +void SdrPolyEditView::SetMarkedPointsSmooth(SdrPathSmoothKind eKind) +{ + basegfx::B2VectorContinuity eFlags; + + if(SDRPATHSMOOTH_ANGULAR == eKind) + { + eFlags = basegfx::CONTINUITY_NONE; + } + else if(SDRPATHSMOOTH_ASYMMETRIC == eKind) + { + eFlags = basegfx::CONTINUITY_C1; + } + else if(SDRPATHSMOOTH_SYMMETRIC == eKind) + { + eFlags = basegfx::CONTINUITY_C2; + } + else + { + return; + } + + if(HasMarkedPoints()) + { + SortMarkedObjects(); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditSetPointsSmooth), GetDescriptionOfMarkedPoints()); + ULONG nMarkAnz(GetMarkedObjectCount()); + + for(ULONG nMarkNum(nMarkAnz); nMarkNum > 0L;) + { + nMarkNum--; + SdrMark* pM = GetSdrMarkByIndex(nMarkNum); + SdrUShortCont* pPts = pM->GetMarkedPoints(); + SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() ); + + if(pPts && pPath) + { + PolyPolygonEditor aEditor( pPath->GetPathPoly(), pPath->IsClosed() ); + if(aEditor.SetPointsSmooth( eFlags, pPts->getContainer() ) ) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath)); + pPath->SetPathPoly(aEditor.GetPolyPolygon()); + } + } + } + + if( bUndo ) + EndUndo(); + } +} + +void SdrPolyEditView::SetMarkedSegmentsKind(SdrPathSegmentKind eKind) +{ + if(HasMarkedPoints()) + { + SortMarkedObjects(); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditSetSegmentsKind), GetDescriptionOfMarkedPoints()); + ULONG nMarkAnz(GetMarkedObjectCount()); + + for(ULONG nMarkNum(nMarkAnz); nMarkNum > 0L;) + { + nMarkNum--; + SdrMark* pM = GetSdrMarkByIndex(nMarkNum); + SdrUShortCont* pPts = pM->GetMarkedPoints(); + SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() ); + + if(pPts && pPath) + { + PolyPolygonEditor aEditor( pPath->GetPathPoly(), pPath->IsClosed() ); + if(aEditor.SetSegmentsKind( eKind, pPts->getContainer()) ) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath)); + pPath->SetPathPoly(aEditor.GetPolyPolygon()); + } + } + } + + if( bUndo ) + EndUndo(); + } +} + +BOOL SdrPolyEditView::IsSetMarkedPointsSmoothPossible() const +{ + ForcePossibilities(); + return bSetMarkedPointsSmoothPossible; +} + +SdrPathSmoothKind SdrPolyEditView::GetMarkedPointsSmooth() const +{ + ForcePossibilities(); + return eMarkedPointsSmooth; +} + +BOOL SdrPolyEditView::IsSetMarkedSegmentsKindPossible() const +{ + ForcePossibilities(); + return bSetMarkedSegmentsKindPossible; +} + +SdrPathSegmentKind SdrPolyEditView::GetMarkedSegmentsKind() const +{ + ForcePossibilities(); + return eMarkedSegmentsKind; +} + +BOOL SdrPolyEditView::IsDeleteMarkedPointsPossible() const +{ + return HasMarkedPoints(); +} + +void SdrPolyEditView::DeleteMarkedPoints() +{ + if (HasMarkedPoints()) + { + BrkAction(); + SortMarkedObjects(); + ULONG nMarkAnz=GetMarkedObjectCount(); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + { + // Description + BegUndo(ImpGetResStr(STR_EditDelete),GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_DELETE); + } + + for (ULONG nMarkNum=nMarkAnz; nMarkNum>0;) + { + nMarkNum--; + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrUShortCont* pPts=pM->GetMarkedPoints(); + SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() ); + + if( pPath && pPts ) + { + PolyPolygonEditor aEditor( pPath ->GetPathPoly(), pPath->IsClosed() ); + if( aEditor.DeletePoints( pPts->getContainer() ) ) + { + if( aEditor.GetPolyPolygon().count() ) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath )); + pPath->SetPathPoly( aEditor.GetPolyPolygon() ); + } + else + { + if( bUndo ) + AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pPath ) ); + pM->GetPageView()->GetObjList()->RemoveObject(pPath->GetOrdNum()); + if( !bUndo ) + { + SdrObject* pObj = pPath; + SdrObject::Free(pObj); + } + } + } + } + } + + if( bUndo ) + EndUndo(); + UnmarkAllPoints(); + MarkListHasChanged(); + } +} + +void SdrPolyEditView::RipUpAtMarkedPoints() +{ + if(HasMarkedPoints()) + { + SortMarkedObjects(); + sal_uInt32 nMarkAnz(GetMarkedObjectCount()); + + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditRipUp), GetDescriptionOfMarkedPoints()); + + for(sal_uInt32 nMarkNum(nMarkAnz); nMarkNum > 0L;) + { + nMarkNum--; + SdrMark* pM = GetSdrMarkByIndex(nMarkNum); + SdrUShortCont* pPts = pM->GetMarkedPoints(); + SdrPathObj* pObj = PTR_CAST(SdrPathObj, pM->GetMarkedSdrObj()); + + if(pPts && pObj) + { + pPts->ForceSort(); + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + sal_Bool bKorregFlag(sal_False); + sal_Bool bInsAny(sal_False); + sal_uInt32 nMarkPtsAnz(pPts->GetCount()); + sal_uInt32 nMax(pObj->GetHdlCount()); + + for(sal_uInt32 i(nMarkPtsAnz); i > 0L;) + { + i--; + sal_uInt32 nNewPt0Idx(0L); + SdrObject* pNeuObj = pObj->RipPoint(pPts->GetObject(i), nNewPt0Idx); + + if(pNeuObj) + { + bInsAny = sal_True; + SdrInsertReason aReason(SDRREASON_VIEWCALL, pObj); + pM->GetPageView()->GetObjList()->InsertObject(pNeuObj, pObj->GetOrdNum() + 1, &aReason); + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNeuObj)); + MarkObj(pNeuObj, pM->GetPageView(), FALSE, TRUE); + } + + if(nNewPt0Idx) + { + // Korrektur notwendig? + DBG_ASSERT(bKorregFlag==FALSE,"Mehrfache Indexkorrektur bei SdrPolyEditView::RipUp()"); + if(!bKorregFlag) + { + bKorregFlag = sal_True; + + for(sal_uInt32 nBla(0L); nBla < nMarkPtsAnz; nBla++) + { + sal_uInt32 nPntNum(pPts->GetObject(nBla)); + nPntNum += nNewPt0Idx; + + if(nPntNum >= nMax) + { + nPntNum -= nMax; + } + + pPts->Replace((sal_uInt16)nPntNum, nBla); + } + + i = nMarkPtsAnz; // ... und nochmal von vorn + } + } + } + } + } + + UnmarkAllPoints(); + if( bUndo ) + EndUndo(); + MarkListHasChanged(); + } +} + +bool SdrPolyEditView::IsRipUpAtMarkedPointsPossible() const +{ + bool bRetval(false); + const sal_uInt32 nMarkCount(GetMarkedObjectCount()); + + for(sal_uInt32 a(0); a < nMarkCount; a++) + { + const SdrMark* pMark = GetSdrMarkByIndex(a); + const SdrPathObj* pMarkedPathObject = dynamic_cast< const SdrPathObj* >(pMark->GetMarkedSdrObj()); + + if(pMarkedPathObject) + { + const SdrUShortCont* pSelectedPoints = pMark->GetMarkedPoints(); + + if(pSelectedPoints && pSelectedPoints->GetCount()) + { + const basegfx::B2DPolyPolygon& rPathPolyPolygon = pMarkedPathObject->GetPathPoly(); + + if(1 == rPathPolyPolygon.count()) + { + // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions + // are different and methods need to be changed thoroughly with interaction rework + const Polygon aPathPolygon(rPathPolyPolygon.getB2DPolygon(0)); + const sal_uInt16 nPointCount(aPathPolygon.GetSize()); + + if(nPointCount >= 3) + { + bRetval = pMarkedPathObject->IsClosedObj(); // #i76617# aPathPolygon.isClosed(); + + for(sal_uInt32 b(0); !bRetval && b < pSelectedPoints->GetCount(); b++) + { + const sal_uInt16 nMarkedPointNum(pSelectedPoints->GetObject(b)); + + bRetval = (nMarkedPointNum > 0 && nMarkedPointNum < nPointCount - 1); + } + } + } + } + } + } + + return bRetval; +} + +bool SdrPolyEditView::IsOpenCloseMarkedObjectsPossible() const +{ + bool bRetval(false); + const sal_uInt32 nMarkCount(GetMarkedObjectCount()); + + for(sal_uInt32 a(0); a < nMarkCount; a++) + { + const SdrMark* pMark = GetSdrMarkByIndex(a); + const SdrPathObj* pMarkedPathObject = dynamic_cast< const SdrPathObj* >(pMark->GetMarkedSdrObj()); + + if(pMarkedPathObject) + { + // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions + // are different and methods need to be changed thoroughly with interaction rework + const PolyPolygon aPathPolyPolygon(pMarkedPathObject->GetPathPoly()); + const sal_uInt16 nPolygonCount(aPathPolyPolygon.Count()); + + for(sal_uInt16 b(0); !bRetval && b < nPolygonCount; b++) + { + const Polygon& rPathPolygon = aPathPolyPolygon[b]; + const sal_uInt16 nPointCount(rPathPolygon.GetSize()); + + bRetval = (nPointCount >= 3); + } + } + } + + return bRetval; +} + +SdrObjClosedKind SdrPolyEditView::GetMarkedObjectsClosedState() const +{ + bool bOpen(false); + bool bClosed(false); + const sal_uInt32 nMarkCount(GetMarkedObjectCount()); + + for(sal_uInt32 a(0); !(bOpen && bClosed) && a < nMarkCount; a++) + { + const SdrMark* pMark = GetSdrMarkByIndex(a); + const SdrPathObj* pMarkedPathObject = dynamic_cast< const SdrPathObj* >(pMark->GetMarkedSdrObj()); + + if(pMarkedPathObject) + { + if(pMarkedPathObject->IsClosedObj()) + { + bClosed = true; + } + else + { + bOpen = true; + } + } + } + + if(bOpen && bClosed) + { + return SDROBJCLOSED_DONTCARE; + } + else if(bOpen) + { + return SDROBJCLOSED_OPEN; + } + else + { + return SDROBJCLOSED_CLOSED; + } +} + +void SdrPolyEditView::ShutMarkedObjects() +{ + CloseMarkedObjects(); +} + +void SdrPolyEditView::CloseMarkedObjects(BOOL bToggle, BOOL bOpen) // , long nOpenDistance) +{ + if (AreObjectsMarked()) + { + const bool bUndo = IsUndoEnabled(); + if( bUndo ) + BegUndo(ImpGetResStr(STR_EditShut),GetDescriptionOfMarkedPoints()); + + bool bChg=false; + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pO=pM->GetMarkedSdrObj(); + BOOL bClosed=pO->IsClosedObj(); + if (pO->IsPolyObj() && (bClosed==bOpen) || bToggle) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO)); + + SdrPathObj* pPathObj = dynamic_cast< SdrPathObj* >( pO ); + if(pPathObj) + pPathObj->ToggleClosed(); + bChg=true; + } + } + + if( bUndo ) + EndUndo(); + + if (bChg) + { + UnmarkAllPoints(); + MarkListHasChanged(); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPolyEditView::ImpCopyMarkedPoints() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrPolyEditView::ImpTransformMarkedPoints(PPolyTrFunc pTrFunc, const void* p1, const void* p2, const void* p3, const void* p4, const void* p5) +{ + const bool bUndo = IsUndoEnabled(); + + ULONG nMarkAnz=GetMarkedObjectCount(); + for (ULONG nm=0; nm<nMarkAnz; nm++) + { + SdrMark* pM=GetSdrMarkByIndex(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrUShortCont* pPts=pM->GetMarkedPoints(); + ULONG nPtAnz=pPts==NULL ? 0 : pPts->GetCount(); + SdrPathObj* pPath=PTR_CAST(SdrPathObj,pObj); + if (nPtAnz!=0 && pPath!=NULL) + { + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + + basegfx::B2DPolyPolygon aXPP(pPath->GetPathPoly()); + + for(sal_uInt32 nPtNum(0L); nPtNum < nPtAnz; nPtNum++) + { + sal_uInt32 nPt(pPts->GetObject(nPtNum)); + sal_uInt32 nPolyNum, nPointNum; + + if(PolyPolygonEditor::GetRelativePolyPoint(aXPP, nPt, nPolyNum, nPointNum)) + { + //#i83671# used nLocalPointNum (which was the polygon point count) + // instead of the point index (nPointNum). This of course leaded + // to a wrong point access to the B2DPolygon. + basegfx::B2DPolygon aNewXP(aXPP.getB2DPolygon(nPolyNum)); + Point aPos, aC1, aC2; + bool bC1(false); + bool bC2(false); + + const basegfx::B2DPoint aB2DPos(aNewXP.getB2DPoint(nPointNum)); + aPos = Point(FRound(aB2DPos.getX()), FRound(aB2DPos.getY())); + + if(aNewXP.isPrevControlPointUsed(nPointNum)) + { + const basegfx::B2DPoint aB2DC1(aNewXP.getPrevControlPoint(nPointNum)); + aC1 = Point(FRound(aB2DC1.getX()), FRound(aB2DC1.getY())); + bC1 = true; + } + + if(aNewXP.isNextControlPointUsed(nPointNum)) + { + const basegfx::B2DPoint aB2DC2(aNewXP.getNextControlPoint(nPointNum)); + aC2 = Point(FRound(aB2DC2.getX()), FRound(aB2DC2.getY())); + bC2 = true; + } + + (*pTrFunc)(aPos,&aC1,&aC2,p1,p2,p3,p4,p5); + aNewXP.setB2DPoint(nPointNum, basegfx::B2DPoint(aPos.X(), aPos.Y())); + + if (bC1) + { + aNewXP.setPrevControlPoint(nPointNum, basegfx::B2DPoint(aC1.X(), aC1.Y())); + } + + if (bC2) + { + aNewXP.setNextControlPoint(nPointNum, basegfx::B2DPoint(aC2.X(), aC2.Y())); + } + + aXPP.setB2DPolygon(nPolyNum, aNewXP); + } + } + + pPath->SetPathPoly(aXPP); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpMove(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void* /*p2*/, const void* /*p3*/, const void* /*p4*/, const void* /*p5*/) +{ + MovePoint(rPt,*(const Size*)p1); + if (pC1!=NULL) MovePoint(*pC1,*(const Size*)p1); + if (pC2!=NULL) MovePoint(*pC2,*(const Size*)p1); +} + +void SdrPolyEditView::MoveMarkedPoints(const Size& rSiz, bool bCopy) +{ + bCopy=FALSE; // noch nicht implementiert + ForceUndirtyMrkPnt(); + XubString aStr(ImpGetResStr(STR_EditMove)); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr,GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_MOVE); + if (bCopy) ImpCopyMarkedPoints(); + ImpTransformMarkedPoints(ImpMove,&rSiz); + EndUndo(); + AdjustMarkHdl(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpResize(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void* p2, const void* p3, const void* /*p4*/, const void* /*p5*/) +{ + ResizePoint(rPt,*(const Point*)p1,*(const Fraction*)p2,*(const Fraction*)p3); + if (pC1!=NULL) ResizePoint(*pC1,*(const Point*)p1,*(const Fraction*)p2,*(const Fraction*)p3); + if (pC2!=NULL) ResizePoint(*pC2,*(const Point*)p1,*(const Fraction*)p2,*(const Fraction*)p3); +} + +void SdrPolyEditView::ResizeMarkedPoints(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy) +{ + bCopy=FALSE; // noch nicht implementiert + ForceUndirtyMrkPnt(); + XubString aStr(ImpGetResStr(STR_EditResize)); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr,GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_RESIZE); + if (bCopy) ImpCopyMarkedPoints(); + ImpTransformMarkedPoints(ImpResize,&rRef,&xFact,&yFact); + EndUndo(); + AdjustMarkHdl(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static void ImpRotate(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void* /*p2*/, const void* p3, const void* p4, const void* /*p5*/) +{ + RotatePoint(rPt,*(const Point*)p1,*(const double*)p3,*(const double*)p4); + if (pC1!=NULL) RotatePoint(*pC1,*(const Point*)p1,*(const double*)p3,*(const double*)p4); + if (pC2!=NULL) RotatePoint(*pC2,*(const Point*)p1,*(const double*)p3,*(const double*)p4); +} + +void SdrPolyEditView::RotateMarkedPoints(const Point& rRef, long nWink, bool bCopy) +{ + bCopy=FALSE; // noch nicht implementiert + ForceUndirtyMrkPnt(); + XubString aStr(ImpGetResStr(STR_EditResize)); + if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy); + BegUndo(aStr,GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_ROTATE); + if (bCopy) ImpCopyMarkedPoints(); + double nSin=sin(nWink*nPi180); + double nCos=cos(nWink*nPi180); + ImpTransformMarkedPoints(ImpRotate,&rRef,&nWink,&nSin,&nCos); + EndUndo(); + AdjustMarkHdl(); +} + +// eof diff --git a/svx/source/svdraw/svdsnpv.cxx b/svx/source/svdraw/svdsnpv.cxx new file mode 100644 index 000000000000..1a8f735887cf --- /dev/null +++ b/svx/source/svdraw/svdsnpv.cxx @@ -0,0 +1,730 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdsnpv.hxx> +#include <math.h> + +#include <svx/svdetc.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdpage.hxx> +#include "svditer.hxx" +#include <svx/sdr/overlay/overlayobjectlist.hxx> +#include <svx/sdr/overlay/overlaycrosshair.hxx> +#include <svx/sdr/overlay/overlayhelpline.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <sdrpaintwindow.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #114409#-1 Migrate PageOrigin +class ImplPageOriginOverlay +{ + // The OverlayObjects + ::sdr::overlay::OverlayObjectList maObjects; + + // The current position in logical coodinates + basegfx::B2DPoint maPosition; + +public: + ImplPageOriginOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos); + ~ImplPageOriginOverlay(); + + void SetPosition(const basegfx::B2DPoint& rNewPosition); +}; + +ImplPageOriginOverlay::ImplPageOriginOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos) +: maPosition(rStartPos) +{ + for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); + + if(pTargetOverlay) + { + ::sdr::overlay::OverlayCrosshairStriped* aNew = new ::sdr::overlay::OverlayCrosshairStriped( + maPosition); + pTargetOverlay->add(*aNew); + maObjects.append(*aNew); + } + } +} + +ImplPageOriginOverlay::~ImplPageOriginOverlay() +{ + // The OverlayObjects are cleared using the destructor of OverlayObjectList. + // That destructor calls clear() at the list which removes all objects from the + // OverlayManager and deletes them. +} + +void ImplPageOriginOverlay::SetPosition(const basegfx::B2DPoint& rNewPosition) +{ + if(rNewPosition != maPosition) + { + // apply to OverlayObjects + for(sal_uInt32 a(0); a < maObjects.count(); a++) + { + sdr::overlay::OverlayCrosshairStriped* pCandidate = + static_cast< sdr::overlay::OverlayCrosshairStriped* >(&maObjects.getOverlayObject(a)); + + if(pCandidate) + { + pCandidate->setBasePosition(rNewPosition); + } + } + + // remember new position + maPosition = rNewPosition; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #114409#-2 Migrate HelpLine +class ImplHelpLineOverlay +{ + // The OverlayObjects + ::sdr::overlay::OverlayObjectList maObjects; + + // The current position in logical coodinates + basegfx::B2DPoint maPosition; + + // HelpLine specific stuff + SdrPageView* mpPageView; + sal_uInt16 mnHelpLineNumber; + SdrHelpLineKind meHelpLineKind; + +public: + ImplHelpLineOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos, + SdrPageView* pPageView, sal_uInt16 nHelpLineNumber, SdrHelpLineKind eKind); + ~ImplHelpLineOverlay(); + + void SetPosition(const basegfx::B2DPoint& rNewPosition); + + // access to HelpLine specific stuff + SdrPageView* GetPageView() const { return mpPageView; } + sal_uInt16 GetHelpLineNumber() const { return mnHelpLineNumber; } + SdrHelpLineKind GetHelpLineKind() const { return meHelpLineKind; } +}; + +ImplHelpLineOverlay::ImplHelpLineOverlay( + const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos, + SdrPageView* pPageView, sal_uInt16 nHelpLineNumber, SdrHelpLineKind eKind) +: maPosition(rStartPos), + mpPageView(pPageView), + mnHelpLineNumber(nHelpLineNumber), + meHelpLineKind(eKind) +{ + for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); + + if(pTargetOverlay) + { + ::sdr::overlay::OverlayHelplineStriped* aNew = new ::sdr::overlay::OverlayHelplineStriped( + maPosition, meHelpLineKind); + pTargetOverlay->add(*aNew); + maObjects.append(*aNew); + } + } +} + +ImplHelpLineOverlay::~ImplHelpLineOverlay() +{ + // The OverlayObjects are cleared using the destructor of OverlayObjectList. + // That destructor calls clear() at the list which removes all objects from the + // OverlayManager and deletes them. +} + +void ImplHelpLineOverlay::SetPosition(const basegfx::B2DPoint& rNewPosition) +{ + if(rNewPosition != maPosition) + { + // apply to OverlayObjects + // apply to OverlayObjects + for(sal_uInt32 a(0); a < maObjects.count(); a++) + { + sdr::overlay::OverlayHelplineStriped* pCandidate = + static_cast< sdr::overlay::OverlayHelplineStriped* >(&maObjects.getOverlayObject(a)); + + if(pCandidate) + { + pCandidate->setBasePosition(rNewPosition); + } + } + + // remember new position + maPosition = rNewPosition; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@ @@ @@@@ @@@@@ @@ @@ @@ @@@@@ @@ @@ +// @@ @@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ +// @@@@ @@@@@@ @@@@@@ @@@@@ @@@@@ @@ @@@@ @@@@@@@ +// @@ @@ @@@ @@ @@ @@ @@@ @@ @@ @@@@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ +// @@@@ @@ @@ @@ @@ @@ @ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrSnapView::ClearVars() +{ + nMagnSizPix=4; + bSnapEnab=TRUE; + bGridSnap=TRUE; + bSnapTo1Pix=TRUE; + bBordSnap=TRUE; + bHlplSnap=TRUE; + bOFrmSnap=TRUE; + bOPntSnap=FALSE; + bOConSnap=TRUE; + bMoveMFrmSnap=TRUE; + bMoveOFrmSnap=TRUE; + bMoveOPntSnap=TRUE; + bMoveOConSnap=TRUE; + bMoveSnapOnlyTopLeft=FALSE; + bOrtho=FALSE; + bBigOrtho=TRUE; + nSnapAngle=1500; + bAngleSnapEnab=FALSE; + bMoveOnlyDragging=FALSE; + bSlantButShear=FALSE; + bCrookNoContortion=FALSE; + eCrookMode=SDRCROOK_ROTATE; + bHlplFixed=FALSE; + bEliminatePolyPoints=FALSE; + nEliminatePolyPointLimitAngle=0; + + // #114409#-1 Migrate PageOrigin + BrkSetPageOrg(); + + // #114409#-2 Migrate HelpLine + BrkDragHelpLine(); +} + +SdrSnapView::SdrSnapView(SdrModel* pModel1, OutputDevice* pOut): + SdrPaintView(pModel1,pOut), + // #114409#-1 Migrate PageOrigin + mpPageOriginOverlay(0L), + // #114409#-2 Migrate HelpLine + mpHelpLineOverlay(0L) +{ + ClearVars(); +} + +// #114409#-1 Migrate PageOrigin +SdrSnapView::~SdrSnapView() +{ + // #114409#-1 Migrate PageOrigin + BrkSetPageOrg(); + + // #114409#-2 Migrate HelpLine + BrkDragHelpLine(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrSnapView::IsAction() const +{ + return IsSetPageOrg() || IsDragHelpLine() || SdrPaintView::IsAction(); +} + +void SdrSnapView::MovAction(const Point& rPnt) +{ + SdrPaintView::MovAction(rPnt); + if (IsSetPageOrg()) { + MovSetPageOrg(rPnt); + } + if (IsDragHelpLine()) { + MovDragHelpLine(rPnt); + } +} + +void SdrSnapView::EndAction() +{ + if (IsSetPageOrg()) { + EndSetPageOrg(); + } + if (IsDragHelpLine()) { + EndDragHelpLine(); + } + SdrPaintView::EndAction(); +} + +void SdrSnapView::BckAction() +{ + BrkSetPageOrg(); + BrkDragHelpLine(); + SdrPaintView::BckAction(); +} + +void SdrSnapView::BrkAction() +{ + BrkSetPageOrg(); + BrkDragHelpLine(); + SdrPaintView::BrkAction(); +} + +void SdrSnapView::TakeActionRect(Rectangle& rRect) const +{ + if (IsSetPageOrg() || IsDragHelpLine()) { + rRect=Rectangle(aDragStat.GetNow(),aDragStat.GetNow()); + } else { + SdrPaintView::TakeActionRect(rRect); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Point SdrSnapView::GetSnapPos(const Point& rPnt, const SdrPageView* pPV) const +{ + Point aPt(rPnt); + SnapPos(aPt,pPV); + return aPt; +} + +#define NOT_SNAPPED 0x7FFFFFFF +USHORT SdrSnapView::SnapPos(Point& rPnt, const SdrPageView* pPV) const +{ + if (!bSnapEnab) return SDRSNAP_NOTSNAPPED; + BOOL bPVOfs=FALSE; + long x=rPnt.X(); + long y=rPnt.Y(); + if (pPV==NULL) { + bPVOfs=TRUE; + pPV=GetSdrPageView(); + if (pPV==NULL) return SDRSNAP_NOTSNAPPED; + } + + long dx=NOT_SNAPPED; + long dy=NOT_SNAPPED; + long dx1,dy1; + long mx=aMagnSiz.Width(); + long my=aMagnSiz.Height(); + if (bHlplVisible && bHlplSnap && !IsDragHelpLine()) + { + const SdrHelpLineList& rHLL=pPV->GetHelpLines(); + USHORT nAnz=rHLL.GetCount(); + for (USHORT i=nAnz; i>0;) { + i--; + const SdrHelpLine& rHL=rHLL[i]; + const Point& rPos=rHL.GetPos(); + switch (rHL.GetKind()) { + case SDRHELPLINE_VERTICAL: { + long a=x-rPos.X(); + if (Abs(a)<=mx) { dx1=-a; if (Abs(dx1)<Abs(dx)) dx=dx1; } + } break; + case SDRHELPLINE_HORIZONTAL: { + long b=y-rPos.Y(); + if (Abs(b)<=my) { dy1=-b; if (Abs(dy1)<Abs(dy)) dy=dy1; } + } break; + case SDRHELPLINE_POINT: { + long a=x-rPos.X(); + long b=y-rPos.Y(); + if (Abs(a)<=mx && Abs(b)<=my) { + dx1=-a; dy1=-b; + if (Abs(dx1)<Abs(dx) && Abs(dy1)<Abs(dy)) { dx=dx1; dy=dy1; } + } + } break; + } // switch + } + } + if (bBordVisible && bBordSnap) { + SdrPage* pPage=pPV->GetPage(); + long xs=pPage->GetWdt(); + long ys=pPage->GetHgt(); + long lft=pPage->GetLftBorder(); + long rgt=pPage->GetRgtBorder(); + long upp=pPage->GetUppBorder(); + long lwr=pPage->GetLwrBorder(); + long a; + a=x- lft ; if (Abs(a)<=mx) { dx1=-a; if (Abs(dx1)<Abs(dx)) dx=dx1; } // linker Rand + a=x-(xs-rgt); if (Abs(a)<=mx) { dx1=-a; if (Abs(dx1)<Abs(dx)) dx=dx1; } // rechter Rand + a=x ; if (Abs(a)<=mx) { dx1=-a; if (Abs(dx1)<Abs(dx)) dx=dx1; } // linke Papierkante + a=x- xs ; if (Abs(a)<=mx) { dx1=-a; if (Abs(dx1)<Abs(dx)) dx=dx1; } // rechte Papierkante + a=y- upp ; if (Abs(a)<=my) { dy1=-a; if (Abs(dy1)<Abs(dy)) dy=dy1; } // linker Rand + a=y-(ys-lwr); if (Abs(a)<=my) { dy1=-a; if (Abs(dy1)<Abs(dy)) dy=dy1; } // rechter Rand + a=y ; if (Abs(a)<=my) { dy1=-a; if (Abs(dy1)<Abs(dy)) dy=dy1; } // linke Papierkante + a=y- ys ; if (Abs(a)<=my) { dy1=-a; if (Abs(dy1)<Abs(dy)) dy=dy1; } // rechte Papierkante + } + if (bOFrmSnap || bOPntSnap /*|| (bConnVisible && bOConSnap)*/) { + ULONG nMaxPointSnapCount=200; + ULONG nMaxFrameSnapCount=200; + + // #97981# go back to IM_DEEPNOGROUPS runthrough for snap to object comparisons + SdrObjListIter aIter(*pPV->GetPage(),/*IM_FLAT*/IM_DEEPNOGROUPS,TRUE); + + while (aIter.IsMore() && (nMaxPointSnapCount>0 || nMaxFrameSnapCount>0)) { + SdrObject* pO=aIter.Next(); + Rectangle aRect(pO->GetCurrentBoundRect()); + aRect.Left ()-=mx; + aRect.Right ()+=mx; + aRect.Top ()-=my; + aRect.Bottom()+=my; + if (aRect.IsInside(rPnt)) { + if (bOPntSnap && nMaxPointSnapCount>0) + { + sal_uInt32 nAnz(pO->GetSnapPointCount()); + for (sal_uInt32 i(0L); i < nAnz && nMaxPointSnapCount > 0L; i++) + { + Point aP(pO->GetSnapPoint(i)); + dx1=x-aP.X(); + dy1=y-aP.Y(); + if (Abs(dx1)<=mx && Abs(dy1)<=my && Abs(dx1)<Abs(dx) && Abs(dy1)<Abs(dy)) { + dx=-dx1; + dy=-dy1; + } + nMaxPointSnapCount--; + } + } + if (bOFrmSnap && nMaxFrameSnapCount>0) { + Rectangle aLog(pO->GetSnapRect()); + Rectangle aR1(aLog); + aR1.Left ()-=mx; + aR1.Right ()+=mx; + aR1.Top ()-=my; + aR1.Bottom()+=my; + if (aR1.IsInside(rPnt)) { + if (Abs(x-aLog.Left ())<=mx) { dx1=-(x-aLog.Left ()); if (Abs(dx1)<Abs(dx)) dx=dx1; } + if (Abs(x-aLog.Right ())<=mx) { dx1=-(x-aLog.Right ()); if (Abs(dx1)<Abs(dx)) dx=dx1; } + if (Abs(y-aLog.Top ())<=my) { dy1=-(y-aLog.Top ()); if (Abs(dy1)<Abs(dy)) dy=dy1; } + if (Abs(y-aLog.Bottom())<=my) { dy1=-(y-aLog.Bottom()); if (Abs(dy1)<Abs(dy)) dy=dy1; } + } + nMaxFrameSnapCount--; + } + } + } + } + if(bGridSnap) + { + double fSnapWidth = aSnapWdtX; + if(dx == NOT_SNAPPED && fSnapWidth != 0.0) + { + double fx = (double)x; + + // round statt trunc + if(fx - (double)pPV->GetPageOrigin().X() >= 0.0) + fx += fSnapWidth / 2.0; + else + fx -= fSnapWidth / 2.0; + + x = (long)((fx - (double)pPV->GetPageOrigin().X()) / fSnapWidth); + x = (long)((double)x * fSnapWidth + (double)pPV->GetPageOrigin().X()); + dx = 0; + } + fSnapWidth = aSnapWdtY; + if(dy == NOT_SNAPPED && fSnapWidth) + { + double fy = (double)y; + + // round statt trunc + if(fy - (double)pPV->GetPageOrigin().Y() >= 0.0) + fy += fSnapWidth / 2.0; + else + fy -= fSnapWidth / 2.0; + + y = (long)((fy - (double)pPV->GetPageOrigin().Y()) / fSnapWidth); + y = (long)((double)y * fSnapWidth + (double)pPV->GetPageOrigin().Y()); + dy = 0; + } + } + BOOL bRet=SDRSNAP_NOTSNAPPED; + if (dx==NOT_SNAPPED) dx=0; else bRet|=SDRSNAP_XSNAPPED; + if (dy==NOT_SNAPPED) dy=0; else bRet|=SDRSNAP_YSNAPPED; + rPnt.X()=x+dx; + rPnt.Y()=y+dy; + return bRet; +} + +void SdrSnapView::CheckSnap(const Point& rPt, const SdrPageView* pPV, long& nBestXSnap, long& nBestYSnap, bool& bXSnapped, bool& bYSnapped) const +{ + Point aPt(rPt); + USHORT nRet=SnapPos(aPt,pPV); + aPt-=rPt; + if ((nRet & SDRSNAP_XSNAPPED) !=0) { + if (bXSnapped) { + if (Abs(aPt.X())<Abs(nBestXSnap)) { + nBestXSnap=aPt.X(); + } + } else { + nBestXSnap=aPt.X(); + bXSnapped=TRUE; + } + } + if ((nRet & SDRSNAP_YSNAPPED) !=0) { + if (bYSnapped) { + if (Abs(aPt.Y())<Abs(nBestYSnap)) { + nBestYSnap=aPt.Y(); + } + } else { + nBestYSnap=aPt.Y(); + bYSnapped=TRUE; + } + } +} + +USHORT SdrSnapView::SnapRect(const Rectangle& rRect, const SdrPageView* pPV, long& rDX, long& rDY) const +{ + long nBestXSnap=0; + long nBestYSnap=0; + bool bXSnapped=FALSE; + bool bYSnapped=FALSE; + CheckSnap(rRect.TopLeft() ,pPV,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped); + if (!bMoveSnapOnlyTopLeft) { + CheckSnap(rRect.TopRight() ,pPV,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped); + CheckSnap(rRect.BottomLeft() ,pPV,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped); + CheckSnap(rRect.BottomRight(),pPV,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped); + } + rDX=nBestXSnap; + rDY=nBestYSnap; + USHORT nRet=0; + if (bXSnapped) nRet+=SDRSNAP_XSNAPPED; + if (bYSnapped) nRet+=SDRSNAP_YSNAPPED; + return nRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_Bool SdrSnapView::BegSetPageOrg(const Point& rPnt) +{ + BrkAction(); + + DBG_ASSERT(0L == mpPageOriginOverlay, "SdrSnapView::BegSetPageOrg: There exists a ImplPageOriginOverlay (!)"); + basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); + mpPageOriginOverlay = new ImplPageOriginOverlay(*this, aStartPos); + aDragStat.Reset(GetSnapPos(rPnt,NULL)); + + return sal_True; +} + +void SdrSnapView::MovSetPageOrg(const Point& rPnt) +{ + if(IsSetPageOrg()) + { + aDragStat.NextMove(GetSnapPos(rPnt,NULL)); + DBG_ASSERT(mpPageOriginOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + basegfx::B2DPoint aNewPos(aDragStat.GetNow().X(), aDragStat.GetNow().Y()); + mpPageOriginOverlay->SetPosition(aNewPos); + } +} + +sal_Bool SdrSnapView::EndSetPageOrg() +{ + sal_Bool bRet(sal_False); + + if(IsSetPageOrg()) + { + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + Point aPnt(aDragStat.GetNow()); + pPV->SetPageOrigin(aPnt); + bRet = sal_True; + } + + // cleanup + BrkSetPageOrg(); + } + + return bRet; +} + +void SdrSnapView::BrkSetPageOrg() +{ + if(IsSetPageOrg()) + { + DBG_ASSERT(mpPageOriginOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); + delete mpPageOriginOverlay; + mpPageOriginOverlay = 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_Bool SdrSnapView::PickHelpLine(const Point& rPnt, short nTol, const OutputDevice& rOut, USHORT& rnHelpLineNum, SdrPageView*& rpPV) const +{ + rpPV=NULL; + nTol=ImpGetHitTolLogic(nTol,&rOut); + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + Point aPnt(rPnt); + USHORT nIndex=pPV->GetHelpLines().HitTest(aPnt,USHORT(nTol),rOut); + if (nIndex!=SDRHELPLINE_NOTFOUND) { + rpPV=pPV; + rnHelpLineNum=nIndex; + return sal_True; + } + } + return sal_False; +} + +// start HelpLine drag for new HelpLine +sal_Bool SdrSnapView::BegDragHelpLine(USHORT nHelpLineNum, SdrPageView* pPV) +{ + sal_Bool bRet(sal_False); + + if(!bHlplFixed) + { + BrkAction(); + + if(pPV && nHelpLineNum < pPV->GetHelpLines().GetCount()) + { + const SdrHelpLineList& rHelpLines = pPV->GetHelpLines(); + const SdrHelpLine& rHelpLine = rHelpLines[nHelpLineNum]; + Point aHelpLinePos = rHelpLine.GetPos(); // + pPV->GetOffset(); + basegfx::B2DPoint aStartPos(aHelpLinePos.X(), aHelpLinePos.Y()); + + DBG_ASSERT(0L == mpHelpLineOverlay, "SdrSnapView::BegDragHelpLine: There exists a ImplHelpLineOverlay (!)"); + mpHelpLineOverlay = new ImplHelpLineOverlay(*this, aStartPos, pPV, nHelpLineNum, rHelpLine.GetKind()); + + aDragStat.Reset(GetSnapPos(aHelpLinePos, pPV)); + aDragStat.SetMinMove(ImpGetMinMovLogic(-3, 0L)); + + bRet = sal_True; + } + } + + return bRet; +} + +// start HelpLine drag with existing HelpLine +sal_Bool SdrSnapView::BegDragHelpLine(const Point& rPnt, SdrHelpLineKind eNewKind) +{ + sal_Bool bRet(sal_False); + + BrkAction(); + + if(GetSdrPageView()) + { + DBG_ASSERT(0L == mpHelpLineOverlay, "SdrSnapView::BegDragHelpLine: There exists a ImplHelpLineOverlay (!)"); + basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); + mpHelpLineOverlay = new ImplHelpLineOverlay(*this, aStartPos, 0L, 0, eNewKind); + aDragStat.Reset(GetSnapPos(rPnt, 0L)); + bRet = sal_True; + } + + return bRet; +} + +Pointer SdrSnapView::GetDraggedHelpLinePointer() const +{ + if(IsDragHelpLine()) + { + switch(mpHelpLineOverlay->GetHelpLineKind()) + { + case SDRHELPLINE_VERTICAL : return Pointer(POINTER_ESIZE); + case SDRHELPLINE_HORIZONTAL: return Pointer(POINTER_SSIZE); + default : return Pointer(POINTER_MOVE); + } + } + + return Pointer(POINTER_MOVE); +} + +void SdrSnapView::MovDragHelpLine(const Point& rPnt) +{ + if(IsDragHelpLine() && aDragStat.CheckMinMoved(rPnt)) + { + Point aPnt(GetSnapPos(rPnt, 0L)); + + if(aPnt != aDragStat.GetNow()) + { + aDragStat.NextMove(aPnt); + DBG_ASSERT(mpHelpLineOverlay, "SdrSnapView::MovDragHelpLine: no ImplHelpLineOverlay (!)"); + basegfx::B2DPoint aNewPos(aDragStat.GetNow().X(), aDragStat.GetNow().Y()); + mpHelpLineOverlay->SetPosition(aNewPos); + } + } +} + +sal_Bool SdrSnapView::EndDragHelpLine() +{ + sal_Bool bRet(sal_False); + + if(IsDragHelpLine()) + { + if(aDragStat.IsMinMoved()) + { + SdrPageView* pPageView = mpHelpLineOverlay->GetPageView(); + + if(pPageView) + { + // moved existing one + Point aPnt(aDragStat.GetNow()); + const SdrHelpLineList& rHelpLines = pPageView->GetHelpLines(); + SdrHelpLine aChangedHelpLine = rHelpLines[mpHelpLineOverlay->GetHelpLineNumber()]; + aChangedHelpLine.SetPos(aPnt); + pPageView->SetHelpLine(mpHelpLineOverlay->GetHelpLineNumber(), aChangedHelpLine); + + bRet = sal_True; + } + else + { + // create new one + pPageView = GetSdrPageView(); + + if(pPageView) + { + Point aPnt(aDragStat.GetNow()); + SdrHelpLine aNewHelpLine(mpHelpLineOverlay->GetHelpLineKind(), aPnt); + pPageView->InsertHelpLine(aNewHelpLine); + + bRet = sal_True; + } + } + } + + // cleanup + BrkDragHelpLine(); + } + + return bRet; +} + +void SdrSnapView::BrkDragHelpLine() +{ + if(IsDragHelpLine()) + { + DBG_ASSERT(mpHelpLineOverlay, "SdrSnapView::EndDragHelpLine: no ImplHelpLineOverlay (!)"); + delete mpHelpLineOverlay; + mpHelpLineOverlay = 0L; + } +} + +// eof diff --git a/svx/source/svdraw/svdstr.src b/svx/source/svdraw/svdstr.src new file mode 100644 index 000000000000..1317a0e1328d --- /dev/null +++ b/svx/source/svdraw/svdstr.src @@ -0,0 +1,2935 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +/* StarView resource file */ + +#include "svdstr.hrc" + // Ab hier gecachte Strings +String STR_ObjNameSingulNONE +{ + Text [ en-US ] = "draw object" ; +}; +String STR_ObjNamePluralNONE +{ + Text [ en-US ] = "draw objects" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulGRUP +{ + Text [ en-US ] = "group object" ; +}; +String STR_ObjNamePluralGRUP +{ + Text [ en-US ] = "group objects" ; +}; +String STR_ObjNameSingulGRUPEMPTY +{ + Text [ en-US ] = "blank group object" ; +}; +String STR_ObjNamePluralGRUPEMPTY +{ + Text [ en-US ] = "Blank group objects" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulLINE +{ + Text [ en-US ] = "Line" ; +}; +String STR_ObjNameSingulLINE_Hori +{ + Text [ en-US ] = "horizontal line" ; +}; +String STR_ObjNameSingulLINE_Vert +{ + Text [ en-US ] = "Vertical line" ; +}; +String STR_ObjNameSingulLINE_Diag +{ + Text [ en-US ] = "diagonal line" ; +}; +String STR_ObjNamePluralLINE +{ + Text [ en-US ] = "Lines" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulRECT +{ + Text [ en-US ] = "Rectangle" ; +}; +String STR_ObjNamePluralRECT +{ + Text [ en-US ] = "Rectangles" ; +}; +String STR_ObjNameSingulQUAD +{ + Text [ en-US ] = "Square" ; +}; +String STR_ObjNamePluralQUAD +{ + Text [ en-US ] = "Squares" ; +}; +String STR_ObjNameSingulPARAL +{ + Text [ en-US ] = "Parallelogram" ; +}; +String STR_ObjNamePluralPARAL +{ + Text [ en-US ] = "Parallelograms" ; +}; +String STR_ObjNameSingulRAUTE +{ + Text [ en-US ] = "Rhombus" ; +}; +String STR_ObjNamePluralRAUTE +{ + Text [ en-US ] = "Rhombuses" ; +}; +String STR_ObjNameSingulRECTRND +{ + Text [ en-US ] = "Rounded rectangle" ; +}; +String STR_ObjNamePluralRECTRND +{ + Text [ en-US ] = "Rounded Rectangles" ; +}; +String STR_ObjNameSingulQUADRND +{ + Text [ en-US ] = "rounded square" ; +}; +String STR_ObjNamePluralQUADRND +{ + Text [ en-US ] = "Rounded Squares" ; +}; +String STR_ObjNameSingulPARALRND +{ + Text [ en-US ] = "Rounded Parallelogram" ; +}; +String STR_ObjNamePluralPARALRND +{ + Text [ en-US ] = "Rounded parallelograms" ; +}; +String STR_ObjNameSingulRAUTERND +{ + Text [ en-US ] = "rounded rhombus" ; +}; +String STR_ObjNamePluralRAUTERND +{ + Text [ en-US ] = "Rounded rhombuses" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulCIRC +{ + Text [ en-US ] = "Circle" ; +}; +String STR_ObjNamePluralCIRC +{ + Text [ en-US ] = "Circles" ; +}; +String STR_ObjNameSingulSECT +{ + Text [ en-US ] = "Circle sector" ; +}; +String STR_ObjNamePluralSECT +{ + Text [ en-US ] = "Circle sectors" ; +}; +String STR_ObjNameSingulCARC +{ + Text [ en-US ] = "Arc" ; +}; +String STR_ObjNamePluralCARC +{ + Text [ en-US ] = "Arcs" ; +}; +String STR_ObjNameSingulCCUT +{ + Text [ en-US ] = "Circle segment" ; +}; +String STR_ObjNamePluralCCUT +{ + Text [ en-US ] = "Circle segments" ; +}; +String STR_ObjNameSingulCIRCE +{ + Text [ en-US ] = "Ellipse" ; +}; +String STR_ObjNamePluralCIRCE +{ + Text [ en-US ] = "Ellipses" ; +}; +String STR_ObjNameSingulSECTE +{ + Text [ en-US ] = "Ellipse Pie" ; +}; +String STR_ObjNamePluralSECTE +{ + Text [ en-US ] = "Ellipse Pies" ; +}; +String STR_ObjNameSingulCARCE +{ + Text [ en-US ] = "Elliptical arc" ; +}; +String STR_ObjNamePluralCARCE +{ + Text [ en-US ] = "Elliptical arcs" ; +}; +String STR_ObjNameSingulCCUTE +{ + Text [ en-US ] = "Ellipse Segment" ; +}; +String STR_ObjNamePluralCCUTE +{ + Text [ en-US ] = "Ellipse Segments" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulPOLY +{ + Text [ en-US ] = "Polygon" ; +}; +String STR_ObjNameSingulPOLY_PntAnz +{ + Text [ en-US ] = "Polygon %2 corners" ; +}; +String STR_ObjNamePluralPOLY +{ + Text [ en-US ] = "Polygons" ; +}; +String STR_ObjNameSingulPLIN +{ + Text [ en-US ] = "Polyline" ; +}; +String STR_ObjNameSingulPLIN_PntAnz +{ + Text [ en-US ] = "Polyline with %2 corners" ; +}; +String STR_ObjNamePluralPLIN +{ + Text [ en-US ] = "Polylines" ; +}; +String STR_ObjNameSingulPATHLINE +{ + Text [ en-US ] = "Bézier curve" ; +}; +String STR_ObjNamePluralPATHLINE +{ + Text [ en-US ] = "Bézier curves" ; +}; +String STR_ObjNameSingulPATHFILL +{ + Text [ en-US ] = "Bézier curve" ; +}; +String STR_ObjNamePluralPATHFILL +{ + Text [ en-US ] = "Bézier curves" ; +}; +String STR_ObjNameSingulFREELINE +{ + Text [ en-US ] = "Freeform Line" ; +}; +String STR_ObjNamePluralFREELINE +{ + Text [ en-US ] = "Freeform Lines" ; +}; +String STR_ObjNameSingulFREEFILL +{ + Text [ en-US ] = "Freeform Line" ; +}; +String STR_ObjNamePluralFREEFILL +{ + Text [ en-US ] = "Freeform Lines" ; +}; +String STR_ObjNameSingulCOMBLINE +{ + Text [ en-US ] = "Curve" ; +}; +String STR_ObjNamePluralCOMBLINE +{ + Text [ en-US ] = "Curve objects" ; +}; +String STR_ObjNameSingulCOMBFILL +{ + Text [ en-US ] = "Curve" ; +}; +String STR_ObjNamePluralCOMBFILL +{ + Text [ en-US ] = "Curve objects" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulNATSPLN +{ + Text [ en-US ] = "Natural Spline" ; +}; +String STR_ObjNamePluralNATSPLN +{ + Text [ en-US ] = "Natural Splines" ; +}; +String STR_ObjNameSingulPERSPLN +{ + Text [ en-US ] = "Periodic Spline" ; +}; +String STR_ObjNamePluralPERSPLN +{ + Text [ en-US ] = "Periodic Splines" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulTEXT +{ + Text [ en-US ] = "Text Frame" ; +}; +String STR_ObjNamePluralTEXT +{ + Text [ en-US ] = "Text Frame" ; +}; +String STR_ObjNameSingulTEXTLNK +{ + Text [ en-US ] = "Linked text frame" ; +}; +String STR_ObjNamePluralTEXTLNK +{ + Text [ en-US ] = "Linked text frames" ; +}; + //String STR_ObjNameSingulXTXT { + // Text="Textfortsetzungsrahmen"; + // Text[ENGLISH]="drawobject"; + // Text[norwegian]="Tegneobjekt"; + // Text[italian]="Disegna oggetto"; + // Text[portuguese_brazilian]="Desenhar objeto"; + // Text[portuguese]="Desenhar objecto"; + // Text[finnish]="Piirto-objekti"; + // Text[danish]="Tegneobjekt"; + // Text[french]="Drawobject"; + // Text[swedish]="Ritobjekt"; + // Text[dutch]="Tekenobject"; + // Text[spanish]="Objeto de dibujo"; + // Text[english_us]="drawobject"; + //}; + //String STR_ObjNamePluralXTXT { + // Text="Textfortsetzungsrahmen"; + // Text[ENGLISH]="drawobjects"; + // Text[norwegian]="Tegneobjektr"; + // Text[italian]="Disegna oggetti"; + // Text[portuguese_brazilian]="Desenhar objetos"; + // Text[portuguese]="Desenhar objectos"; + // Text[finnish]="Piirto-objektit"; + // Text[danish]="Tegneobjekter"; + // Text[french]="Drawobjects"; + // Text[swedish]="Ritobjekt"; + // Text[dutch]="Tekenobjecten"; + // Text[spanish]="Objetos de dibujo"; + // Text[english_us]="drawobjects"; + //}; +String STR_ObjNameSingulFITTEXT +{ + Text [ en-US ] = "Fit-to-size text object" ; +}; +String STR_ObjNamePluralFITTEXT +{ + Text [ en-US ] = "Fit-to-size text objects" ; +}; +String STR_ObjNameSingulFITALLTEXT +{ + Text [ en-US ] = "Fit-to-size text object" ; +}; +String STR_ObjNamePluralFITALLTEXT +{ + Text [ en-US ] = "Fit-to-size text objects" ; +}; +String STR_ObjNameSingulTITLETEXT +{ + Text [ en-US ] = "Title text" ; +}; +String STR_ObjNamePluralTITLETEXT +{ + Text [ en-US ] = "Title texts" ; +}; +String STR_ObjNameSingulOUTLINETEXT +{ + Text [ en-US ] = "Outline Text" ; +}; +String STR_ObjNamePluralOUTLINETEXT +{ + Text [ en-US ] = "Outline Texts" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulGRAF +{ + Text [ en-US ] = "graphic" ; +}; +String STR_ObjNamePluralGRAF +{ + Text [ en-US ] = "graphics" ; +}; +String STR_ObjNameSingulGRAFLNK +{ + Text [ en-US ] = "Linked graphic" ; +}; +String STR_ObjNamePluralGRAFLNK +{ + Text [ en-US ] = "Linked graphics" ; +}; +String STR_ObjNameSingulGRAFNONE +{ + Text [ en-US ] = "Blank graphic object" ; +}; +String STR_ObjNamePluralGRAFNONE +{ + Text [ en-US ] = "Blank graphic objects" ; +}; +String STR_ObjNameSingulGRAFNONELNK +{ + Text [ en-US ] = "Blank linked graphic" ; +}; +String STR_ObjNamePluralGRAFNONELNK +{ + Text [ en-US ] = "Blank linked graphics" ; +}; +String STR_ObjNameSingulGRAFMTF +{ + Text [ en-US ] = "Metafile" ; +}; +String STR_ObjNamePluralGRAFMTF +{ + Text [ en-US ] = "Metafiles" ; +}; +String STR_ObjNameSingulGRAFMTFLNK +{ + Text [ en-US ] = "Linked Metafile" ; +}; +String STR_ObjNamePluralGRAFMTFLNK +{ + Text [ en-US ] = "Linked Metafiles" ; +}; +String STR_ObjNameSingulGRAFBMP +{ + Text [ en-US ] = "Bitmap" ; +}; +String STR_ObjNameSingulGRAFBMPTRANS +{ + Text [ en-US ] = "Bitmap with transparency" ; +}; +String STR_ObjNameSingulGRAFBMPLNK +{ + Text [ en-US ] = "Linked Bitmap" ; +}; +String STR_ObjNameSingulGRAFBMPTRANSLNK +{ + Text [ en-US ] = "Linked bitmap with transparency" ; +}; +String STR_ObjNamePluralGRAFBMP +{ + Text [ en-US ] = "Bitmaps" ; +}; +String STR_ObjNamePluralGRAFBMPTRANS +{ + Text [ en-US ] = "Bitmaps with transparency" ; +}; +String STR_ObjNamePluralGRAFBMPLNK +{ + Text [ en-US ] = "Linked bitmaps" ; +}; +String STR_ObjNamePluralGRAFBMPTRANSLNK +{ + Text [ en-US ] = "Linked bitmaps with transparency" ; +}; +String STR_ObjNameSingulCUSTOMSHAPE +{ + Text [ en-US ] = "Shape"; +}; +String STR_ObjNamePluralCUSTOMSHAPE +{ + Text [ en-US ] = "Shapes"; +}; +String STR_ObjNameSingulGRAFMAC +{ + Text [ en-US ] = "Mac graphic" ; +}; +String STR_ObjNamePluralGRAFMAC +{ + Text [ en-US ] = "Mac graphics" ; +}; +String STR_ObjNameSingulGRAFMACLNK +{ + Text [ en-US ] = "Linked Mac graphic" ; +}; +String STR_ObjNamePluralGRAFMACLNK +{ + Text [ en-US ] = "Linked Mac graphics" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulOLE2 +{ + Text [ en-US ] = "embedded object (OLE)" ; +}; +String STR_ObjNamePluralOLE2 +{ + Text [ en-US ] = "Embedded objects (OLE)" ; +}; +String STR_ObjNameSingulUno +{ + Text [ en-US ] = "Control"; +}; +String STR_ObjNamePluralUno +{ + Text [ en-US ] = "Controls"; +}; +String STR_ObjNameSingulOLE2LNK +{ + Text [ en-US ] = "linked embedded object (OLE)" ; +}; +String STR_ObjNamePluralOLE2LNK +{ + Text [ en-US ] = "Linked embedded objects (OLE)" ; +}; +String STR_ObjOLE2NamePrefix +{ + Text [ en-US ] = "Object" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulFrame +{ + Text [ en-US ] = "Frame" ; +}; +String STR_ObjNamePluralFrame +{ + Text [ en-US ] = "Frames" ; +}; +String STR_ObjFrameNamePrefix +{ + Text [ en-US ] = "Frame" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulEDGE +{ + Text [ en-US ] = "Object Connectors" ; +}; +String STR_ObjNamePluralEDGE +{ + Text [ en-US ] = "Object Connectors" ; +}; +String STR_ObjNameSingulCAPTION +{ + Text [ en-US ] = "Callout" ; +}; +String STR_ObjNamePluralCAPTION +{ + Text [ en-US ] = "Callouts" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ObjNameSingulPAGE +{ + Text [ en-US ] = "Preview object" ; +}; +String STR_ObjNamePluralPAGE +{ + Text [ en-US ] = "Preview objects" ; +}; +String STR_ObjNameSingulMEASURE +{ + Text [ en-US ] = "Dimension line" ; +}; +String STR_ObjNamePluralMEASURE +{ + Text [ en-US ] = "Dimensioning objects" ; +}; +String STR_ObjNamePlural +{ + Text [ en-US ] = "draw objects" ; +}; +String STR_ObjNameNoObj +{ + Text [ en-US ] = "No draw object" ; +}; +String STR_ObjNameAnd +{ + Text [ en-US ] = "and" ; +}; +String STR_ObjNameSingulPlural +{ + Text [ en-US ] = "draw object(s)" ; +}; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + +// Neu ab 537: Namen fuer 3D-Objekte +String STR_ObjNameSingulCube3d +{ + Text [ en-US ] = "3D cube"; +}; + +String STR_ObjNamePluralCube3d +{ + Text [ en-US ] = "3D cubes"; +}; + +String STR_ObjNameSingulExtrude3d +{ + Text [ en-US ] = "Extrusion object"; +}; + +String STR_ObjNamePluralExtrude3d +{ + Text [ en-US ] = "Extrusion objects"; +}; + +String STR_ObjNameSingulLabel3d +{ + Text [ en-US ] = "3D text"; +}; + +String STR_ObjNamePluralLabel3d +{ + Text [ en-US ] = "3D texts"; +}; + +String STR_ObjNameSingulLathe3d +{ + Text [ en-US ] = "rotation object"; +}; + +String STR_ObjNamePluralLathe3d +{ + Text [ en-US ] = "rotation objects"; +}; + +String STR_ObjNameSingulObj3d +{ + Text [ en-US ] = "3D object"; +}; + +String STR_ObjNamePluralObj3d +{ + Text [ en-US ] = "3D objects"; +}; + +String STR_ObjNamePluralPoly3d +{ + Text [ en-US ] = "3D polygons"; +}; + +String STR_ObjNameSingulScene3d +{ + Text [ en-US ] = "3D scene"; +}; + +String STR_ObjNamePluralScene3d +{ + Text [ en-US ] = "3D scenes"; +}; + +String STR_ObjNameSingulSphere3d +{ + Text [ en-US ] = "sphere"; +}; + +String STR_ObjNamePluralSphere3d +{ + Text [ en-US ] = "spheres"; +}; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + +String STR_EditWithCopy +{ + Text [ en-US ] = "with copy" ; +}; +String STR_EditPosSize +{ + Text [ en-US ] = "Set position and size for %1" ; +}; +String STR_EditDelete +{ + Text [ en-US ] = "Delete %1" ; +}; +String STR_EditMovToTop +{ + Text [ en-US ] = "Move %1 forward" ; +}; +String STR_EditMovToBtm +{ + Text [ en-US ] = "Move %1 further back" ; +}; +String STR_EditPutToTop +{ + Text [ en-US ] = "Move %1 to front" ; +}; +String STR_EditPutToBtm +{ + Text [ en-US ] = "Move %1 to back" ; +}; +String STR_EditRevOrder +{ + Text [ en-US ] = "Reverse order of %1" ; +}; +String STR_EditMove +{ + Text [ en-US ] = "Move %1" ; +}; +String STR_EditResize +{ + Text [ en-US ] = "Resize %1" ; +}; +String STR_EditRotate +{ + Text [ en-US ] = "Rotate %1" ; +}; +String STR_EditMirrorHori +{ + Text [ en-US ] = "Flip %1 horizontal" ; +}; +String STR_EditMirrorVert +{ + Text [ en-US ] = "Flip %1 vertical" ; +}; +String STR_EditMirrorDiag +{ + Text [ en-US ] = "Flip %1 diagonal" ; +}; +String STR_EditMirrorFree +{ + Text [ en-US ] = "Flip %1 freehand" ; +}; +String STR_EditShear +{ + Text [ en-US ] = "Distort %1 (slant)" ; +}; +String STR_EditCrook +{ + Text [ en-US ] = "Arrange %1 in circle" ; +}; +String STR_EditCrookContortion +{ + Text [ en-US ] = "Curve %1 in circle" ; +}; +String STR_EditDistort +{ + Text [ en-US ] = "Distort %1" ; +}; +String STR_EditRipUp +{ + Text [ en-US ] = "Undo %1" ; +}; +String STR_EditSetPointsSmooth +{ + Text [ en-US ] = "Modify bézier properties of %1" ; +}; +String STR_EditSetSegmentsKind +{ + Text [ en-US ] = "Modify bézier properties of %1" ; +}; +String STR_EditShut +{ + Text [ en-US ] = "Close %1" ; +}; +String STR_EditSetGlueEscDir +{ + Text [ en-US ] = "Set exit direction for %1" ; +}; +String STR_EditSetGluePercent +{ + Text [ en-US ] = "Set relative attribute at %1" ; +}; +String STR_EditSetGlueAlign +{ + Text [ en-US ] = "Set reference point for %1" ; +}; +String STR_EditGroup +{ + Text [ en-US ] = "Group %1" ; +}; +String STR_EditUngroup +{ + Text [ en-US ] = "Ungroup %1" ; +}; +String STR_EditSetAttributes +{ + Text [ en-US ] = "Apply attributes to %1" ; +}; +String STR_EditSetStylesheet +{ + Text [ en-US ] = "Apply Styles to %1" ; +}; +String STR_EditDelStylesheet +{ + Text [ en-US ] = "Remove Style from %1" ; +}; +String STR_EditConvToPoly +{ + Text [ en-US ] = "Convert %1 to polygon" ; +}; +String STR_EditConvToPolys +{ + Text [ en-US ] = "Convert %1 to polygons" ; +}; +String STR_EditConvToCurve +{ + Text [ en-US ] = "Convert %1 to curve" ; +}; +String STR_EditConvToCurves +{ + Text [ en-US ] = "Convert %1 to curves" ; +}; +String STR_EditConvToContour +{ + Text [ en-US ] = "Convert %1 to contour"; +}; +String STR_EditConvToContours +{ + Text [ en-US ] = "Convert %1 to contours"; +}; +String STR_EditAlign +{ + Text [ en-US ] = "Align %1" ; +}; +String STR_EditAlignVTop +{ + Text [ en-US ] = "Align %1 to top" ; +}; +String STR_EditAlignVBottom +{ + Text [ en-US ] = "Align %1 to bottom" ; +}; +String STR_EditAlignVCenter +{ + Text [ en-US ] = "Horizontally center %1" ; +}; +String STR_EditAlignHLeft +{ + Text [ en-US ] = "Align %1 to left" ; +}; +String STR_EditAlignHRight +{ + Text [ en-US ] = "Align %1 to right" ; +}; +String STR_EditAlignHCenter +{ + Text [ en-US ] = "Vertically center %1" ; +}; +String STR_EditAlignCenter +{ + Text [ en-US ] = "Center %1" ; +}; +String STR_EditTransform +{ + Text [ en-US ] = "Transform %1" ; +}; +String STR_EditCombine_PolyPoly +{ + Text [ en-US ] = "Combine %1" ; +}; +String STR_EditMergeMergePoly +{ + Text [ en-US ] = "Merge %1"; +}; +String STR_EditMergeSubstractPoly +{ + Text [ en-US ] = "Subtract %1"; +}; +String STR_EditMergeIntersectPoly +{ + Text [ en-US ] = "Intersect %1"; +}; +String STR_DistributeMarkedObjects +{ + Text [ en-US ] = "Distribute selected objects"; +}; +String STR_EditCombine_OnePoly +{ + Text [ en-US ] = "Combine %1" ; +}; +String STR_EditDismantle_Polys +{ + Text [ en-US ] = "Split %1" ; +}; +String STR_EditDismantle_Lines +{ + Text [ en-US ] = "Split %1" ; +}; +String STR_EditImportMtf +{ + Text [ en-US ] = "Split %1" ; +}; +String STR_EditImportSGV +{ + Text = "StarDraw Dos Zeichnung importieren" ; +}; +String STR_EditImportHPGL +{ + Text = "HPGL importieren" ; +}; +String STR_EditImportDXF +{ + Text = "DXF importieren" ; +}; +String STR_ExchangePaste +{ + Text [ en-US ] = "Insert object(s)" ; +}; +String STR_ExchangeClpCut +{ + Text [ en-US ] = "Cut %1" ; +}; +String STR_ExchangeClpPaste +{ + Text [ en-US ] = "Paste Clipboard" ; +}; +String STR_ExchangeDD +{ + Text [ en-US ] = "Drag and Drop %1" ; +}; +String STR_ExchangeDDPaste +{ + Text [ en-US ] = "Insert Drag and Drop" ; +}; +String STR_DragInsertPoint +{ + Text [ en-US ] = "Insert point to %1" ; +}; +String STR_DragInsertGluePoint +{ + Text [ en-US ] = "Insert glue point to %1" ; +}; +String STR_DragMethMovHdl +{ + Text [ en-US ] = "Move reference-point" ; +}; +String STR_DragMethObjOwn +{ + Text [ en-US ] = "Geometrically change %1" ; +}; +String STR_DragMethMove +{ + Text [ en-US ] = "Move %1" ; +}; +String STR_DragMethResize +{ + Text [ en-US ] = "Resize %1" ; +}; +String STR_DragMethRotate +{ + Text [ en-US ] = "Rotate %1" ; +}; +String STR_DragMethMirrorHori +{ + Text [ en-US ] = "Flip %1 horizontal" ; +}; +String STR_DragMethMirrorVert +{ + Text [ en-US ] = "Flip %1 vertical" ; +}; +String STR_DragMethMirrorDiag +{ + Text [ en-US ] = "Flip %1 diagonal" ; +}; +String STR_DragMethMirrorFree +{ + Text [ en-US ] = "Flip %1 freehand" ; +}; +String STR_DragMethGradient +{ + Text [ en-US ] = "Interactive gradient for %1"; +}; +String STR_DragMethTransparence +{ + Text [ en-US ] = "Interactive transparency for %1"; +}; +String STR_DragMethShear +{ + Text [ en-US ] = "Distort %1 (slant)" ; +}; +String STR_DragMethCrook +{ + Text [ en-US ] = "Arrange %1 in circle" ; +}; +String STR_DragMethCrookContortion +{ + Text [ en-US ] = "Curve %1 in circle" ; +}; +String STR_DragMethDistort +{ + Text [ en-US ] = "Distort %1" ; +}; +String STR_DragMethCrop +{ + Text [ en-US ] = "Crop %O" ; +}; + +String STR_DragRectEckRad +{ + Text [ en-US ] = "Alter radius by %1" ; +}; +String STR_DragPathObj +{ + Text [ en-US ] = "Change %1" ; +}; +String STR_DragRectResize +{ + Text [ en-US ] = "Resize %1" ; +}; +String STR_DragCaptFram +{ + Text [ en-US ] = "Move %1" ; +}; +String STR_DragCaptTail +{ + Text [ en-US ] = "Move end point of %1" ; +}; +String STR_DragCircAngle +{ + Text [ en-US ] = "Adjust angle by %1" ; +}; +String STR_DragEdgeTail +{ + Text [ en-US ] = "Change %1" ; +}; +String STR_ViewTextEdit +{ + Text [ en-US ] = "TextEdit: Paragraph %1, Row %2, Column %3" ; +}; +String STR_ViewMarked +{ + Text [ en-US ] = "%1 selected" ; +}; +String STR_ViewMarkedPoint +{ + Text [ en-US ] = "Point from %1" ; +}; +String STR_ViewMarkedPoints +{ + Text [ en-US ] = "%2 points from %1" ; +}; +String STR_ViewMarkedGluePoint +{ + Text [ en-US ] = "Glue point from %1" ; +}; +String STR_ViewMarkedGluePoints +{ + Text [ en-US ] = "%2 glue points from %1" ; +}; +String STR_ViewMarkObjs +{ + Text [ en-US ] = "Mark objects" ; +}; +String STR_ViewMarkMoreObjs +{ + Text [ en-US ] = "Mark additional objects" ; +}; +String STR_ViewMarkPoints +{ + Text [ en-US ] = "Mark points" ; +}; +String STR_ViewMarkMorePoints +{ + Text [ en-US ] = "Mark additional points" ; +}; +String STR_ViewMarkGluePoints +{ + Text [ en-US ] = "Mark glue points" ; +}; +String STR_ViewMarkMoreGluePoints +{ + Text [ en-US ] = "Mark additional glue points" ; +}; +String STR_ViewCreateObj +{ + Text [ en-US ] = "Create %1" ; +}; +String STR_UndoInsertObj +{ + Text [ en-US ] = "Insert %1" ; +}; +String STR_UndoCopyObj +{ + Text [ en-US ] = "Copy %1" ; +}; +String STR_UndoObjOrdNum +{ + Text [ en-US ] = "Change object order of %1" ; +}; +String STR_UndoObjSetText +{ + Text [ en-US ] = "Edit text of %1" ; +}; +String STR_UndoNewPage +{ + Text [ en-US ] = "Insert page" ; +}; +String STR_UndoDelPage +{ + Text [ en-US ] = "Delete page" ; +}; +String STR_UndoCopPage +{ + Text [ en-US ] = "Copy page" ; +}; +String STR_UndoMovPage +{ + Text [ en-US ] = "Change order of pages" ; +}; +String STR_UndoNewPageMasterDscr +{ + Text [ en-US ] = "Assign background page" ; +}; +String STR_UndoDelPageMasterDscr +{ + Text [ en-US ] = "Clear background page assignment" ; +}; +String STR_UndoMovPageMasterDscr +{ + Text [ en-US ] = "Move background page assignment" ; +}; +String STR_UndoChgPageMasterDscr +{ + Text [ en-US ] = "Change background page assignment" ; +}; +String STR_UndoMergeModel +{ + Text [ en-US ] = "Insert document" ; +}; +String STR_UndoNewLayer +{ + Text [ en-US ] = "Insert Layer" ; +}; +String STR_UndoDelLayer +{ + Text [ en-US ] = "Delete layer" ; +}; +String STR_UndoMovLayer +{ + Text [ en-US ] = "Change order of layers" ; +}; +// --> OD 2009-07-09 #i73249# +String STR_UndoObjName +{ + Text [ en-US ] = "Change object name of %1 to" ; +}; +String STR_UndoObjTitle +{ + Text [ en-US ] = "Change object title of %1" ; +}; +String STR_UndoObjDescription +{ + Text [ en-US ] = "Change object description of %1" ; +}; +// <-- +String STR_StandardLayerName +{ + Text [ en-US ] = "Standard" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValON +{ + Text [ en-US ] = "on" ; +}; +String STR_ItemValOFF +{ + Text [ en-US ] = "off" ; +}; +String STR_ItemValYES +{ + Text [ en-US ] = "yes" ; +}; +String STR_ItemValNO +{ + Text [ en-US ] = "No" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValCAPTIONTYPE1 +{ + Text [ en-US ] = "Type 1" ; +}; +String STR_ItemValCAPTIONTYPE2 +{ + Text [ en-US ] = "Type 2" ; +}; +String STR_ItemValCAPTIONTYPE3 +{ + Text [ en-US ] = "Type 3" ; +}; +String STR_ItemValCAPTIONTYPE4 +{ + Text [ en-US ] = "Type 4" ; +}; +String STR_ItemValCAPTIONESCHORI +{ + Text [ en-US ] = "Horizontal" ; +}; +String STR_ItemValCAPTIONESCVERT +{ + Text [ en-US ] = "Vertical" ; +}; +String STR_ItemValCAPTIONESCBESTFIT +{ + Text [ en-US ] = "Automatic" ; +}; + /////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValFITTOSIZENONE +{ + Text [ en-US ] = "Off" ; +}; +String STR_ItemValFITTOSIZEPROP +{ + Text [ en-US ] = "Proportional" ; +}; +String STR_ItemValFITTOSIZEALLLINES +{ + Text [ en-US ] = "Fit to size (all rows separately) " ; +}; +String STR_ItemValFITTOSIZERESIZEAT +{ + Text [ en-US ] = "Use hard attributes" ; +}; + /////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValTEXTVADJTOP +{ + Text [ en-US ] = "Top" ; +}; +String STR_ItemValTEXTVADJCENTER +{ + Text [ en-US ] = "Center" ; +}; +String STR_ItemValTEXTVADJBOTTOM +{ + Text [ en-US ] = "Bottom" ; +}; +String STR_ItemValTEXTVADJBLOCK +{ + Text [ en-US ] = "Use entire height" ; +}; +String STR_ItemValTEXTVADJSTRETCH +{ + Text [ en-US ] = "Stretched" ; +}; +String STR_ItemValTEXTHADJLEFT +{ + Text [ en-US ] = "Left" ; +}; +String STR_ItemValTEXTHADJCENTER +{ + Text [ en-US ] = "Center" ; +}; +String STR_ItemValTEXTHADJRIGHT +{ + Text [ en-US ] = "Right" ; +}; +String STR_ItemValTEXTHADJBLOCK +{ + Text [ en-US ] = "Use entire width" ; +}; +String STR_ItemValTEXTHADJSTRETCH +{ + Text [ en-US ] = "Stretched" ; +}; + /////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValTEXTANI_NONE +{ + Text [ en-US ] = "off" ; +}; +String STR_ItemValTEXTANI_BLINK +{ + Text [ en-US ] = "flash" ; +}; +String STR_ItemValTEXTANI_SCROLL +{ + Text [ en-US ] = "Scroll Through" ; +}; +String STR_ItemValTEXTANI_ALTERNATE +{ + Text [ en-US ] = "alternating" ; +}; +String STR_ItemValTEXTANI_SLIDE +{ + Text [ en-US ] = "Scroll In" ; +}; +String STR_ItemValTEXTANI_LEFT +{ + Text [ en-US ] = "left" ; +}; +String STR_ItemValTEXTANI_UP +{ + Text [ en-US ] = "up" ; +}; +String STR_ItemValTEXTANI_RIGHT +{ + Text [ en-US ] = "right" ; +}; +String STR_ItemValTEXTANI_DOWN +{ + Text [ en-US ] = "down" ; +}; + /////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValEDGE_ORTHOLINES +{ + Text [ en-US ] = "Standard Connector" ; +}; +String STR_ItemValEDGE_THREELINES +{ + Text [ en-US ] = "Line Connector" ; +}; +String STR_ItemValEDGE_ONELINE +{ + Text [ en-US ] = "Straight Connector" ; +}; +String STR_ItemValEDGE_BEZIER +{ + Text [ en-US ] = "Curved Connector" ; +}; + /////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValMEASURE_STD +{ + Text [ en-US ] = "Standard" ; +}; +String STR_ItemValMEASURE_RADIUS +{ + Text [ en-US ] = "Radius" ; +}; +String STR_ItemValMEASURE_TEXTHAUTO +{ + Text [ en-US ] = "automatic" ; +}; +String STR_ItemValMEASURE_TEXTLEFTOUTSIDE +{ + Text [ en-US ] = "left outside" ; +}; +String STR_ItemValMEASURE_TEXTINSIDE +{ + Text [ en-US ] = "inside (centered)" ; +}; +String STR_ItemValMEASURE_TEXTRIGHTOUTSID +{ + Text [ en-US ] = "right outside" ; +}; +String STR_ItemValMEASURE_TEXTVAUTO +{ + Text [ en-US ] = "automatic" ; +}; +String STR_ItemValMEASURE_ABOVE +{ + Text [ en-US ] = "on the line" ; +}; +String STR_ItemValMEASURETEXT_BREAKEDLINE +{ + Text [ en-US ] = "broken line" ; +}; +String STR_ItemValMEASURE_BELOW +{ + Text [ en-US ] = "below the line" ; +}; +String STR_ItemValMEASURETEXT_VERTICALCEN +{ + Text [ en-US ] = "centered" ; +}; + /////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemValCIRC_FULL +{ + Text [ en-US ] = "full circle" ; +}; +String STR_ItemValCIRC_SECT +{ + Text [ en-US ] = "Circle Pie" ; +}; +String STR_ItemValCIRC_CUT +{ + Text [ en-US ] = "Circle segment" ; +}; +String STR_ItemValCIRC_ARC +{ + Text [ en-US ] = "Arc" ; +}; + /////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// +String STR_ItemNam_SHADOW +{ + Text [ en-US ] = "Shadow" ; +}; +String STR_ItemNam_SHADOWCOLOR +{ + Text [ en-US ] = "Shadow color" ; +}; +String STR_ItemNam_SHADOWXDIST +{ + Text [ en-US ] = "Horizontal shadow outline" ; +}; +String STR_ItemNam_SHADOWYDIST +{ + Text [ en-US ] = "Vertical shadow outline" ; +}; +String STR_ItemNam_SHADOWTRANSPARENCE +{ + Text [ en-US ] = "Shadow transparency" ; +}; +String STR_ItemNam_SHADOW3D +{ + Text [ en-US ] = "3D shadow" ; +}; +String STR_ItemNam_SHADOWPERSP +{ + Text [ en-US ] = "Perspective shadow" ; +}; +String STR_ItemNam_CAPTIONTYPE +{ + Text [ en-US ] = "Callout type" ; +}; +String STR_ItemNam_CAPTIONFIXEDANGLE +{ + Text [ en-US ] = "Given angle" ; +}; +String STR_ItemNam_CAPTIONANGLE +{ + Text [ en-US ] = "Angle" ; +}; +String STR_ItemNam_CAPTIONGAP +{ + Text [ en-US ] = "Gap" ; +}; +String STR_ItemNam_CAPTIONESCDIR +{ + Text [ en-US ] = "Exit direction" ; +}; +String STR_ItemNam_CAPTIONESCISREL +{ + Text [ en-US ] = "Relative exit position" ; +}; +String STR_ItemNam_CAPTIONESCREL +{ + Text [ en-US ] = "Exit Position" ; +}; +String STR_ItemNam_CAPTIONESCABS +{ + Text [ en-US ] = "Exit Position" ; +}; +String STR_ItemNam_CAPTIONLINELEN +{ + Text [ en-US ] = "Line length" ; +}; +String STR_ItemNam_CAPTIONFITLINELEN +{ + Text [ en-US ] = "Auto line length" ; +}; +String STR_ItemNam_ECKENRADIUS +{ + Text [ en-US ] = "Corner radius" ; +}; +String STR_ItemNam_TEXT_LEFTDIST +{ + Text [ en-US ] = "Left border spacing" ; +}; +String STR_ItemNam_TEXT_RIGHTDIST +{ + Text [ en-US ] = "Right border spacing" ; +}; +String STR_ItemNam_TEXT_UPPERDIST +{ + Text [ en-US ] = "Upper border spacing" ; +}; +String STR_ItemNam_TEXT_LOWERDIST +{ + Text [ en-US ] = "Lower border spacing" ; +}; +String STR_ItemNam_TEXT_AUTOGROWHEIGHT +{ + Text [ en-US ] = "AutoFit frame height" ; +}; +String STR_ItemNam_TEXT_MINFRAMEHEIGHT +{ + Text [ en-US ] = "Min. frame height" ; +}; +String STR_ItemNam_TEXT_MAXFRAMEHEIGHT +{ + Text [ en-US ] = "Max. frame height" ; +}; +String STR_ItemNam_TEXT_AUTOGROWWIDTH +{ + Text [ en-US ] = "AutoFit frame width" ; +}; +String STR_ItemNam_TEXT_MINFRAMEWIDTH +{ + Text [ en-US ] = "Min. frame width" ; +}; +String STR_ItemNam_TEXT_MAXFRAMEWIDTH +{ + Text [ en-US ] = "Max. frame width" ; +}; +String STR_ItemNam_TEXT_VERTADJUST +{ + Text [ en-US ] = "Vertical text anchor" ; +}; +String STR_ItemNam_TEXT_HORZADJUST +{ + Text [ en-US ] = "Horizontal text anchor" ; +}; +String STR_ItemNam_TEXT_FITTOSIZE +{ + Text [ en-US ] = "Fit text to frame" ; +}; + +String STR_ItemNam_GRAFRED +{ + Text [ en-US ] = "Red"; +}; +String STR_ItemNam_GRAFGREEN +{ + Text [ en-US ] = "Green"; +}; +String STR_ItemNam_GRAFBLUE +{ + Text [ en-US ] = "Blue"; +}; +String STR_ItemNam_GRAFLUMINANCE +{ + Text [ en-US ] = "Brightness"; +}; +String STR_ItemNam_GRAFCONTRAST +{ + Text [ en-US ] = "Contrast"; +}; +String STR_ItemNam_GRAFGAMMA +{ + Text [ en-US ] = "Gamma"; +}; +String STR_ItemNam_GRAFTRANSPARENCE +{ + Text [ en-US ] = "Transparency"; +}; +String STR_ItemNam_GRAFINVERT +{ + Text [ en-US ] = "Invert"; +}; +String STR_ItemNam_GRAFMODE +{ + Text [ en-US ] = "Graphics mode"; +}; +String STR_ItemNam_GRAFRESERVE2 { Text = "" ; }; +String STR_ItemNam_GRAFRESERVE3 { Text = "" ; }; +String STR_ItemNam_GRAFRESERVE4 { Text = "" ; }; +String STR_ItemNam_GRAFRESERVE5 { Text = "" ; }; +String STR_ItemNam_GRAFRESERVE6 { Text = "" ; }; + +String STR_ItemNam_RESERVE19 { Text = "" ; }; +String STR_ItemNamSET_MISC +{ + Text [ en-US ] = "Various attributes" ; +}; +String STR_ItemNam_OBJMOVEPROTECT +{ + Text [ en-US ] = "Position protected" ; +}; +String STR_ItemNam_OBJSIZEPROTECT +{ + Text [ en-US ] = "Size Protection" ; +}; +String STR_ItemNam_OBJPRINTABLE +{ + Text [ en-US ] = "Don't print" ; +}; +String STR_ItemNam_LAYERID +{ + Text [ en-US ] = "Layer Indicator" ; +}; +String STR_ItemNam_LAYERNAME +{ + Text [ en-US ] = "Le~vel" ; +}; +String STR_ItemNam_OBJECTNAME +{ + Text [ en-US ] = "Object name" ; +}; +String STR_ItemNam_STARTANGLE +{ + Text [ en-US ] = "Start angle" ; +}; +String STR_ItemNam_ENDANGLE +{ + Text [ en-US ] = "Final angle" ; +}; +String STR_ItemNam_POSITIONX +{ + Text [ en-US ] = "X Position" ; +}; +String STR_ItemNam_POSITIONY +{ + Text [ en-US ] = "Y Position" ; +}; +String STR_ItemNam_SIZEWIDTH +{ + Text [ en-US ] = "Width" ; +}; +String STR_ItemNam_SIZEHEIGHT +{ + Text [ en-US ] = "Height" ; +}; +String STR_ItemNam_ROTATEANGLE +{ + Text [ en-US ] = "Rotation angle" ; +}; +String STR_ItemNam_SHEARANGLE +{ + Text [ en-US ] = "Shear angle" ; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + // Ende der gecachten Strings + + // und hier noch Bitmaps +Bitmap BMAP_GrafikEi { File = "grafikei.bmp" ; }; +Bitmap BMAP_GrafikDe { File = "grafikde.bmp" ; }; + +// Strings fuer den Vorlagen-Dialog +String SIP_UNKNOWN_ATTR +{ + Text [ en-US ] = "Unknown attribute"; +}; + +// Strings fuer den Vorlagen-Dialog +String SIP_XA_LINESTYLE +{ + Text [ en-US ] = "Line style"; +}; + +String SIP_XA_LINEDASH +{ + Text [ en-US ] = "Line pattern"; +}; + +String SIP_XA_LINEWIDTH +{ + Text [ en-US ] = "Line width"; +}; + +String SIP_XA_LINECOLOR +{ + Text [ en-US ] = "Line color"; +}; + +String SIP_XA_LINESTART +{ + Text [ en-US ] = "Line head"; +}; + +String SIP_XA_LINEEND +{ + Text [ en-US ] = "Line end"; +}; + +String SIP_XA_LINESTARTWIDTH +{ + Text [ en-US ] = "Line head width"; +}; + +String SIP_XA_LINEENDWIDTH +{ + Text [ en-US ] = "Line end width"; +}; + +String SIP_XA_LINESTARTCENTER +{ + Text [ en-US ] = "Center arrowhead"; +}; + +String SIP_XA_LINEENDCENTER +{ + Text [ en-US ] = "Center arrowend"; +}; + +String SIP_XA_LINETRANSPARENCE +{ + Text [ en-US ] = "Line transparency"; +}; + +String SIP_XA_LINEJOINT +{ + Text [ en-US ] = "Line joint"; +}; + +String SIP_XA_LINERESERVED2 +{ + Text [ en-US ] = "Line reserved for 2"; +}; + +String SIP_XA_LINERESERVED3 +{ + Text [ en-US ] = "Line reserved for 3"; +}; + +String SIP_XA_LINERESERVED4 +{ + Text [ en-US ] = "Line reserved for 4"; +}; + +String SIP_XA_LINERESERVED5 +{ + Text [ en-US ] = "Line reserved for 5"; +}; + +String SIP_XA_LINERESERVED_LAST +{ + Text [ en-US ] = "Line reserved for 6"; +}; + +String SIP_XATTRSET_LINE +{ + Text [ en-US ] = "Line attributes"; +}; + +String SIP_XA_FILLSTYLE +{ + Text [ en-US ] = "Fill style"; +}; + +String SIP_XA_FILLCOLOR +{ + Text [ en-US ] = "Fillcolor"; +}; + +String SIP_XA_FILLGRADIENT +{ + Text [ en-US ] = "Gradient"; +}; + +String SIP_XA_FILLHATCH +{ + Text [ en-US ] = "Hatching"; +}; + +String SIP_XA_FILLBITMAP +{ + Text [ en-US ] = "Fillbitmap"; +}; + +String SIP_XA_FILLTRANSPARENCE +{ + Text [ en-US ] = "Transparency"; +}; + +String SIP_XA_GRADIENTSTEPCOUNT +{ + Text [ en-US ] = "Number of gradient steps"; +}; + +String SIP_XA_FILLBMP_TILE +{ + Text [ en-US ] = "Tile fill"; +}; + +String SIP_XA_FILLBMP_POS +{ + Text [ en-US ] = "Fillbitmap position"; +}; + +String SIP_XA_FILLBMP_SIZEX +{ + Text [ en-US ] = "Fillbitmap width"; +}; + +String SIP_XA_FILLBMP_SIZEY +{ + Text [ en-US ] = "Height of fillbitmap"; +}; + +String SIP_XA_FILLFLOATTRANSPARENCE +{ + Text [ en-US ] = "Transparent gradient"; +}; + +String SIP_XA_SECONDARYFILLCOLOR +{ + Text [ en-US ] = "Fill reserved for 2"; +}; + +String SIP_XA_FILLBMP_SIZELOG +{ + Text [ en-US ] = "Tile size not in %"; +}; + +String SIP_XA_FILLBMP_TILEOFFSETX +{ + Text [ en-US ] = "Tile offset X in %"; +}; + +String SIP_XA_FILLBMP_TILEOFFSETY +{ + Text [ en-US ] = "Tile offset Y in %"; +}; + +String SIP_XA_FILLBMP_STRETCH +{ + Text [ en-US ] = "Bitmap scaling"; +}; + +String SIP_XA_FILLRESERVED3 +{ + Text [ en-US ] = "Bitmap reserved for 3"; +}; + +String SIP_XA_FILLRESERVED4 +{ + Text [ en-US ] = "Bitmap reserved for 4"; +}; + +String SIP_XA_FILLRESERVED5 +{ + Text [ en-US ] = "Bitmap reserved for 5"; +}; + +String SIP_XA_FILLRESERVED6 +{ + Text [ en-US ] = "Bitmap reserved for 6"; +}; + +String SIP_XA_FILLRESERVED7 +{ + Text [ en-US ] = "Bitmap reserved for 7"; +}; + +String SIP_XA_FILLRESERVED8 +{ + Text [ en-US ] = "Bitmap reserved for 8"; +}; + +String SIP_XA_FILLBMP_POSOFFSETX +{ + Text [ en-US ] = "Tile position X in %"; +}; + +String SIP_XA_FILLBMP_POSOFFSETY +{ + Text [ en-US ] = "Tile position Y in %"; +}; + +String SIP_XA_FILLBACKGROUND +{ + Text [ en-US ] = "Background fill"; +}; + +String SIP_XA_FILLRESERVED10 +{ + Text [ en-US ] = "Fill reserved for 10"; +}; + +String SIP_XA_FILLRESERVED11 +{ + Text [ en-US ] = "Fill reserved for 11"; +}; + +String SIP_XA_FILLRESERVED_LAST +{ + Text [ en-US ] = "Fill reserved for 12"; +}; + +String SIP_XATTRSET_FILL +{ + Text [ en-US ] = "Area attributes"; +}; + +String SIP_XA_FORMTXTSTYLE +{ + Text [ en-US ] = "Fontwork style"; +}; + +String SIP_XA_FORMTXTADJUST +{ + Text [ en-US ] = "Fontwork alignment"; +}; + +String SIP_XA_FORMTXTDISTANCE +{ + Text [ en-US ] = "Fontwork spacing"; +}; + +String SIP_XA_FORMTXTSTART +{ + Text [ en-US ] = "Fontwork font begin"; +}; + +String SIP_XA_FORMTXTMIRROR +{ + Text [ en-US ] = "Fontwork mirror"; +}; + +String SIP_XA_FORMTXTOUTLINE +{ + Text [ en-US ] = "Fontwork outline"; +}; + +String SIP_XA_FORMTXTSHADOW +{ + Text [ en-US ] = "Fontwork shadow"; +}; + +String SIP_XA_FORMTXTSHDWCOLOR +{ + Text [ en-US ] = "Fontwork shadow color"; +}; + +String SIP_XA_FORMTXTSHDWXVAL +{ + Text [ en-US ] = "Fontwork shadow offset X"; +}; + +String SIP_XA_FORMTXTSHDWYVAL +{ + Text [ en-US ] = "Fontwork shadow offset Y"; +}; + +String SIP_XA_FORMTXTSTDFORM +{ + Text [ en-US ] = "Fontwork default form"; +}; + +String SIP_XA_FORMTXTHIDEFORM +{ + Text [ en-US ] = "Hide fontwork outline"; +}; + +String SIP_XA_FORMTXTSHDWTRANSP +{ + Text [ en-US ] = "Fontwork shadow transparency"; +}; + +String SIP_XA_FTRESERVED2 +{ + Text [ en-US ] = "Fontwork reserved for 2"; +}; + +String SIP_XA_FTRESERVED3 +{ + Text [ en-US ] = "Fontwork reserved for 3"; +}; + +String SIP_XA_FTRESERVED4 +{ + Text [ en-US ] = "Fontwork reserved for 4"; +}; + +String SIP_XA_FTRESERVED5 +{ + Text [ en-US ] = "Fontwork reserved for 5"; +}; + +String SIP_XA_FTRESERVED_LAST +{ + Text [ en-US ] = "Fontwork reserved for 6"; +}; + +String SIP_SA_SHADOW +{ + Text [ en-US ] = "Shadow"; +}; + +String SIP_SA_SHADOWCOLOR +{ + Text [ en-US ] = "Shadow color"; +}; + +String SIP_SA_SHADOWXDIST +{ + Text [ en-US ] = "Shadow spacing X"; +}; + +String SIP_SA_SHADOWYDIST +{ + Text [ en-US ] = "Shadow spacing Y"; +}; + +String SIP_SA_SHADOWTRANSPARENCE +{ + Text [ en-US ] = "Shadow transparency"; +}; + +String SIP_SA_SHADOW3D +{ + Text [ en-US ] = "3D shadow"; +}; + +String SIP_SA_SHADOWPERSP +{ + Text [ en-US ] = "Perspective shadow"; +}; + +String SIP_SA_CAPTIONTYPE +{ + Text [ en-US ] = "Type of legend"; +}; + +String SIP_SA_CAPTIONFIXEDANGLE +{ + Text [ en-US ] = "Fixed legend angle"; +}; + +String SIP_SA_CAPTIONANGLE +{ + Text [ en-US ] = "Legend angle"; +}; + +String SIP_SA_CAPTIONGAP +{ + Text [ en-US ] = "Legend lines spacing"; +}; + +String SIP_SA_CAPTIONESCDIR +{ + Text [ en-US ] = "Legend exit alignment"; +}; + +String SIP_SA_CAPTIONESCISREL +{ + Text [ en-US ] = "Relative exit legend"; +}; + +String SIP_SA_CAPTIONESCREL +{ + Text [ en-US ] = "Relative exit legend"; +}; + +String SIP_SA_CAPTIONESCABS +{ + Text [ en-US ] = "Absolute exit of legend"; +}; + +String SIP_SA_CAPTIONLINELEN +{ + Text [ en-US ] = "Legend line length"; +}; + +String SIP_SA_CAPTIONFITLINELEN +{ + Text [ en-US ] = "AutoLength of legend lines"; +}; + +String SIP_SA_ECKENRADIUS +{ + Text [ en-US ] = "Corner radius"; +}; + +String SIP_SA_TEXT_MINFRAMEHEIGHT +{ + Text [ en-US ] = "Minimal frame height"; +}; + +String SIP_SA_TEXT_AUTOGROWHEIGHT +{ + Text [ en-US ] = "AutoFit height"; +}; + +String SIP_SA_TEXT_FITTOSIZE +{ + Text [ en-US ] = "Fit text to frame"; +}; + +String SIP_SA_TEXT_LEFTDIST +{ + Text [ en-US ] = "Left text frame spacing"; +}; + +String SIP_SA_TEXT_RIGHTDIST +{ + Text [ en-US ] = "Right text frame spacing"; +}; + +String SIP_SA_TEXT_UPPERDIST +{ + Text [ en-US ] = "Upper text frame spacing"; +}; + +String SIP_SA_TEXT_LOWERDIST +{ + Text [ en-US ] = "Lower text frame spacing"; +}; + +String SIP_SA_TEXT_VERTADJUST +{ + Text [ en-US ] = "Vertical text anchor"; +}; + +String SIP_SA_TEXT_MAXFRAMEHEIGHT +{ + Text [ en-US ] = "Maximal frame height"; +}; + +String SIP_SA_TEXT_MINFRAMEWIDTH +{ + Text [ en-US ] = "Minimal frame width"; +}; + +String SIP_SA_TEXT_MAXFRAMEWIDTH +{ + Text [ en-US ] = "Maximal frame width"; +}; + +String SIP_SA_TEXT_AUTOGROWWIDTH +{ + Text [ en-US ] = "AutoFit width"; +}; + +String SIP_SA_TEXT_HORZADJUST +{ + Text [ en-US ] = "Horizontal text anchor"; +}; + +String SIP_SA_TEXT_ANIKIND +{ + Text [ en-US ] = "Ticker"; +}; + +String SIP_SA_TEXT_ANIDIRECTION +{ + Text [ en-US ] = "Ticker direction"; +}; + +String SIP_SA_TEXT_ANISTARTINSIDE +{ + Text [ en-US ] = "Ticker start inside"; +}; + +String SIP_SA_TEXT_ANISTOPINSIDE +{ + Text [ en-US ] = "Ticker stop inside"; +}; + +String SIP_SA_TEXT_ANICOUNT +{ + Text [ en-US ] = "Number of ticker runs"; +}; + +String SIP_SA_TEXT_ANIDELAY +{ + Text [ en-US ] = "Speed of ticker"; +}; + +String SIP_SA_TEXT_ANIAMOUNT +{ + Text [ en-US ] = "Ticker step size"; +}; + +String SIP_SA_TEXT_CONTOURFRAME +{ + Text [ en-US ] = "Outline text flow"; +}; + +String SIP_SA_CUSTOMSHAPE_ADJUSTMENT +{ + Text[ en-US ] = "Shape Adjustment"; +}; + +String SIP_SA_XMLATTRIBUTES +{ + Text [ en-US ] = "User-defined attributes"; +}; + +String SIP_SA_TEXT_USEFIXEDCELLHEIGHT +{ + Text [ en-US ] = "Use font-independent line spacing"; +}; + +String SIP_SA_WORDWRAP +{ + Text[ en-US ] = "Word wrap text in shape"; +}; + +String SIP_SA_AUTOGROWSIZE +{ + Text[ en-US ] = "Auto grow shape to fit text"; +}; + +String SIP_SA_RESERVE18 +{ + Text [ en-US ] = "SvDraw reserved for 18"; +}; + +String SIP_SA_RESERVE19 +{ + Text [ en-US ] = "SvDraw reserved for 19"; +}; + +String SIP_SA_EDGEKIND +{ + Text [ en-US ] = "Type of connector"; +}; + +String SIP_SA_EDGENODE1HORZDIST +{ + Text [ en-US ] = "Horz. spacing object 1"; +}; + +String SIP_SA_EDGENODE1VERTDIST +{ + Text [ en-US ] = "Vert. spacing object 1"; +}; + +String SIP_SA_EDGENODE2HORZDIST +{ + Text [ en-US ] = "Horz. spacing object 2"; +}; + +String SIP_SA_EDGENODE2VERTDIST +{ + Text [ en-US ] = "Vert. spacing object 2"; +}; + +String SIP_SA_EDGENODE1GLUEDIST +{ + Text [ en-US ] = "Glue spacing object 1"; +}; + +String SIP_SA_EDGENODE2GLUEDIST +{ + Text [ en-US ] = "Glue spacing object 2"; +}; + +String SIP_SA_EDGELINEDELTAANZ +{ + Text [ en-US ] = "Number of movable lines"; +}; + +String SIP_SA_EDGELINE1DELTA +{ + Text [ en-US ] = "Offset line 1"; +}; + +String SIP_SA_EDGELINE2DELTA +{ + Text [ en-US ] = "Offset line 2"; +}; + +String SIP_SA_EDGELINE3DELTA +{ + Text [ en-US ] = "Offset line 3"; +}; + +String SIP_SA_MEASUREKIND +{ + Text [ en-US ] = "Type of dimensioning"; +}; + +String SIP_SA_MEASURETEXTHPOS +{ + Text [ en-US ] = "Dimension value - horizontal position"; +}; + +String SIP_SA_MEASURETEXTVPOS +{ + Text [ en-US ] = "Dimension value - vertical position"; +}; + +String SIP_SA_MEASURELINEDIST +{ + Text [ en-US ] = "Dimension line space"; +}; + +String SIP_SA_MEASUREHELPLINEOVERHANG +{ + Text [ en-US ] = "Dimension help line overhang"; +}; + +String SIP_SA_MEASUREHELPLINEDIST +{ + Text [ en-US ] = "Dimension help line spacing"; +}; + +String SIP_SA_MEASUREHELPLINE1LEN +{ + Text [ en-US ] = "Backlog of dimension help line 1"; +}; + +String SIP_SA_MEASUREHELPLINE2LEN +{ + Text [ en-US ] = "Backlog of dimension help line 2"; +}; + +String SIP_SA_MEASUREBELOWREFEDGE +{ + Text [ en-US ] = "Lower edge dimensioning"; +}; + +String SIP_SA_MEASURETEXTROTA90 +{ + Text [ en-US ] = "Dimension value across dimension line"; +}; + +String SIP_SA_MEASURETEXTUPSIDEDOWN +{ + Text [ en-US ] = "Rotate dimension value by 180 degree"; +}; + +String SIP_SA_MEASUREOVERHANG +{ + Text [ en-US ] = "Dimension line overhang"; +}; + +String SIP_SA_MEASUREUNIT +{ + Text [ en-US ] = "Measure unit"; +}; + +String SIP_SA_MEASURESCALE +{ + Text [ en-US ] = "Additional scale factor"; +}; + +String SIP_SA_MEASURESHOWUNIT +{ + Text [ en-US ] = "Measure unit display"; +}; + +String SIP_SA_MEASUREFORMATSTRING +{ + Text [ en-US ] = "Dimension value format"; +}; + +String SIP_SA_MEASURETEXTAUTOANGLE +{ + Text [ en-US ] = "AutoPositioning of the dimension value"; +}; + +String SIP_SA_MEASURETEXTAUTOANGLEVIEW +{ + Text [ en-US ] = "Angle for the automatic positioning of the dimension value"; +}; + +String SIP_SA_MEASURETEXTISFIXEDANGLE +{ + Text [ en-US ] = "Determination of the dimension value angle"; +}; + +String SIP_SA_MEASURETEXTFIXEDANGLE +{ + Text [ en-US ] = "Angle of the dimension value"; +}; + +String SIP_SA_MEASUREDECIMALPLACES +{ + Text [ en-US ] = "Decimal places"; +}; + +String SIP_SA_MEASURERESERVE05 +{ + Text [ en-US ] = "Dimensioning reserved 5"; +}; + +String SIP_SA_MEASURERESERVE06 +{ + Text [ en-US ] = "Dimensioning reserved for 6"; +}; + +String SIP_SA_MEASURERESERVE07 +{ + Text [ en-US ] = "Dimensioning reserved for 7"; +}; + +String SIP_SA_CIRCKIND +{ + Text [ en-US ] = "Type of circle"; +}; + +String SIP_SA_CIRCSTARTANGLE +{ + Text [ en-US ] = "Start angle"; +}; + +String SIP_SA_CIRCENDANGLE +{ + Text [ en-US ] = "End angle"; +}; + +String SIP_SA_CIRCRESERVE0 +{ + Text [ en-US ] = "Circle reserved for 0"; +}; + +String SIP_SA_CIRCRESERVE1 +{ + Text [ en-US ] = "Circle reserved for 1"; +}; + +String SIP_SA_CIRCRESERVE2 +{ + Text [ en-US ] = "Circle reserved for 2"; +}; + +String SIP_SA_CIRCRESERVE3 +{ + Text [ en-US ] = "Circle reserved for 3"; +}; + +String SIP_SA_OBJMOVEPROTECT +{ + Text [ en-US ] = "Protected object position"; +}; + +String SIP_SA_OBJSIZEPROTECT +{ + Text [ en-US ] = "Protected object size"; +}; + +String SIP_SA_OBJPRINTABLE +{ + Text [ en-US ] = "Object, printable"; +}; + +String SIP_SA_OBJVISIBLE +{ + Text [ en-US ] = "Object, visible"; +}; + +String SIP_SA_LAYERID +{ + Text [ en-US ] = "Level ID"; +}; + +String SIP_SA_LAYERNAME +{ + Text [ en-US ] = "Layer"; +}; + +String SIP_SA_OBJECTNAME +{ + Text [ en-US ] = "Object name"; +}; + +String SIP_SA_ALLPOSITIONX +{ + Text [ en-US ] = "Position X, complete"; +}; + +String SIP_SA_ALLPOSITIONY +{ + Text [ en-US ] = "Position Y, complete"; +}; + +String SIP_SA_ALLSIZEWIDTH +{ + Text [ en-US ] = "Total Width"; +}; + +String SIP_SA_ALLSIZEHEIGHT +{ + Text [ en-US ] = "Height, complete"; +}; + +String SIP_SA_ONEPOSITIONX +{ + Text [ en-US ] = "Single position X"; +}; + +String SIP_SA_ONEPOSITIONY +{ + Text [ en-US ] = "Single position Y"; +}; + +String SIP_SA_ONESIZEWIDTH +{ + Text [ en-US ] = "Single width"; +}; + +String SIP_SA_ONESIZEHEIGHT +{ + Text [ en-US ] = "Single height"; +}; + +String SIP_SA_LOGICSIZEWIDTH +{ + Text [ en-US ] = "Logical width"; +}; + +String SIP_SA_LOGICSIZEHEIGHT +{ + Text [ en-US ] = "Logical height"; +}; + +String SIP_SA_ROTATEANGLE +{ + Text [ en-US ] = "Single rotation angle"; +}; + +String SIP_SA_SHEARANGLE +{ + Text [ en-US ] = "Single shear angle"; +}; + +String SIP_SA_MOVEX +{ + Text [ en-US ] = "Move horizontally"; +}; + +String SIP_SA_MOVEY +{ + Text [ en-US ] = "Move vertically"; +}; + +String SIP_SA_RESIZEXONE +{ + Text [ en-US ] = "Resize X, single"; +}; + +String SIP_SA_RESIZEYONE +{ + Text [ en-US ] = "Resize Y, single"; +}; + +String SIP_SA_ROTATEONE +{ + Text [ en-US ] = "Single rotation"; +}; + +String SIP_SA_HORZSHEARONE +{ + Text [ en-US ] = "Single horizontal shear"; +}; + +String SIP_SA_VERTSHEARONE +{ + Text [ en-US ] = "Single vertical shear"; +}; + +String SIP_SA_RESIZEXALL +{ + Text [ en-US ] = "Resize X, complete"; +}; + +String SIP_SA_RESIZEYALL +{ + Text [ en-US ] = "Resize Y, complete"; +}; + +String SIP_SA_ROTATEALL +{ + Text [ en-US ] = "Rotate all"; +}; + +String SIP_SA_HORZSHEARALL +{ + Text [ en-US ] = "Shear horizontal, complete"; +}; + +String SIP_SA_VERTSHEARALL +{ + Text [ en-US ] = "Shear vertical, complete"; +}; + +String SIP_SA_TRANSFORMREF1X +{ + Text [ en-US ] = "Reference point 1 X"; +}; + +String SIP_SA_TRANSFORMREF1Y +{ + Text [ en-US ] = "Reference point 1 Y"; +}; + +String SIP_SA_TRANSFORMREF2X +{ + Text [ en-US ] = "Reference point 2 X"; +}; + +String SIP_SA_TRANSFORMREF2Y +{ + Text [ en-US ] = "Reference point 2 Y"; +}; + +String SIP_EE_PARA_HYPHENATE +{ + Text [ en-US ] = "Hyphenation"; +}; + +String SIP_EE_PARA_BULLETSTATE +{ + Text [ en-US ] = "Display bullets"; +}; + +String SIP_EE_PARA_OUTLLRSPACE +{ + Text [ en-US ] = "Numbering indents"; +}; + +String SIP_EE_PARA_OUTLLEVEL +{ + Text [ en-US ] = "Numbering level"; +}; + +String SIP_EE_PARA_BULLET +{ + Text [ en-US ] = "Bullets and Numberings"; +}; + +String SIP_EE_PARA_LRSPACE +{ + Text [ en-US ] = "Indents"; +}; + +String SIP_EE_PARA_ULSPACE +{ + Text [ en-US ] = "Paragraph spacing"; +}; + +String SIP_EE_PARA_SBL +{ + Text [ en-US ] = "Line spacing"; +}; + +String SIP_EE_PARA_JUST +{ + Text [ en-US ] = "Paragraph alignment"; +}; + +String SIP_EE_PARA_TABS +{ + Text [ en-US ] = "Tabulators"; +}; + +String SIP_EE_CHAR_COLOR +{ + Text [ en-US ] = "Font color"; +}; + +String SIP_EE_CHAR_FONTINFO +{ + Text [ en-US ] = "Character set"; +}; + +String SIP_EE_CHAR_FONTHEIGHT +{ + Text [ en-US ] = "Font size"; +}; + +String SIP_EE_CHAR_FONTWIDTH +{ + Text [ en-US ] = "Font width"; +}; + +String SIP_EE_CHAR_WEIGHT +{ + Text [ en-US ] = "Bold (thickness)"; +}; + +String SIP_EE_CHAR_UNDERLINE +{ + Text [ en-US ] = "Underline"; +}; + +String SIP_EE_CHAR_OVERLINE +{ + Text [ en-US ] = "Overline"; +}; + +String SIP_EE_CHAR_STRIKEOUT +{ + Text [ en-US ] = "Strikethrough"; +}; + +String SIP_EE_CHAR_ITALIC +{ + Text [ en-US ] = "Italic"; +}; + +String SIP_EE_CHAR_OUTLINE +{ + Text [ en-US ] = "Outline"; +}; + +String SIP_EE_CHAR_SHADOW +{ + Text [ en-US ] = "Font shadow"; +}; + +String SIP_EE_CHAR_ESCAPEMENT +{ + Text [ en-US ] = "Superscript/subscript"; +}; + +String SIP_EE_CHAR_PAIRKERNING +{ + Text [ en-US ] = "Kerning"; +}; + +String SIP_EE_CHAR_KERNING +{ + Text [ en-US ] = "Manual kerning"; +}; + +String SIP_EE_CHAR_WLM +{ + Text [ en-US ] = "No underline for spaces"; +}; + +String SIP_EE_FEATURE_TAB +{ + Text [ en-US ] = "Tabulator"; +}; + +String SIP_EE_FEATURE_LINEBR +{ + Text [ en-US ] = "Optional line break"; +}; + +String SIP_EE_FEATURE_NOTCONV +{ + Text [ en-US ] = "Non-convertible character"; +}; + +String SIP_EE_FEATURE_FIELD +{ + Text [ en-US ] = "Fields"; +}; + +String SIP_SA_GRAFRED +{ + Text [ en-US ] = "Red"; +}; +String SIP_SA_GRAFGREEN +{ + Text [ en-US ] = "Green"; +}; +String SIP_SA_GRAFBLUE +{ + Text [ en-US ] = "Blue"; +}; +String SIP_SA_GRAFLUMINANCE +{ + Text [ en-US ] = "Brightness"; +}; +String SIP_SA_GRAFCONTRAST +{ + Text [ en-US ] = "Contrast"; +}; +String SIP_SA_GRAFGAMMA +{ + Text [ en-US ] = "Gamma"; +}; +String SIP_SA_GRAFTRANSPARENCE +{ + Text [ en-US ] = "Transparency"; +}; +String SIP_SA_GRAFINVERT +{ + Text [ en-US ] = "Invert"; +}; +String SIP_SA_GRAFMODE +{ + Text [ en-US ] = "Graphics mode"; +}; +String SIP_SA_GRAFCROP +{ + Text [ en-US ] = "Crop"; + +}; +String SIP_SA_GRAFRESERVE3 { Text = "" ; }; +String SIP_SA_GRAFRESERVE4 { Text = "" ; }; +String SIP_SA_GRAFRESERVE5 { Text = "" ; }; +String SIP_SA_GRAFRESERVE6 { Text = "" ; }; + +Bitmap SIP_SA_MARKERS +{ + File = "markers.bmp"; +}; + +Bitmap SIP_SA_FINE_MARKERS +{ + File = "markers2.bmp"; +}; + +// #100499# +Bitmap BMP_SVXOLEOBJ +{ + File = "oleobj.bmp" ; +}; + +// #101928# +Bitmap SIP_SA_ACCESSIBILITY_MARKERS +{ + File = "markersACC.bmp"; +}; + +String STR_ObjNameSingulMEDIA +{ + Text [ en-US ] = "Media object" ; +}; +String STR_ObjNamePluralMEDIA +{ + Text [ en-US ] = "Media objects" ; +}; + +// drawing layer table strings + +String STR_TABLE_ATTR +{ + Text [ en-US ] = "Apply table attributes" ; +}; +String STR_TABLE_AUTOFMT +{ + Text [ en-US ] = "AutoFormat table" ; +}; +String STR_TABLE_INSCOL +{ + Text [ en-US ] = "Insert column" ; +}; +String STR_TABLE_INSROW +{ + Text [ en-US ] = "Insert row" ; +}; +String STR_UNDO_COL_DELETE +{ + Text [ en-US ] = "Delete column" ; +}; +String STR_UNDO_ROW_DELETE +{ + Text [ en-US ] = "Delete row" ; +}; +String STR_TABLE_SPLIT +{ + Text [ en-US ] = "Split cells" ; +}; +String STR_TABLE_MERGE +{ + Text [ en-US ] = "Merge cells" ; +}; +String STR_TABLE_NUMFORMAT +{ + Text [ en-US ] = "Format cell" ; +}; + +String STR_TABLE_DISTRIBUTE_ROWS +{ + Text [ en-US ] = "Distribute rows" ; +}; + +String STR_TABLE_DISTRIBUTE_COLUMNS +{ + Text [ en-US ] = "Distribute columns" ; +}; + +String STR_TABLE_STYLE +{ + Text [ en-US ] = "Table style" ; +}; + +String STR_TABLE_STYLE_SETTINGS +{ + Text [ en-US ] = "Table style settings" ; +}; + +String STR_ObjNameSingulTable +{ + Text [ en-US ] = "Table"; +}; +String STR_ObjNamePluralTable +{ + Text [ en-US ] = "Tables"; +}; + +Bitmap SIP_SA_CROP_MARKERS +{ + File = "cropmarkers.bmp"; +}; + +Bitmap SIP_SA_CROP_FINE_MARKERS +{ + File = "cropmarkers2.bmp"; +}; + +Bitmap SIP_SA_ACCESSIBILITY_CROP_MARKERS +{ + File = "cropmarkersACC.bmp"; +}; + +// ******************************************************************* EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svx/source/svdraw/svdtext.cxx b/svx/source/svdraw/svdtext.cxx new file mode 100644 index 000000000000..29018b6084ea --- /dev/null +++ b/svx/source/svdraw/svdtext.cxx @@ -0,0 +1,224 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#define ITEMID_FONTHEIGHT EE_CHAR_FONTHEIGHT + +#include "svx/svdotext.hxx" +#include "svx/svdetc.hxx" +#include "editeng/outlobj.hxx" +#include "svx/svdoutl.hxx" +#include "svx/svdmodel.hxx" +#include "editeng/fhgtitem.hxx" +#include <editeng/eeitem.hxx> +#include <svl/itemset.hxx> + +SdrText::SdrText( SdrTextObj& rObject, OutlinerParaObject* pOutlinerParaObject /* = 0 */ ) +: mpOutlinerParaObject( pOutlinerParaObject ) +, mrObject( rObject ) +, mpModel( rObject.GetModel() ) +, mbPortionInfoChecked( false ) +{ + OSL_ENSURE(&mrObject, "SdrText created without SdrTextObj (!)"); +} + +SdrText::~SdrText() +{ + clearWeak(); + delete mpOutlinerParaObject; +} + +void SdrText::CheckPortionInfo( SdrOutliner& rOutliner ) +{ + if(!mbPortionInfoChecked) + { + // #i102062# no action when the Outliner is the HitTestOutliner, + // this will remove WrongList info at the OPO + if(mpModel && &rOutliner == &mpModel->GetHitTestOutliner()) + return; + + // Optimierung: ggf. BigTextObject erzeugen + mbPortionInfoChecked=true; + if(mpOutlinerParaObject!=NULL && rOutliner.ShouldCreateBigTextObject()) + { + // #i102062# MemoryLeak closed + delete mpOutlinerParaObject; + mpOutlinerParaObject = rOutliner.CreateParaObject(); + } + } +} + +void SdrText::ReformatText() +{ + mbPortionInfoChecked=FALSE; + mpOutlinerParaObject->ClearPortionInfo(); +} + +const SfxItemSet& SdrText::GetItemSet() const +{ + return const_cast< SdrText* >(this)->GetObjectItemSet(); +} + +void SdrText::SetOutlinerParaObject( OutlinerParaObject* pTextObject ) +{ + if( mpOutlinerParaObject != pTextObject ) + { + if( mpModel ) + { + // Update HitTestOutliner + const SdrTextObj* pTestObj = mpModel->GetHitTestOutliner().GetTextObj(); + if( pTestObj && pTestObj->GetOutlinerParaObject() == mpOutlinerParaObject ) + mpModel->GetHitTestOutliner().SetTextObj( 0 ); + } + + if( mpOutlinerParaObject ) + delete mpOutlinerParaObject; + + mpOutlinerParaObject = pTextObject; + + mbPortionInfoChecked = false; + } +} + +OutlinerParaObject* SdrText::GetOutlinerParaObject() const +{ + return mpOutlinerParaObject; +} + +/** returns the current OutlinerParaObject and removes it from this instance */ +OutlinerParaObject* SdrText::RemoveOutlinerParaObject() +{ + if( mpModel ) + { + // Update HitTestOutliner + const SdrTextObj* pTestObj = mpModel->GetHitTestOutliner().GetTextObj(); + if( pTestObj && pTestObj->GetOutlinerParaObject() == mpOutlinerParaObject ) + mpModel->GetHitTestOutliner().SetTextObj( 0 ); + } + + OutlinerParaObject* pOPO = mpOutlinerParaObject; + + mpOutlinerParaObject = 0; + mbPortionInfoChecked = false; + + return pOPO; +} + +void SdrText::SetModel( SdrModel* pNewModel ) +{ + if( pNewModel == mpModel ) + return; + + SdrModel* pOldModel = mpModel; + mpModel = pNewModel; + + if( mpOutlinerParaObject && pOldModel!=NULL && pNewModel!=NULL) + { + bool bHgtSet = GetObjectItemSet().GetItemState(EE_CHAR_FONTHEIGHT, TRUE) == SFX_ITEM_SET; + + MapUnit aOldUnit(pOldModel->GetScaleUnit()); + MapUnit aNewUnit(pNewModel->GetScaleUnit()); + FASTBOOL bScaleUnitChanged=aNewUnit!=aOldUnit; + // und nun dem OutlinerParaObject einen neuen Pool verpassen + // !!! Hier muss noch DefTab und RefDevice der beiden Models + // !!! verglichen werden und dann ggf. AutoGrow zuschlagen !!! + // !!! fehlende Implementation !!! + ULONG nOldFontHgt=pOldModel->GetDefaultFontHeight(); + ULONG nNewFontHgt=pNewModel->GetDefaultFontHeight(); + BOOL bDefHgtChanged=nNewFontHgt!=nOldFontHgt; + BOOL bSetHgtItem=bDefHgtChanged && !bHgtSet; + if (bSetHgtItem) + { // #32665# + // zunaechst das HeightItem festklopfen, damit + // 1. Es eben bestehen bleibt und + // 2. DoStretchChars vom richtigen Wert ausgeht + SetObjectItem(SvxFontHeightItem(nOldFontHgt, 100, EE_CHAR_FONTHEIGHT)); + } + // erst jetzt den Outliner holen, etc. damit obiges SetAttr auch wirkt + SdrOutliner& rOutliner = mrObject.ImpGetDrawOutliner(); + rOutliner.SetText(*mpOutlinerParaObject); + delete mpOutlinerParaObject; + mpOutlinerParaObject=0; + if (bScaleUnitChanged) + { + Fraction aMetricFactor=GetMapFactor(aOldUnit,aNewUnit).X(); + + // Funktioniert nicht richtig: + // Geht am Outliner leider nur in % + // double nPercFloat=double(aMetricFactor)*100+0.5; + // USHORT nPerc=(USHORT)nPercFloat; + // rOutliner.DoStretchChars(100,nPerc); + + if (bSetHgtItem) + { + // Und nun noch das Rahmenattribut korregieren + nOldFontHgt=BigMulDiv(nOldFontHgt,aMetricFactor.GetNumerator(),aMetricFactor.GetDenominator()); + SetObjectItem(SvxFontHeightItem(nOldFontHgt, 100, EE_CHAR_FONTHEIGHT)); + } + } + SetOutlinerParaObject(rOutliner.CreateParaObject()); // #34494# + mpOutlinerParaObject->ClearPortionInfo(); + mbPortionInfoChecked=FALSE; + rOutliner.Clear(); + } +} + +void SdrText::ForceOutlinerParaObject( USHORT nOutlMode ) +{ + if( mpModel && !mpOutlinerParaObject ) + { + Outliner* pOutliner = SdrMakeOutliner( nOutlMode, mpModel ); + if( pOutliner ) + { + Outliner& aDrawOutliner = mpModel->GetDrawOutliner(); + pOutliner->SetCalcFieldValueHdl( aDrawOutliner.GetCalcFieldValueHdl() ); + + pOutliner->SetStyleSheet( 0, GetStyleSheet()); + OutlinerParaObject* pOutlinerParaObject = pOutliner->CreateParaObject(); + SetOutlinerParaObject( pOutlinerParaObject ); + + delete pOutliner; + } + } +} + +const SfxItemSet& SdrText::GetObjectItemSet() +{ + return mrObject.GetObjectItemSet(); +} + +void SdrText::SetObjectItem(const SfxPoolItem& rItem) +{ + mrObject.SetObjectItem( rItem ); +} + +SfxStyleSheet* SdrText::GetStyleSheet() const +{ + return mrObject.GetStyleSheet(); +} diff --git a/svx/source/svdraw/svdtrans.cxx b/svx/source/svdraw/svdtrans.cxx new file mode 100644 index 000000000000..ad4cf3763241 --- /dev/null +++ b/svx/source/svdraw/svdtrans.cxx @@ -0,0 +1,1271 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdtrans.hxx> +#include <math.h> +#include <svx/xpoly.hxx> + +#include <vcl/virdev.hxx> +#include <tools/bigint.hxx> +#include <tools/debug.hxx> +#include <unotools/syslocale.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void MoveXPoly(XPolygon& rPoly, const Size& S) +{ + rPoly.Move(S.Width(),S.Height()); +} + +void MoveXPoly(XPolyPolygon& rPoly, const Size& S) +{ + rPoly.Move(S.Width(),S.Height()); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ResizeRect(Rectangle& rRect, const Point& rRef, const Fraction& rxFact, const Fraction& ryFact, FASTBOOL bNoJustify) +{ + Fraction xFact(rxFact); + Fraction yFact(ryFact); + //long nHgt=rRect.Bottom()-rRect.Top(); + + { + if (xFact.GetDenominator()==0) { + long nWdt=rRect.Right()-rRect.Left(); + if (xFact.GetNumerator()>=0) { // DivZero abfangen + xFact=Fraction(xFact.GetNumerator(),1); + if (nWdt==0) rRect.Right()++; + } else { + xFact=Fraction(xFact.GetNumerator(),-1); + if (nWdt==0) rRect.Left()--; + } + } + rRect.Left() =rRef.X()+Round(((double)(rRect.Left() -rRef.X())*xFact.GetNumerator())/xFact.GetDenominator()); + rRect.Right() =rRef.X()+Round(((double)(rRect.Right() -rRef.X())*xFact.GetNumerator())/xFact.GetDenominator()); + } + { + if (yFact.GetDenominator()==0) { + long nHgt=rRect.Bottom()-rRect.Top(); + if (yFact.GetNumerator()>=0) { // DivZero abfangen + yFact=Fraction(yFact.GetNumerator(),1); + if (nHgt==0) rRect.Bottom()++; + } else { + yFact=Fraction(yFact.GetNumerator(),-1); + if (nHgt==0) rRect.Top()--; + } + + yFact=Fraction(yFact.GetNumerator(),1); // DivZero abfangen + } + rRect.Top() =rRef.Y()+Round(((double)(rRect.Top() -rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator()); + rRect.Bottom()=rRef.Y()+Round(((double)(rRect.Bottom()-rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator()); + } + if (!bNoJustify) rRect.Justify(); +} + + +void ResizePoly(Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + USHORT nAnz=rPoly.GetSize(); + for (USHORT i=0; i<nAnz; i++) { + ResizePoint(rPoly[i],rRef,xFact,yFact); + } +} + +void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + USHORT nAnz=rPoly.GetPointCount(); + for (USHORT i=0; i<nAnz; i++) { + ResizePoint(rPoly[i],rRef,xFact,yFact); + } +} + +void ResizePoly(PolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + ResizePoly(rPoly[i],rRef,xFact,yFact); + } +} + +void ResizeXPoly(XPolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + ResizeXPoly(rPoly[i],rRef,xFact,yFact); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void RotatePoly(Polygon& rPoly, const Point& rRef, double sn, double cs) +{ + USHORT nAnz=rPoly.GetSize(); + for (USHORT i=0; i<nAnz; i++) { + RotatePoint(rPoly[i],rRef,sn,cs); + } +} + +void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs) +{ + USHORT nAnz=rPoly.GetPointCount(); + for (USHORT i=0; i<nAnz; i++) { + RotatePoint(rPoly[i],rRef,sn,cs); + } +} + +void RotatePoly(PolyPolygon& rPoly, const Point& rRef, double sn, double cs) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + RotatePoly(rPoly[i],rRef,sn,cs); + } +} + +void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + RotateXPoly(rPoly[i],rRef,sn,cs); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void MirrorRect(Rectangle& rRect, const Point& /*rRef1*/, const Point& /*rRef2*/, FASTBOOL bNoJustify) +{ + // !!! fehlende Implementation !!! + if (!bNoJustify) rRect.Justify(); +} + +void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2) +{ + long mx=rRef2.X()-rRef1.X(); + long my=rRef2.Y()-rRef1.Y(); + if (mx==0) { // Achse senkrecht + long dx=rRef1.X()-rPnt.X(); + rPnt.X()+=2*dx; + } else if (my==0) { // Achse waagerecht + long dy=rRef1.Y()-rPnt.Y(); + rPnt.Y()+=2*dy; + } else if (mx==my) { // Achse diagonal '\' + long dx1=rPnt.X()-rRef1.X(); + long dy1=rPnt.Y()-rRef1.Y(); + rPnt.X()=rRef1.X()+dy1; + rPnt.Y()=rRef1.Y()+dx1; + } else if (mx==-my) { // Achse diagonal '/' + long dx1=rPnt.X()-rRef1.X(); + long dy1=rPnt.Y()-rRef1.Y(); + rPnt.X()=rRef1.X()-dy1; + rPnt.Y()=rRef1.Y()-dx1; + } else { // beliebige Achse + // mal optimieren !!! + // Lot auf der Spiegelachse faellen oder so + long nRefWink=GetAngle(rRef2-rRef1); + rPnt-=rRef1; + long nPntWink=GetAngle(rPnt); + long nWink=2*(nRefWink-nPntWink); + double a=nWink*nPi180; + double nSin=sin(a); + double nCos=cos(a); + RotatePoint(rPnt,Point(),nSin,nCos); + rPnt+=rRef1; + } +} + +void MirrorPoly(Polygon& rPoly, const Point& rRef1, const Point& rRef2) +{ + USHORT nAnz=rPoly.GetSize(); + for (USHORT i=0; i<nAnz; i++) { + MirrorPoint(rPoly[i],rRef1,rRef2); + } +} + +void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2) +{ + USHORT nAnz=rPoly.GetPointCount(); + for (USHORT i=0; i<nAnz; i++) { + MirrorPoint(rPoly[i],rRef1,rRef2); + } +} + +void MirrorPoly(PolyPolygon& rPoly, const Point& rRef1, const Point& rRef2) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + MirrorPoly(rPoly[i],rRef1,rRef2); + } +} + +void MirrorXPoly(XPolyPolygon& rPoly, const Point& rRef1, const Point& rRef2) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + MirrorXPoly(rPoly[i],rRef1,rRef2); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ShearPoly(Polygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear) +{ + USHORT nAnz=rPoly.GetSize(); + for (USHORT i=0; i<nAnz; i++) { + ShearPoint(rPoly[i],rRef,tn,bVShear); + } +} + +void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear) +{ + USHORT nAnz=rPoly.GetPointCount(); + for (USHORT i=0; i<nAnz; i++) { + ShearPoint(rPoly[i],rRef,tn,bVShear); + } +} + +void ShearPoly(PolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + ShearPoly(rPoly[i],rRef,tn,bVShear); + } +} + +void ShearXPoly(XPolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear) +{ + USHORT nAnz=rPoly.Count(); + for (USHORT i=0; i<nAnz; i++) { + ShearXPoly(rPoly[i],rRef,tn,bVShear); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@@@@ @@@@ @@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@ @@ @@ @@ @@ @@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@ @@ @@ @@@@ @@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter, + const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert) +{ + FASTBOOL bC1=pC1!=NULL; + FASTBOOL bC2=pC2!=NULL; + long x0=rPnt.X(); + long y0=rPnt.Y(); + long cx=rCenter.X(); + long cy=rCenter.Y(); + double nWink=GetCrookAngle(rPnt,rCenter,rRad,bVert); + double sn=sin(nWink); + double cs=cos(nWink); + RotatePoint(rPnt,rCenter,sn,cs); + if (bC1) { + if (bVert) { + // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate + pC1->Y()-=y0; + // Resize, entsprechend der Entfernung vom Zentrum + pC1->Y()=Round(((double)pC1->Y()) /rRad.X()*(cx-pC1->X())); + pC1->Y()+=cy; + } else { + // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate + pC1->X()-=x0; + // Resize, entsprechend der Entfernung vom Zentrum + long nPntRad=cy-pC1->Y(); + double nFact=(double)nPntRad/(double)rRad.Y(); + pC1->X()=Round((double)pC1->X()*nFact); + pC1->X()+=cx; + } + RotatePoint(*pC1,rCenter,sn,cs); + } + if (bC2) { + if (bVert) { + // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate + pC2->Y()-=y0; + // Resize, entsprechend der Entfernung vom Zentrum + pC2->Y()=Round(((double)pC2->Y()) /rRad.X()*(rCenter.X()-pC2->X())); + pC2->Y()+=cy; + } else { + // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate + pC2->X()-=x0; + // Resize, entsprechend der Entfernung vom Zentrum + long nPntRad=rCenter.Y()-pC2->Y(); + double nFact=(double)nPntRad/(double)rRad.Y(); + pC2->X()=Round((double)pC2->X()*nFact); + pC2->X()+=cx; + } + RotatePoint(*pC2,rCenter,sn,cs); + } + rSin=sn; + rCos=cs; + return nWink; +} + +double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter, + const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert) +{ + FASTBOOL bC1=pC1!=NULL; + FASTBOOL bC2=pC2!=NULL; + long x0=rPnt.X(); + long y0=rPnt.Y(); + long dx1=0,dy1=0; + long dxC1=0,dyC1=0; + long dxC2=0,dyC2=0; + if (bVert) { + long nStart=rCenter.X()-rRad.X(); + dx1=rPnt.X()-nStart; + rPnt.X()=nStart; + if (bC1) { + dxC1=pC1->X()-nStart; + pC1->X()=nStart; + } + if (bC2) { + dxC2=pC2->X()-nStart; + pC2->X()=nStart; + } + } else { + long nStart=rCenter.Y()-rRad.Y(); + dy1=rPnt.Y()-nStart; + rPnt.Y()=nStart; + if (bC1) { + dyC1=pC1->Y()-nStart; + pC1->Y()=nStart; + } + if (bC2) { + dyC2=pC2->Y()-nStart; + pC2->Y()=nStart; + } + } + double nWink=GetCrookAngle(rPnt,rCenter,rRad,bVert); + double sn=sin(nWink); + double cs=cos(nWink); + RotatePoint(rPnt,rCenter,sn,cs); + if (bC1) { if (bVert) pC1->Y()-=y0-rCenter.Y(); else pC1->X()-=x0-rCenter.X(); RotatePoint(*pC1,rCenter,sn,cs); } + if (bC2) { if (bVert) pC2->Y()-=y0-rCenter.Y(); else pC2->X()-=x0-rCenter.X(); RotatePoint(*pC2,rCenter,sn,cs); } + if (bVert) { + rPnt.X()+=dx1; + if (bC1) pC1->X()+=dxC1; + if (bC2) pC2->X()+=dxC2; + } else { + rPnt.Y()+=dy1; + if (bC1) pC1->Y()+=dyC1; + if (bC2) pC2->Y()+=dyC2; + } + rSin=sn; + rCos=cs; + return nWink; +} + +double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter, + const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert, + const Rectangle rRefRect) +{ + //FASTBOOL bC1=pC1!=NULL; + //FASTBOOL bC2=pC2!=NULL; + //long x0=rPnt.X(); + long y0=rPnt.Y(); + CrookSlantXPoint(rPnt,pC1,pC2,rCenter,rRad,rSin,rCos,bVert); + if (bVert) { + } else { + //long nBase=rCenter.Y()-rRad.Y(); + long nTop=rRefRect.Top(); + long nBtm=rRefRect.Bottom(); + long nHgt=nBtm-nTop; + long dy=rPnt.Y()-y0; + //FASTBOOL bOben=rRad.Y()<0; + double a=((double)(y0-nTop))/nHgt; + a*=dy; + rPnt.Y()=y0+Round(a); + } return 0.0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert) +{ + double nSin,nCos; + USHORT nPointAnz=rPoly.GetPointCount(); + USHORT i=0; + while (i<nPointAnz) { + Point* pPnt=&rPoly[i]; + Point* pC1=NULL; + Point* pC2=NULL; + if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links + pC1=pPnt; + i++; + pPnt=&rPoly[i]; + } + i++; + if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts + pC2=&rPoly[i]; + i++; + } + CrookRotateXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert); + } +} + +void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert) +{ + double nSin,nCos; + USHORT nPointAnz=rPoly.GetPointCount(); + USHORT i=0; + while (i<nPointAnz) { + Point* pPnt=&rPoly[i]; + Point* pC1=NULL; + Point* pC2=NULL; + if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links + pC1=pPnt; + i++; + pPnt=&rPoly[i]; + } + i++; + if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts + pC2=&rPoly[i]; + i++; + } + CrookSlantXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert); + } +} + +void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect) +{ + double nSin,nCos; + USHORT nPointAnz=rPoly.GetPointCount(); + USHORT i=0; + while (i<nPointAnz) { + Point* pPnt=&rPoly[i]; + Point* pC1=NULL; + Point* pC2=NULL; + if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links + pC1=pPnt; + i++; + pPnt=&rPoly[i]; + } + i++; + if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts + pC2=&rPoly[i]; + i++; + } + CrookStretchXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert,rRefRect); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert) +{ + USHORT nPolyAnz=rPoly.Count(); + for (USHORT nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) { + CrookRotatePoly(rPoly[nPolyNum],rCenter,rRad,bVert); + } +} + +void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert) +{ + USHORT nPolyAnz=rPoly.Count(); + for (USHORT nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) { + CrookSlantPoly(rPoly[nPolyNum],rCenter,rRad,bVert); + } +} + +void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect) +{ + USHORT nPolyAnz=rPoly.Count(); + for (USHORT nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) { + CrookStretchPoly(rPoly[nPolyNum],rCenter,rRad,bVert,rRefRect); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +long GetAngle(const Point& rPnt) +{ + long a=0; + if (rPnt.Y()==0) { + if (rPnt.X()<0) a=-18000; + } else if (rPnt.X()==0) { + if (rPnt.Y()>0) a=-9000; + else a=9000; + } else { + a=Round((atan2((double)-rPnt.Y(),(double)rPnt.X())/nPi180)); + } + return a; +} + +long NormAngle180(long a) +{ + while (a<18000) a+=36000; + while (a>=18000) a-=36000; + return a; +} + +long NormAngle360(long a) +{ + while (a<0) a+=36000; + while (a>=36000) a-=36000; + return a; +} + +USHORT GetAngleSector(long nWink) +{ + while (nWink<0) nWink+=36000; + while (nWink>=36000) nWink-=36000; + if (nWink< 9000) return 0; + if (nWink<18000) return 1; + if (nWink<27000) return 2; + return 3; +} + +long GetLen(const Point& rPnt) +{ + long x=Abs(rPnt.X()); + long y=Abs(rPnt.Y()); + if (x+y<0x8000) { // weil 7FFF * 7FFF * 2 = 7FFE0002 + x*=x; + y*=y; + x+=y; + x=Round(sqrt((double)x)); + return x; + } else { + double nx=x; + double ny=y; + nx*=nx; + ny*=ny; + nx+=ny; + nx=sqrt(nx); + if (nx>0x7FFFFFFF) { + return 0x7FFFFFFF; // Ueberlauf, mehr is nich! + } else { + return Round(nx); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void GeoStat::RecalcSinCos() +{ + if (nDrehWink==0) { + nSin=0.0; + nCos=1.0; + } else { + double a=nDrehWink*nPi180; + nSin=sin(a); + nCos=cos(a); + } +} + +void GeoStat::RecalcTan() +{ + if (nShearWink==0) { + nTan=0.0; + } else { + double a=nShearWink*nPi180; + nTan=tan(a); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Polygon Rect2Poly(const Rectangle& rRect, const GeoStat& rGeo) +{ + Polygon aPol(5); + aPol[0]=rRect.TopLeft(); + aPol[1]=rRect.TopRight(); + aPol[2]=rRect.BottomRight(); + aPol[3]=rRect.BottomLeft(); + aPol[4]=rRect.TopLeft(); + if (rGeo.nShearWink!=0) ShearPoly(aPol,rRect.TopLeft(),rGeo.nTan); + if (rGeo.nDrehWink!=0) RotatePoly(aPol,rRect.TopLeft(),rGeo.nSin,rGeo.nCos); + return aPol; +} + +void Poly2Rect(const Polygon& rPol, Rectangle& rRect, GeoStat& rGeo) +{ + rGeo.nDrehWink=GetAngle(rPol[1]-rPol[0]); + rGeo.nDrehWink=NormAngle360(rGeo.nDrehWink); + // Drehung ist damit im Kasten + rGeo.RecalcSinCos(); + + Point aPt1(rPol[1]-rPol[0]); + if (rGeo.nDrehWink!=0) RotatePoint(aPt1,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin fuer Rueckdrehung + long nWdt=aPt1.X(); + + Point aPt0(rPol[0]); + Point aPt3(rPol[3]-rPol[0]); + if (rGeo.nDrehWink!=0) RotatePoint(aPt3,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin fuer Rueckdrehung + long nHgt=aPt3.Y(); + + if(aPt3.X()) + { + // #i74358# the axes are not orthogonal, so for getting the correct height, + // calculate the length of aPt3 + + // #i74358# this change was wrong, in the field of the old geometry stuff + // it is not an error. The new height always is the same as before; shear + // does not change object height at all. This is different from the interactions, + // but obviously wanted in the old versions. + // + // nHgt = static_cast< long >(sqrt(static_cast< double >(aPt3.X() * aPt3.X() + aPt3.Y() * aPt3.Y()))); + } + + long nShW=GetAngle(aPt3); + nShW-=27000; // ShearWink wird zur Senkrechten gemessen + nShW=-nShW; // Negieren, denn '+' ist Rechtskursivierung + + FASTBOOL bMirr=aPt3.Y()<0; + if (bMirr) { // "Punktetausch" bei Spiegelung + nHgt=-nHgt; + nShW+=18000; + aPt0=rPol[3]; + } + nShW=NormAngle180(nShW); + if (nShW<-9000 || nShW>9000) { + nShW=NormAngle180(nShW+18000); + } + if (nShW<-SDRMAXSHEAR) nShW=-SDRMAXSHEAR; // ShearWinkel begrenzen auf +/- 89.00 deg + if (nShW>SDRMAXSHEAR) nShW=SDRMAXSHEAR; + rGeo.nShearWink=nShW; + rGeo.RecalcTan(); + Point aRU(aPt0); + aRU.X()+=nWdt; + aRU.Y()+=nHgt; + rRect=Rectangle(aPt0,aRU); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void OrthoDistance8(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho) +{ + long dx=rPt.X()-rPt0.X(); + long dy=rPt.Y()-rPt0.Y(); + long dxa=Abs(dx); + long dya=Abs(dy); + if (dx==0 || dy==0 || dxa==dya) return; + if (dxa>=dya*2) { rPt.Y()=rPt0.Y(); return; } + if (dya>=dxa*2) { rPt.X()=rPt0.X(); return; } + if ((dxa<dya) != bBigOrtho) { + rPt.Y()=rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) ); + } else { + rPt.X()=rPt0.X()+(dya* (dx>=0 ? 1 : -1) ); + } +} + +void OrthoDistance4(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho) +{ + long dx=rPt.X()-rPt0.X(); + long dy=rPt.Y()-rPt0.Y(); + long dxa=Abs(dx); + long dya=Abs(dy); + if ((dxa<dya) != bBigOrtho) { + rPt.Y()=rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) ); + } else { + rPt.X()=rPt0.X()+(dya* (dx>=0 ? 1 : -1) ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +long BigMulDiv(long nVal, long nMul, long nDiv) +{ + BigInt aVal(nVal); + aVal*=nMul; + if (aVal.IsNeg()!=(nDiv<0)) { + aVal-=nDiv/2; // fuer korrektes Runden + } else { + aVal+=nDiv/2; // fuer korrektes Runden + } + if(nDiv) + { + aVal/=nDiv; + return long(aVal); + } + return 0x7fffffff; +} + +void Kuerzen(Fraction& rF, unsigned nDigits) +{ + INT32 nMul=rF.GetNumerator(); + INT32 nDiv=rF.GetDenominator(); + FASTBOOL bNeg=FALSE; + if (nMul<0) { nMul=-nMul; bNeg=!bNeg; } + if (nDiv<0) { nDiv=-nDiv; bNeg=!bNeg; } + if (nMul==0 || nDiv==0) return; + UINT32 a; + a=UINT32(nMul); unsigned nMulZ=0; // Fuehrende Nullen zaehlen + while (a<0x00800000) { nMulZ+=8; a<<=8; } + while (a<0x80000000) { nMulZ++; a<<=1; } + a=UINT32(nDiv); unsigned nDivZ=0; // Fuehrende Nullen zaehlen + while (a<0x00800000) { nDivZ+=8; a<<=8; } + while (a<0x80000000) { nDivZ++; a<<=1; } + // Anzahl der verwendeten Digits bestimmen + int nMulDigits=32-nMulZ; + int nDivDigits=32-nDivZ; + // Nun bestimmen, wieviele Stellen hinten weg koennen + int nMulWeg=nMulDigits-nDigits; if (nMulWeg<0) nMulWeg=0; + int nDivWeg=nDivDigits-nDigits; if (nDivWeg<0) nDivWeg=0; + int nWeg=Min(nMulWeg,nDivWeg); + nMul>>=nWeg; + nDiv>>=nWeg; + if (nMul==0 || nDiv==0) { + DBG_WARNING("Oups, beim kuerzen einer Fraction hat sich Joe verrechnet."); + return; + } + if (bNeg) nMul=-nMul; + rF=Fraction(nMul,nDiv); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Wieviele eU-Einheiten passen in einen mm bzw. Inch? +// Oder wie gross ist ein eU in mm bzw. Inch, und davon der Kehrwert + +FrPair GetInchOrMM(MapUnit eU) +{ + switch (eU) { + case MAP_1000TH_INCH: return FrPair(1000,1); + case MAP_100TH_INCH : return FrPair( 100,1); + case MAP_10TH_INCH : return FrPair( 10,1); + case MAP_INCH : return FrPair( 1,1); + case MAP_POINT : return FrPair( 72,1); + case MAP_TWIP : return FrPair(1440,1); + case MAP_100TH_MM : return FrPair( 100,1); + case MAP_10TH_MM : return FrPair( 10,1); + case MAP_MM : return FrPair( 1,1); + case MAP_CM : return FrPair( 1,10); + case MAP_PIXEL : { + VirtualDevice aVD; + aVD.SetMapMode(MapMode(MAP_100TH_MM)); + Point aP(aVD.PixelToLogic(Point(64,64))); // 64 Pixel fuer bessere Genauigkeit + return FrPair(6400,aP.X(),6400,aP.Y()); + } + case MAP_APPFONT: case MAP_SYSFONT: { + VirtualDevice aVD; + aVD.SetMapMode(MapMode(eU)); + Point aP(aVD.LogicToPixel(Point(32,32))); // 32 Einheiten fuer bessere Genauigkeit + aVD.SetMapMode(MapMode(MAP_100TH_MM)); + aP=aVD.PixelToLogic(aP); + return FrPair(3200,aP.X(),3200,aP.Y()); + } + default: break; + } + return Fraction(1,1); +} + +FrPair GetInchOrMM(FieldUnit eU) +{ + switch (eU) { + case FUNIT_INCH : return FrPair( 1,1); + case FUNIT_POINT : return FrPair( 72,1); + case FUNIT_TWIP : return FrPair(1440,1); + case FUNIT_100TH_MM : return FrPair( 100,1); + case FUNIT_MM : return FrPair( 1,1); + case FUNIT_CM : return FrPair( 1,10); + case FUNIT_M : return FrPair( 1,1000); + case FUNIT_KM : return FrPair( 1,1000000); + case FUNIT_PICA : return FrPair( 6,1); + case FUNIT_FOOT : return FrPair( 1,12); + case FUNIT_MILE : return FrPair( 1,63360); + default: break; + } + return Fraction(1,1); +} + +// Den Faktor berechnen, der anzuwenden ist um n Einheiten von eS nach +// eD umzurechnen. Z.B. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100. + +FrPair GetMapFactor(MapUnit eS, MapUnit eD) +{ + if (eS==eD) return FrPair(1,1,1,1); + FrPair aS(GetInchOrMM(eS)); + FrPair aD(GetInchOrMM(eD)); + FASTBOOL bSInch=IsInch(eS); + FASTBOOL bDInch=IsInch(eD); + FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y()); + if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); } + if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); } + return aRet; +}; + +FrPair GetMapFactor(MapUnit eS, FieldUnit eD) +{ + FrPair aS(GetInchOrMM(eS)); + FrPair aD(GetInchOrMM(eD)); + FASTBOOL bSInch=IsInch(eS); + FASTBOOL bDInch=IsInch(eD); + FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y()); + if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); } + if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); } + return aRet; +}; + +FrPair GetMapFactor(FieldUnit eS, MapUnit eD) +{ + FrPair aS(GetInchOrMM(eS)); + FrPair aD(GetInchOrMM(eD)); + FASTBOOL bSInch=IsInch(eS); + FASTBOOL bDInch=IsInch(eD); + FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y()); + if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); } + if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); } + return aRet; +}; + +FrPair GetMapFactor(FieldUnit eS, FieldUnit eD) +{ + if (eS==eD) return FrPair(1,1,1,1); + FrPair aS(GetInchOrMM(eS)); + FrPair aD(GetInchOrMM(eD)); + FASTBOOL bSInch=IsInch(eS); + FASTBOOL bDInch=IsInch(eD); + FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y()); + if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); } + if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); } + return aRet; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm + // 1 furlong = 10 chains = 7.920" = 201.168,0mm + // 1 chain = 4 poles = 792" = 20.116,8mm + // 1 pole = 5 1/2 yd = 198" = 5.029,2mm + // 1 yd = 3 ft = 36" = 914,4mm + // 1 ft = 12 " = 1" = 304,8mm + +void GetMeterOrInch(MapUnit eMU, short& rnKomma, long& rnMul, long& rnDiv, FASTBOOL& rbMetr, FASTBOOL& rbInch) +{ + rnMul=1; rnDiv=1; + short nKomma=0; + FASTBOOL bMetr=FALSE,bInch=FALSE; + switch (eMU) { + // Metrisch + case MAP_100TH_MM : bMetr=TRUE; nKomma=5; break; + case MAP_10TH_MM : bMetr=TRUE; nKomma=4; break; + case MAP_MM : bMetr=TRUE; nKomma=3; break; + case MAP_CM : bMetr=TRUE; nKomma=2; break; + // Inch + case MAP_1000TH_INCH: bInch=TRUE; nKomma=3; break; + case MAP_100TH_INCH : bInch=TRUE; nKomma=2; break; + case MAP_10TH_INCH : bInch=TRUE; nKomma=1; break; + case MAP_INCH : bInch=TRUE; nKomma=0; break; + case MAP_POINT : bInch=TRUE; rnDiv=72; break; // 1Pt = 1/72" + case MAP_TWIP : bInch=TRUE; rnDiv=144; nKomma=1; break; // 1Twip = 1/1440" + // Sonstiges + case MAP_PIXEL : break; + case MAP_SYSFONT : break; + case MAP_APPFONT : break; + case MAP_RELATIVE : break; + default: break; + } // switch + rnKomma=nKomma; + rbMetr=bMetr; + rbInch=bInch; +} + +void GetMeterOrInch(FieldUnit eFU, short& rnKomma, long& rnMul, long& rnDiv, FASTBOOL& rbMetr, FASTBOOL& rbInch) +{ + rnMul=1; rnDiv=1; + short nKomma=0; + FASTBOOL bMetr=FALSE,bInch=FALSE; + switch (eFU) { + case FUNIT_NONE : break; + // Metrisch + case FUNIT_100TH_MM : bMetr=TRUE; nKomma=5; break; + case FUNIT_MM : bMetr=TRUE; nKomma=3; break; + case FUNIT_CM : bMetr=TRUE; nKomma=2; break; + case FUNIT_M : bMetr=TRUE; nKomma=0; break; + case FUNIT_KM : bMetr=TRUE; nKomma=-3; break; + // Inch + case FUNIT_TWIP : bInch=TRUE; rnDiv=144; nKomma=1; break; // 1Twip = 1/1440" + case FUNIT_POINT : bInch=TRUE; rnDiv=72; break; // 1Pt = 1/72" + case FUNIT_PICA : bInch=TRUE; rnDiv=6; break; // 1Pica = 1/6" ? + case FUNIT_INCH : bInch=TRUE; break; // 1" = 1" + case FUNIT_FOOT : bInch=TRUE; rnMul=12; break; // 1Ft = 12" + case FUNIT_MILE : bInch=TRUE; rnMul=6336; nKomma=-1; break; // 1mile = 63360" + // sonstiges + case FUNIT_CUSTOM : break; + case FUNIT_PERCENT : nKomma=2; break; + } // switch + rnKomma=nKomma; + rbMetr=bMetr; + rbInch=bInch; +} + +void SdrFormatter::Undirty() +{ + if (aScale.GetNumerator()==0 || aScale.GetDenominator()==0) aScale=Fraction(1,1); + FASTBOOL bSrcMetr,bSrcInch,bDstMetr,bDstInch; + long nMul1,nDiv1,nMul2,nDiv2; + short nKomma1,nKomma2; + // Zunaechst normalisieren auf m bzw. " + if (!bSrcFU) { + GetMeterOrInch(eSrcMU,nKomma1,nMul1,nDiv1,bSrcMetr,bSrcInch); + } else { + GetMeterOrInch(eSrcFU,nKomma1,nMul1,nDiv1,bSrcMetr,bSrcInch); + } + if (!bDstFU) { + GetMeterOrInch(eDstMU,nKomma2,nMul2,nDiv2,bDstMetr,bDstInch); + } else { + GetMeterOrInch(eDstFU,nKomma2,nMul2,nDiv2,bDstMetr,bDstInch); + } + nMul1*=nDiv2; + nDiv1*=nMul2; + nKomma1=nKomma1-nKomma2; + + if (bSrcInch && bDstMetr) { + nKomma1+=4; + nMul1*=254; + } + if (bSrcMetr && bDstInch) { + nKomma1-=4; + nDiv1*=254; + } + + // Temporaere Fraction zum Kuerzen + Fraction aTempFract(nMul1,nDiv1); + nMul1=aTempFract.GetNumerator(); + nDiv1=aTempFract.GetDenominator(); + + nMul_=nMul1; + nDiv_=nDiv1; + nKomma_=nKomma1; + bDirty=FALSE; +} + + +void SdrFormatter::TakeStr(long nVal, XubString& rStr) const +{ + sal_Unicode aNullCode('0'); + + if(!nVal) + { + rStr = UniString(); + rStr += aNullCode; + return; + } + + // Hier fallen trotzdem evtl. Nachkommastellen weg, wg. MulDiv statt Real + BOOL bNeg(nVal < 0); + SvtSysLocale aSysLoc; + const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData(); + + ForceUndirty(); + + sal_Int16 nK(nKomma_); + XubString aStr; + + if(bNeg) + nVal = -nVal; + + while(nK <= -3) + { + nVal *= 1000; + nK += 3; + } + + while(nK <= -1) + { + nVal *= 10; + nK++; + } + + if(nMul_ != nDiv_) + nVal = BigMulDiv(nVal, nMul_, nDiv_); + + aStr = UniString::CreateFromInt32(nVal); + + if(nK > 0 && aStr.Len() <= nK ) + { + // Komma erforderlich + sal_Int16 nAnz(nK - aStr.Len()); + + if(nAnz >= 0 && rLoc.isNumLeadingZero()) + nAnz++; + + for(xub_StrLen i=0; i<nAnz; i++) + aStr.Insert(aNullCode, 0); + + // zuviele Nachkommastellen abhacken + xub_StrLen nNumDigits(rLoc.getNumDigits()); + xub_StrLen nWeg(nK - nNumDigits); + + if(nWeg > 0) + { + // hier muesste eigentlich noch gerundet werden! + aStr.Erase(aStr.Len() - nWeg); + nK = nNumDigits; + } + } + + // Vorkommastellen fuer spaeter merken + xub_StrLen nVorKomma(aStr.Len() - nK); + + if(nK > 0) + { + // KommaChar einfuegen + // erstmal trailing Zeros abhacken + while(nK > 0 && aStr.GetChar(aStr.Len() - 1) == aNullCode) + { + aStr.Erase(aStr.Len() - 1); + nK--; + } + + if(nK > 0) + { + // na, noch Nachkommastellen da? + sal_Unicode cDec(rLoc.getNumDecimalSep().GetChar(0)); + aStr.Insert(cDec, nVorKomma); + } + } + + // ggf. Trennpunkte bei jedem Tausender einfuegen + if( nVorKomma > 3 ) + { + String aThoSep( rLoc.getNumThousandSep() ); + if ( aThoSep.Len() > 0 ) + { + sal_Unicode cTho( aThoSep.GetChar(0) ); + sal_Int32 i(nVorKomma - 3); + + while(i > 0) + { + rStr.Insert(cTho, (xub_StrLen)i); + i -= 3; + } + } + } + + if(!aStr.Len()) + aStr += aNullCode; + + if(bNeg && (aStr.Len() > 1 || aStr.GetChar(0) != aNullCode)) + { + rStr.Insert(sal_Unicode('-'), 0); + } + + rStr = aStr; +} + +void SdrFormatter::TakeUnitStr(MapUnit eUnit, XubString& rStr) +{ + switch(eUnit) + { + // Metrisch + case MAP_100TH_MM : + { + sal_Char aText[] = "/100mm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_10TH_MM : + { + sal_Char aText[] = "/10mm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_MM : + { + sal_Char aText[] = "mm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_CM : + { + sal_Char aText[] = "cm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + + // Inch + case MAP_1000TH_INCH: + { + sal_Char aText[] = "/1000\""; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_100TH_INCH : + { + sal_Char aText[] = "/100\""; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_10TH_INCH : + { + sal_Char aText[] = "/10\""; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_INCH : + { + rStr = UniString(); + rStr += sal_Unicode('"'); + break; + } + case MAP_POINT : + { + sal_Char aText[] = "pt"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_TWIP : + { + sal_Char aText[] = "twip"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + + // Sonstiges + case MAP_PIXEL : + { + sal_Char aText[] = "pixel"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_SYSFONT : + { + sal_Char aText[] = "sysfont"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_APPFONT : + { + sal_Char aText[] = "appfont"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case MAP_RELATIVE : + { + rStr = UniString(); + rStr += sal_Unicode('%'); + break; + } + default: break; + } +} + +void SdrFormatter::TakeUnitStr(FieldUnit eUnit, XubString& rStr) +{ + switch(eUnit) + { + default : + case FUNIT_NONE : + case FUNIT_CUSTOM : + { + rStr = UniString(); + break; + } + + // Metrisch + case FUNIT_100TH_MM: + { + sal_Char aText[] = "/100mm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_MM : + { + sal_Char aText[] = "mm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_CM : + { + sal_Char aText[] = "cm"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_M : + { + rStr = UniString(); + rStr += sal_Unicode('m'); + break; + } + case FUNIT_KM : + { + sal_Char aText[] = "km"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + + // Inch + case FUNIT_TWIP : + { + sal_Char aText[] = "twip"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_POINT : + { + sal_Char aText[] = "pt"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_PICA : + { + sal_Char aText[] = "pica"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_INCH : + { + rStr = UniString(); + rStr += sal_Unicode('"'); + break; + } + case FUNIT_FOOT : + { + sal_Char aText[] = "ft"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + case FUNIT_MILE : + { + sal_Char aText[] = "mile(s)"; + rStr = UniString(aText, sizeof(aText-1)); + break; + } + + // sonstiges + case FUNIT_PERCENT: + { + rStr = UniString(); + rStr += sal_Unicode('%'); + break; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + diff --git a/svx/source/svdraw/svdundo.cxx b/svx/source/svdraw/svdundo.cxx new file mode 100644 index 000000000000..667dd3a340b5 --- /dev/null +++ b/svx/source/svdraw/svdundo.cxx @@ -0,0 +1,1871 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <svx/svdundo.hxx> +#include "svditext.hxx" +#include <svx/svdotext.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdlayer.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdview.hxx> +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include <svx/scene3d.hxx> +#include <editeng/outlobj.hxx> +#include <svx/svdogrp.hxx> +#include <svx/sdr/properties/itemsettools.hxx> +#include <svx/sdr/properties/properties.hxx> +#include <svx/svdocapt.hxx> +#include <svl/whiter.hxx> +#include <svx/e3dsceneupdater.hxx> + +#include "svdviter.hxx" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// iterates over all views and unmarks this SdrObject if it is marked +static void ImplUnmarkObject( SdrObject* pObj ) +{ + SdrViewIter aIter( pObj ); + for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() ) + { + pView->MarkObj( pObj, pView->GetSdrPageView(), TRUE ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrUndoAction,SfxUndoAction); + +BOOL SdrUndoAction::CanRepeat(SfxRepeatTarget& rView) const +{ + SdrView* pV=PTR_CAST(SdrView,&rView); + if (pV!=NULL) return CanSdrRepeat(*pV); + return FALSE; +} + +void SdrUndoAction::Repeat(SfxRepeatTarget& rView) +{ + SdrView* pV=PTR_CAST(SdrView,&rView); + if (pV!=NULL) SdrRepeat(*pV); + DBG_ASSERT(pV!=NULL,"Repeat: Uebergebenes SfxRepeatTarget ist keine SdrView"); +} + +XubString SdrUndoAction::GetRepeatComment(SfxRepeatTarget& rView) const +{ + SdrView* pV=PTR_CAST(SdrView,&rView); + if (pV!=NULL) return GetSdrRepeatComment(*pV); + return String(); +} + +bool SdrUndoAction::CanSdrRepeat(SdrView& /*rView*/) const +{ + return FALSE; +} + +void SdrUndoAction::SdrRepeat(SdrView& /*rView*/) +{ +} + +XubString SdrUndoAction::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + return String(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoGroup::SdrUndoGroup(SdrModel& rNewMod) +: SdrUndoAction(rNewMod), + aBuf(1024,32,32), + eFunction(SDRREPFUNC_OBJ_NONE) /*#72642#*/ +{} + +SdrUndoGroup::SdrUndoGroup(SdrModel& rNewMod,const String& rStr) +: SdrUndoAction(rNewMod), + aBuf(1024,32,32), + aComment(rStr), + eFunction(SDRREPFUNC_OBJ_NONE) +{} + +SdrUndoGroup::~SdrUndoGroup() +{ + Clear(); +} + +void SdrUndoGroup::Clear() +{ + for (ULONG nu=0; nu<GetActionCount(); nu++) { + SdrUndoAction* pAct=GetAction(nu); + delete pAct; + } + aBuf.Clear(); +} + +void SdrUndoGroup::AddAction(SdrUndoAction* pAct) +{ + aBuf.Insert(pAct,CONTAINER_APPEND); +} + +void SdrUndoGroup::push_front( SdrUndoAction* pAct ) +{ + aBuf.Insert(pAct, (ULONG)0 ); +} + +void SdrUndoGroup::Undo() +{ + for (ULONG nu=GetActionCount(); nu>0;) { + nu--; + SdrUndoAction* pAct=GetAction(nu); + pAct->Undo(); + } +} + +void SdrUndoGroup::Redo() +{ + for (ULONG nu=0; nu<GetActionCount(); nu++) { + SdrUndoAction* pAct=GetAction(nu); + pAct->Redo(); + } +} + +XubString SdrUndoGroup::GetComment() const +{ + XubString aRet(aComment); + sal_Char aSearchText[] = "%1"; + String aSearchString(aSearchText, sizeof(aSearchText-1)); + + aRet.SearchAndReplace(aSearchString, aObjDescription); + + return aRet; +} + +bool SdrUndoGroup::CanSdrRepeat(SdrView& rView) const +{ + switch (eFunction) { + case SDRREPFUNC_OBJ_NONE : return FALSE; + case SDRREPFUNC_OBJ_DELETE : return rView.AreObjectsMarked(); + case SDRREPFUNC_OBJ_COMBINE_POLYPOLY: return rView.IsCombinePossible(FALSE); + case SDRREPFUNC_OBJ_COMBINE_ONEPOLY : return rView.IsCombinePossible(TRUE); + case SDRREPFUNC_OBJ_DISMANTLE_POLYS : return rView.IsDismantlePossible(FALSE); + case SDRREPFUNC_OBJ_DISMANTLE_LINES : return rView.IsDismantlePossible(TRUE); + case SDRREPFUNC_OBJ_CONVERTTOPOLY : return rView.IsConvertToPolyObjPossible(FALSE); + case SDRREPFUNC_OBJ_CONVERTTOPATH : return rView.IsConvertToPathObjPossible(FALSE); + case SDRREPFUNC_OBJ_GROUP : return rView.IsGroupPossible(); + case SDRREPFUNC_OBJ_UNGROUP : return rView.IsUnGroupPossible(); + case SDRREPFUNC_OBJ_PUTTOTOP : return rView.IsToTopPossible(); + case SDRREPFUNC_OBJ_PUTTOBTM : return rView.IsToBtmPossible(); + case SDRREPFUNC_OBJ_MOVTOTOP : return rView.IsToTopPossible(); + case SDRREPFUNC_OBJ_MOVTOBTM : return rView.IsToBtmPossible(); + case SDRREPFUNC_OBJ_REVORDER : return rView.IsReverseOrderPossible(); + case SDRREPFUNC_OBJ_IMPORTMTF : return rView.IsImportMtfPossible(); + default: break; + } // switch + return FALSE; +} + +void SdrUndoGroup::SdrRepeat(SdrView& rView) +{ + switch (eFunction) { + case SDRREPFUNC_OBJ_NONE : break; + case SDRREPFUNC_OBJ_DELETE : rView.DeleteMarked(); break; + case SDRREPFUNC_OBJ_COMBINE_POLYPOLY: rView.CombineMarkedObjects(sal_False); break; + case SDRREPFUNC_OBJ_COMBINE_ONEPOLY : rView.CombineMarkedObjects(sal_True); break; + case SDRREPFUNC_OBJ_DISMANTLE_POLYS : rView.DismantleMarkedObjects(FALSE); break; + case SDRREPFUNC_OBJ_DISMANTLE_LINES : rView.DismantleMarkedObjects(TRUE); break; + case SDRREPFUNC_OBJ_CONVERTTOPOLY : rView.ConvertMarkedToPolyObj(FALSE); break; + case SDRREPFUNC_OBJ_CONVERTTOPATH : rView.ConvertMarkedToPathObj(FALSE); break; + case SDRREPFUNC_OBJ_GROUP : rView.GroupMarked(); break; + case SDRREPFUNC_OBJ_UNGROUP : rView.UnGroupMarked(); break; + case SDRREPFUNC_OBJ_PUTTOTOP : rView.PutMarkedToTop(); break; + case SDRREPFUNC_OBJ_PUTTOBTM : rView.PutMarkedToBtm(); break; + case SDRREPFUNC_OBJ_MOVTOTOP : rView.MovMarkedToTop(); break; + case SDRREPFUNC_OBJ_MOVTOBTM : rView.MovMarkedToBtm(); break; + case SDRREPFUNC_OBJ_REVORDER : rView.ReverseOrderOfMarked(); break; + case SDRREPFUNC_OBJ_IMPORTMTF : rView.DoImportMarkedMtf(); break; + default: break; + } // switch +} + +XubString SdrUndoGroup::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + XubString aRet(aComment); + sal_Char aSearchText[] = "%1"; + String aSearchString(aSearchText, sizeof(aSearchText-1)); + + aRet.SearchAndReplace(aSearchString, ImpGetResStr(STR_ObjNameSingulPlural)); + + return aRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@ @@@@@ @@@@@@ @@@@@ @@@@ @@@@@@ @@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@@@@ @@ @@@@ @@ @@ @@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@ @@@@@ @@@@ @@@@@ @@@@ @@ @@@@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoObj::SdrUndoObj(SdrObject& rNewObj): + SdrUndoAction(*rNewObj.GetModel()), + pObj(&rNewObj) +{ +} + +void SdrUndoObj::GetDescriptionStringForObject( const SdrObject& _rForObject, USHORT nStrCacheID, String& rStr, FASTBOOL bRepeat ) +{ + rStr = ImpGetResStr(nStrCacheID); + sal_Char aSearchText[] = "%1"; + String aSearchString(aSearchText, sizeof(aSearchText-1)); + + xub_StrLen nPos = rStr.Search(aSearchString); + + if(nPos != STRING_NOTFOUND) + { + rStr.Erase(nPos, 2); + + if(bRepeat) + { + rStr.Insert(ImpGetResStr(STR_ObjNameSingulPlural), nPos); + } + else + { + XubString aStr; + + _rForObject.TakeObjNameSingul(aStr); + rStr.Insert(aStr, nPos); + } + } +} + +void SdrUndoObj::ImpTakeDescriptionStr(USHORT nStrCacheID, XubString& rStr, FASTBOOL bRepeat) const +{ + if ( pObj ) + GetDescriptionStringForObject( *pObj, nStrCacheID, rStr, bRepeat ); +} + +// #94278# common call method for evtl. page change when UNDO/REDO +// is triggered +void SdrUndoObj::ImpShowPageOfThisObject() +{ + if(pObj && pObj->IsInserted() && pObj->GetPage() && pObj->GetModel()) + { + SdrHint aHint(HINT_SWITCHTOPAGE); + + aHint.SetObject(pObj); + aHint.SetPage(pObj->GetPage()); + + pObj->GetModel()->Broadcast(aHint); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoAttrObj::SdrUndoAttrObj(SdrObject& rNewObj, FASTBOOL bStyleSheet1, FASTBOOL bSaveText) +: SdrUndoObj(rNewObj), + pUndoSet(NULL), + pRedoSet(NULL), + pRepeatSet(NULL), + pUndoStyleSheet(NULL), + pRedoStyleSheet(NULL), + pRepeatStyleSheet(NULL), + bHaveToTakeRedoSet(TRUE), + pTextUndo(NULL), + + // #i8508# + pTextRedo(NULL), + + pUndoGroup(NULL) +{ + bStyleSheet = bStyleSheet1; + + SdrObjList* pOL = rNewObj.GetSubList(); + BOOL bIsGroup(pOL!=NULL && pOL->GetObjCount()); + BOOL bIs3DScene(bIsGroup && pObj->ISA(E3dScene)); + + if(bIsGroup) + { + // Aha, Gruppenobjekt + pUndoGroup = new SdrUndoGroup(*pObj->GetModel()); + sal_uInt32 nObjAnz(pOL->GetObjCount()); + + for(sal_uInt32 nObjNum(0); nObjNum < nObjAnz; nObjNum++) + { + pUndoGroup->AddAction( + new SdrUndoAttrObj(*pOL->GetObj(nObjNum), bStyleSheet1)); + } + } + + if(!bIsGroup || bIs3DScene) + { + if(pUndoSet) + { + delete pUndoSet; + } + + pUndoSet = new SfxItemSet(pObj->GetMergedItemSet()); + + if(bStyleSheet) + pUndoStyleSheet = pObj->GetStyleSheet(); + + if(bSaveText) + { + pTextUndo = pObj->GetOutlinerParaObject(); + if(pTextUndo) + pTextUndo = new OutlinerParaObject(*pTextUndo); + } + } +} + +SdrUndoAttrObj::~SdrUndoAttrObj() +{ + if(pUndoSet) + delete pUndoSet; + if(pRedoSet) + delete pRedoSet; + if(pRepeatSet) + delete pRepeatSet; + if(pUndoGroup) + delete pUndoGroup; + if(pTextUndo) + delete pTextUndo; + + // #i8508# + if(pTextRedo) + delete pTextRedo; +} + +void SdrUndoAttrObj::SetRepeatAttr(const SfxItemSet& rSet) +{ + if(pRepeatSet) + delete pRepeatSet; + + pRepeatSet = new SfxItemSet(rSet); +} + +void SdrUndoAttrObj::Undo() +{ + E3DModifySceneSnapRectUpdater aUpdater(pObj); + BOOL bIs3DScene(pObj && pObj->ISA(E3dScene)); + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + if(!pUndoGroup || bIs3DScene) + { + if(bHaveToTakeRedoSet) + { + bHaveToTakeRedoSet = FALSE; + + if(pRedoSet) + { + delete pRedoSet; + } + + pRedoSet = new SfxItemSet(pObj->GetMergedItemSet()); + + if(bStyleSheet) + pRedoStyleSheet=pObj->GetStyleSheet(); + + if(pTextUndo) + { + // #i8508# + pTextRedo = pObj->GetOutlinerParaObject(); + + if(pTextRedo) + pTextRedo = new OutlinerParaObject(*pTextRedo); + } + } + + if(bStyleSheet) + { + pRedoStyleSheet = pObj->GetStyleSheet(); + pObj->SetStyleSheet(pUndoStyleSheet, TRUE); + } + + sdr::properties::ItemChangeBroadcaster aItemChange(*pObj); + + // #105122# Since ClearItem sets back everything to normal + // it also sets fit-to-size text to non-fit-to-size text and + // switches on autogrowheight (the default). That may lead to + // loosing the geometry size info for the object when it is + // re-layouted from AdjustTextFrameWidthAndHeight(). This makes + // rescuing the size of the object necessary. + const Rectangle aSnapRect = pObj->GetSnapRect(); + + if(pUndoSet) + { + // #109587# + if(pObj->ISA(SdrCaptionObj)) + { + // do a more smooth item deletion here, else the text + // rect will be reformatted, especially when information regarding + // vertical text is changed. When clearing only set items it's + // slower, but safer regarding such information (it's not changed + // usually) + SfxWhichIter aIter(*pUndoSet); + sal_uInt16 nWhich(aIter.FirstWhich()); + + while(nWhich) + { + if(SFX_ITEM_SET != pUndoSet->GetItemState(nWhich, sal_False)) + { + pObj->ClearMergedItem(nWhich); + } + + nWhich = aIter.NextWhich(); + } + } + else + { + pObj->ClearMergedItem(); + } + + pObj->SetMergedItemSet(*pUndoSet); + } + + // #105122# Restore prev size here when it was changed. + if(aSnapRect != pObj->GetSnapRect()) + { + pObj->NbcSetSnapRect(aSnapRect); + } + + pObj->GetProperties().BroadcastItemChange(aItemChange); + + if(pTextUndo) + { + pObj->SetOutlinerParaObject(new OutlinerParaObject(*pTextUndo)); + } + } + + if(pUndoGroup) + { + pUndoGroup->Undo(); + } +} + +void SdrUndoAttrObj::Redo() +{ + E3DModifySceneSnapRectUpdater aUpdater(pObj); + BOOL bIs3DScene(pObj && pObj->ISA(E3dScene)); + + if(!pUndoGroup || bIs3DScene) + { + if(bStyleSheet) + { + pUndoStyleSheet = pObj->GetStyleSheet(); + pObj->SetStyleSheet(pRedoStyleSheet, TRUE); + } + + sdr::properties::ItemChangeBroadcaster aItemChange(*pObj); + + // #105122# + const Rectangle aSnapRect = pObj->GetSnapRect(); + + if(pRedoSet) + { + // #109587# + if(pObj->ISA(SdrCaptionObj)) + { + // do a more smooth item deletion here, else the text + // rect will be reformatted, especially when information regarding + // vertical text is changed. When clearing only set items it's + // slower, but safer regarding such information (it's not changed + // usually) + SfxWhichIter aIter(*pRedoSet); + sal_uInt16 nWhich(aIter.FirstWhich()); + + while(nWhich) + { + if(SFX_ITEM_SET != pRedoSet->GetItemState(nWhich, sal_False)) + { + pObj->ClearMergedItem(nWhich); + } + + nWhich = aIter.NextWhich(); + } + } + else + { + pObj->ClearMergedItem(); + } + + pObj->SetMergedItemSet(*pRedoSet); + } + + // #105122# Restore prev size here when it was changed. + if(aSnapRect != pObj->GetSnapRect()) + { + pObj->NbcSetSnapRect(aSnapRect); + } + + pObj->GetProperties().BroadcastItemChange(aItemChange); + + // #i8508# + if(pTextRedo) + { + pObj->SetOutlinerParaObject(new OutlinerParaObject(*pTextRedo)); + } + } + + if(pUndoGroup) + { + pUndoGroup->Redo(); + } + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +XubString SdrUndoAttrObj::GetComment() const +{ + XubString aStr; + + if(bStyleSheet) + { + ImpTakeDescriptionStr(STR_EditSetStylesheet, aStr); + } + else + { + ImpTakeDescriptionStr(STR_EditSetAttributes, aStr); + } + + return aStr; +} + +void SdrUndoAttrObj::SdrRepeat(SdrView& rView) +{ + if(pRepeatSet) + { + rView.SetAttrToMarked(*pRepeatSet, FALSE); + } +} + +bool SdrUndoAttrObj::CanSdrRepeat(SdrView& rView) const +{ + return (pRepeatSet!=0L && rView.AreObjectsMarked()); +} + +XubString SdrUndoAttrObj::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + XubString aStr; + + if(bStyleSheet) + { + ImpTakeDescriptionStr(STR_EditSetStylesheet, aStr, TRUE); + } + else + { + ImpTakeDescriptionStr(STR_EditSetAttributes, aStr, TRUE); + } + + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoMoveObj::Undo() +{ + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + pObj->Move(Size(-aDistance.Width(),-aDistance.Height())); +} + +void SdrUndoMoveObj::Redo() +{ + pObj->Move(Size(aDistance.Width(),aDistance.Height())); + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +XubString SdrUndoMoveObj::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_EditMove,aStr); + return aStr; +} + +void SdrUndoMoveObj::SdrRepeat(SdrView& rView) +{ + rView.MoveMarkedObj(aDistance); +} + +bool SdrUndoMoveObj::CanSdrRepeat(SdrView& rView) const +{ + return rView.AreObjectsMarked(); +} + +XubString SdrUndoMoveObj::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_EditMove,aStr,TRUE); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoGeoObj::SdrUndoGeoObj(SdrObject& rNewObj): + SdrUndoObj(rNewObj), + pUndoGeo(NULL), + pRedoGeo(NULL), + pUndoGroup(NULL) +{ + SdrObjList* pOL=rNewObj.GetSubList(); + if (pOL!=NULL && pOL->GetObjCount() && !rNewObj.ISA(E3dScene)) + { + // Aha, Gruppenobjekt + // AW: Aber keine 3D-Szene, dann nur fuer die Szene selbst den Undo anlegen + pUndoGroup=new SdrUndoGroup(*pObj->GetModel()); + ULONG nObjAnz=pOL->GetObjCount(); + for (ULONG nObjNum=0; nObjNum<nObjAnz; nObjNum++) { + pUndoGroup->AddAction(new SdrUndoGeoObj(*pOL->GetObj(nObjNum))); + } + } else { + pUndoGeo=pObj->GetGeoData(); + } +} + +SdrUndoGeoObj::~SdrUndoGeoObj() +{ + if (pUndoGeo!=NULL) delete pUndoGeo; + if (pRedoGeo!=NULL) delete pRedoGeo; + if (pUndoGroup!=NULL) delete pUndoGroup; +} + +void SdrUndoGeoObj::Undo() +{ + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + if(pUndoGroup) + { + pUndoGroup->Undo(); + + // #97172# + // only repaint, no objectchange + pObj->ActionChanged(); + } + else + { + if (pRedoGeo!=NULL) delete pRedoGeo; + pRedoGeo=pObj->GetGeoData(); + pObj->SetGeoData(*pUndoGeo); + } +} + +void SdrUndoGeoObj::Redo() +{ + if(pUndoGroup) + { + pUndoGroup->Redo(); + + // #97172# + // only repaint, no objectchange + pObj->ActionChanged(); + } + else + { + if (pUndoGeo!=NULL) delete pUndoGeo; + pUndoGeo=pObj->GetGeoData(); + pObj->SetGeoData(*pRedoGeo); + } + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +XubString SdrUndoGeoObj::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_DragMethObjOwn,aStr); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoObjList::SdrUndoObjList(SdrObject& rNewObj, bool bOrdNumDirect) +: SdrUndoObj(rNewObj), + bOwner(FALSE), + pView(NULL), + pPageView(NULL) +{ + pObjList=pObj->GetObjList(); + if (bOrdNumDirect) { + nOrdNum=pObj->GetOrdNumDirect(); + } else { + nOrdNum=pObj->GetOrdNum(); + } +} + +SdrUndoObjList::~SdrUndoObjList() +{ + if (pObj!=NULL && IsOwner()) + { + // Attribute muessen wieder in den regulaeren Pool + SetOwner(FALSE); + + // nun loeschen + SdrObject::Free( pObj ); + } +} + +void SdrUndoObjList::SetOwner(bool bNew) +{ + bOwner = bNew; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoRemoveObj::Undo() +{ + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + DBG_ASSERT(!pObj->IsInserted(),"UndoRemoveObj: pObj ist bereits Inserted"); + if (!pObj->IsInserted()) + { + // #i11426# + // For UNDOs in Calc/Writer it is necessary to adapt the anchor + // pos of the target object. + Point aOwnerAnchorPos(0, 0); + + if(pObjList + && pObjList->GetOwnerObj() + && pObjList->GetOwnerObj()->ISA(SdrObjGroup)) + { + aOwnerAnchorPos = pObjList->GetOwnerObj()->GetAnchorPos(); + } + + E3DModifySceneSnapRectUpdater aUpdater(pObjList->GetOwnerObj()); + SdrInsertReason aReason(SDRREASON_UNDO); + pObjList->InsertObject(pObj,nOrdNum,&aReason); + + // #i11426# + if(aOwnerAnchorPos.X() || aOwnerAnchorPos.Y()) + { + pObj->NbcSetAnchorPos(aOwnerAnchorPos); + } + } +} + +void SdrUndoRemoveObj::Redo() +{ + DBG_ASSERT(pObj->IsInserted(),"RedoRemoveObj: pObj ist nicht Inserted"); + if (pObj->IsInserted()) + { + ImplUnmarkObject( pObj ); + E3DModifySceneSnapRectUpdater aUpdater(pObj); + pObjList->RemoveObject(nOrdNum); + } + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoInsertObj::Undo() +{ + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + DBG_ASSERT(pObj->IsInserted(),"UndoInsertObj: pObj ist nicht Inserted"); + if (pObj->IsInserted()) + { + ImplUnmarkObject( pObj ); + +#ifdef DBG_UTIL + SdrObject* pChkObj= +#endif + pObjList->RemoveObject(nOrdNum); + DBG_ASSERT(pChkObj==pObj,"UndoInsertObj: RemoveObjNum!=pObj"); + } +} + +void SdrUndoInsertObj::Redo() +{ + DBG_ASSERT(!pObj->IsInserted(),"RedoInsertObj: pObj ist bereits Inserted"); + if (!pObj->IsInserted()) + { + // --> OD 2005-05-10 #i45952# - restore anchor position of an object, + // which becomes a member of a group, because its cleared in method + // <InsertObject(..)>. Needed for correct ReDo in Writer. + Point aAnchorPos( 0, 0 ); + if ( pObjList && + pObjList->GetOwnerObj() && + pObjList->GetOwnerObj()->ISA(SdrObjGroup) ) + { + aAnchorPos = pObj->GetAnchorPos(); + } + // <-- + + SdrInsertReason aReason(SDRREASON_UNDO); + pObjList->InsertObject(pObj,nOrdNum,&aReason); + + // --> OD 2005-05-10 #i45952# + if ( aAnchorPos.X() || aAnchorPos.Y() ) + { + pObj->NbcSetAnchorPos( aAnchorPos ); + } + // <-- + } + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoDelObj::Undo() +{ + SdrUndoRemoveObj::Undo(); + DBG_ASSERT(IsOwner(),"UndoDeleteObj: pObj gehoert nicht der UndoAction"); + SetOwner(FALSE); +} + +void SdrUndoDelObj::Redo() +{ + SdrUndoRemoveObj::Redo(); + DBG_ASSERT(!IsOwner(),"RedoDeleteObj: pObj gehoert bereits der UndoAction"); + SetOwner(TRUE); +} + +XubString SdrUndoDelObj::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_EditDelete,aStr); + return aStr; +} + +void SdrUndoDelObj::SdrRepeat(SdrView& rView) +{ + rView.DeleteMarked(); +} + +bool SdrUndoDelObj::CanSdrRepeat(SdrView& rView) const +{ + return rView.AreObjectsMarked(); +} + +XubString SdrUndoDelObj::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_EditDelete,aStr,TRUE); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoNewObj::Undo() +{ + SdrUndoInsertObj::Undo(); + DBG_ASSERT(!IsOwner(),"RedoNewObj: pObj gehoert bereits der UndoAction"); + SetOwner(TRUE); +} + +void SdrUndoNewObj::Redo() +{ + SdrUndoInsertObj::Redo(); + DBG_ASSERT(IsOwner(),"RedoNewObj: pObj gehoert nicht der UndoAction"); + SetOwner(FALSE); +} + +String SdrUndoNewObj::GetComment( const SdrObject& _rForObject ) +{ + String sComment; + GetDescriptionStringForObject( _rForObject, STR_UndoInsertObj, sComment ); + return sComment; +} + +XubString SdrUndoNewObj::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoInsertObj,aStr); + return aStr; +} + +SdrUndoReplaceObj::SdrUndoReplaceObj(SdrObject& rOldObj1, SdrObject& rNewObj1, bool bOrdNumDirect) +: SdrUndoObj(rOldObj1), + bOldOwner(FALSE), + bNewOwner(FALSE), + pNewObj(&rNewObj1) +{ + SetOldOwner(TRUE); + + pObjList=pObj->GetObjList(); + if (bOrdNumDirect) { + nOrdNum=pObj->GetOrdNumDirect(); + } else { + nOrdNum=pObj->GetOrdNum(); + } +} + +SdrUndoReplaceObj::~SdrUndoReplaceObj() +{ + if (pObj!=NULL && IsOldOwner()) + { + // Attribute muessen wieder in den regulaeren Pool + SetOldOwner(FALSE); + + // nun loeschen + SdrObject::Free( pObj ); + } + if (pNewObj!=NULL && IsNewOwner()) + { + // Attribute muessen wieder in den regulaeren Pool + SetNewOwner(FALSE); + + // nun loeschen + SdrObject::Free( pNewObj ); + } +} + +void SdrUndoReplaceObj::Undo() +{ + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + if (IsOldOwner() && !IsNewOwner()) + { + DBG_ASSERT(!pObj->IsInserted(),"SdrUndoReplaceObj::Undo(): Altes Objekt ist bereits inserted!"); + DBG_ASSERT(pNewObj->IsInserted(),"SdrUndoReplaceObj::Undo(): Neues Objekt ist nicht inserted!"); + SetOldOwner(FALSE); + SetNewOwner(TRUE); + + ImplUnmarkObject( pNewObj ); + pObjList->ReplaceObject(pObj,nOrdNum); + } + else + { + DBG_ERROR("SdrUndoReplaceObj::Undo(): IsMine-Flags stehen verkehrt. Doppelter Undo-Aufruf?"); + } +} + +void SdrUndoReplaceObj::Redo() +{ + if (!IsOldOwner() && IsNewOwner()) + { + DBG_ASSERT(!pNewObj->IsInserted(),"SdrUndoReplaceObj::Redo(): Neues Objekt ist bereits inserted!"); + DBG_ASSERT(pObj->IsInserted(),"SdrUndoReplaceObj::Redo(): Altes Objekt ist nicht inserted!"); + SetOldOwner(TRUE); + SetNewOwner(FALSE); + + ImplUnmarkObject( pObj ); + pObjList->ReplaceObject(pNewObj,nOrdNum); + + } + else + { + DBG_ERROR("SdrUndoReplaceObj::Redo(): IsMine-Flags stehen verkehrt. Doppelter Redo-Aufruf?"); + } + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +void SdrUndoReplaceObj::SetNewOwner(bool bNew) +{ + bNewOwner = bNew; +} + +void SdrUndoReplaceObj::SetOldOwner(bool bNew) +{ + bOldOwner = bNew; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +XubString SdrUndoCopyObj::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoCopyObj,aStr); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i11702# + +SdrUndoObjectLayerChange::SdrUndoObjectLayerChange(SdrObject& rObj, SdrLayerID aOldLayer, SdrLayerID aNewLayer) +: SdrUndoObj(rObj), + maOldLayer(aOldLayer), + maNewLayer(aNewLayer) +{ +} + +void SdrUndoObjectLayerChange::Undo() +{ + ImpShowPageOfThisObject(); + pObj->SetLayer(maOldLayer); +} + +void SdrUndoObjectLayerChange::Redo() +{ + pObj->SetLayer(maNewLayer); + ImpShowPageOfThisObject(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoObjOrdNum::SdrUndoObjOrdNum(SdrObject& rNewObj, UINT32 nOldOrdNum1, UINT32 nNewOrdNum1): + SdrUndoObj(rNewObj), + nOldOrdNum(nOldOrdNum1), + nNewOrdNum(nNewOrdNum1) +{ +} + +void SdrUndoObjOrdNum::Undo() +{ + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + SdrObjList* pOL=pObj->GetObjList(); + if (pOL==NULL) { + DBG_ERROR("UndoObjOrdNum: pObj hat keine ObjList"); + return; + } + pOL->SetObjectOrdNum(nNewOrdNum,nOldOrdNum); +} + +void SdrUndoObjOrdNum::Redo() +{ + SdrObjList* pOL=pObj->GetObjList(); + if (pOL==NULL) { + DBG_ERROR("RedoObjOrdNum: pObj hat keine ObjList"); + return; + } + pOL->SetObjectOrdNum(nOldOrdNum,nNewOrdNum); + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +XubString SdrUndoObjOrdNum::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoObjOrdNum,aStr); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoObjSetText::SdrUndoObjSetText(SdrObject& rNewObj, sal_Int32 nText) +: SdrUndoObj(rNewObj) +, pOldText(NULL) +, pNewText(NULL) +, bNewTextAvailable(FALSE) +, bEmptyPresObj(FALSE) +, mnText(nText) +{ + SdrText* pText = static_cast< SdrTextObj*>( &rNewObj )->getText(mnText); + if( pText && pText->GetOutlinerParaObject() ) + pOldText = new OutlinerParaObject(*pText->GetOutlinerParaObject()); + + bEmptyPresObj = rNewObj.IsEmptyPresObj(); +} + +SdrUndoObjSetText::~SdrUndoObjSetText() +{ + if ( pOldText ) + delete pOldText; + if ( pNewText ) + delete pNewText; +} + +void SdrUndoObjSetText::AfterSetText() +{ + if (!bNewTextAvailable) + { + SdrText* pText = static_cast< SdrTextObj*>( pObj )->getText(mnText); + if( pText && pText->GetOutlinerParaObject() ) + pNewText = new OutlinerParaObject(*pText->GetOutlinerParaObject()); + bNewTextAvailable=TRUE; + } +} + +void SdrUndoObjSetText::Undo() +{ + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); + + // alten Text sichern fuer Redo + if (!bNewTextAvailable) + AfterSetText(); + + // Text fuer Undo kopieren, denn SetOutlinerParaObject() ist Eigentumsuebereignung + OutlinerParaObject* pText1 = pOldText; + if(pText1) + pText1 = new OutlinerParaObject(*pText1); + + SdrText* pText = static_cast< SdrTextObj*>( pObj )->getText(mnText); + if( pText ) + pText->SetOutlinerParaObject(pText1); + + pObj->SetEmptyPresObj( bEmptyPresObj ); + pObj->ActionChanged(); +} + +void SdrUndoObjSetText::Redo() +{ + // Text fuer Undo kopieren, denn SetOutlinerParaObject() ist Eigentumsuebereignung + OutlinerParaObject* pText1 = pNewText; + + if(pText1) + pText1 = new OutlinerParaObject(*pText1); + + SdrText* pText = static_cast< SdrTextObj*>( pObj )->getText(mnText); + if( pText ) + static_cast< SdrTextObj* >( pObj )->NbcSetOutlinerParaObjectForText( pText1, pText ); + + pObj->ActionChanged(); + + // #94278# Trigger PageChangeCall + ImpShowPageOfThisObject(); +} + +XubString SdrUndoObjSetText::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoObjSetText,aStr); + return aStr; +} + +XubString SdrUndoObjSetText::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoObjSetText,aStr); + return aStr; +} + +void SdrUndoObjSetText::SdrRepeat(SdrView& rView) +{ + if (bNewTextAvailable && rView.AreObjectsMarked()) + { + const SdrMarkList& rML=rView.GetMarkedObjectList(); + + const bool bUndo = rView.IsUndoEnabled(); + if( bUndo ) + { + XubString aStr; + ImpTakeDescriptionStr(STR_UndoObjSetText,aStr); + rView.BegUndo(aStr); + } + + ULONG nAnz=rML.GetMarkCount(); + for (ULONG nm=0; nm<nAnz; nm++) + { + SdrObject* pObj2=rML.GetMark(nm)->GetMarkedSdrObj(); + SdrTextObj* pTextObj=PTR_CAST(SdrTextObj,pObj2); + if (pTextObj!=NULL) + { + if( bUndo ) + rView.AddUndo(new SdrUndoObjSetText(*pTextObj,0)); + + OutlinerParaObject* pText1=pNewText; + if (pText1!=NULL) + pText1 = new OutlinerParaObject(*pText1); + pTextObj->SetOutlinerParaObject(pText1); + } + } + + if( bUndo ) + rView.EndUndo(); + } +} + +bool SdrUndoObjSetText::CanSdrRepeat(SdrView& rView) const +{ + FASTBOOL bOk=FALSE; + if (bNewTextAvailable && rView.AreObjectsMarked()) { + bOk=TRUE; + } + return bOk; +} + +// --> OD 2009-07-09 #i73249# +SdrUndoObjStrAttr::SdrUndoObjStrAttr( SdrObject& rNewObj, + const ObjStrAttrType eObjStrAttr, + const String& sOldStr, + const String& sNewStr) + : SdrUndoObj( rNewObj ), + meObjStrAttr( eObjStrAttr ), + msOldStr( sOldStr ), + msNewStr( sNewStr ) +{ +} + +void SdrUndoObjStrAttr::Undo() +{ + ImpShowPageOfThisObject(); + + switch ( meObjStrAttr ) + { + case OBJ_NAME: + { + pObj->SetName( msOldStr ); + } + break; + case OBJ_TITLE: + { + pObj->SetTitle( msOldStr ); + } + break; + case OBJ_DESCRIPTION: + { + pObj->SetDescription( msOldStr ); + } + break; + } +} + +void SdrUndoObjStrAttr::Redo() +{ + switch ( meObjStrAttr ) + { + case OBJ_NAME: + { + pObj->SetName( msNewStr ); + } + break; + case OBJ_TITLE: + { + pObj->SetTitle( msNewStr ); + } + break; + case OBJ_DESCRIPTION: + { + pObj->SetDescription( msNewStr ); + } + break; + } + + ImpShowPageOfThisObject(); +} + +String SdrUndoObjStrAttr::GetComment() const +{ + String aStr; + switch ( meObjStrAttr ) + { + case OBJ_NAME: + { + ImpTakeDescriptionStr( STR_UndoObjName, aStr ); + aStr += sal_Unicode(' '); + aStr += sal_Unicode('\''); + aStr += msNewStr; + aStr += sal_Unicode('\''); + } + break; + case OBJ_TITLE: + { + ImpTakeDescriptionStr( STR_UndoObjTitle, aStr ); + } + break; + case OBJ_DESCRIPTION: + { + ImpTakeDescriptionStr( STR_UndoObjDescription, aStr ); + } + break; + } + + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@ @@@@ @@ @@ @@@@@ @@@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@@@@@ @@@@ @@@@ @@@@@ +// @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ +// @@@@@ @@ @@ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoLayer::SdrUndoLayer(USHORT nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel): + SdrUndoAction(rNewModel), + pLayer(rNewLayerAdmin.GetLayer(nLayerNum)), + pLayerAdmin(&rNewLayerAdmin), + nNum(nLayerNum), + bItsMine(FALSE) +{ +} + +SdrUndoLayer::~SdrUndoLayer() +{ + if (bItsMine) { + delete pLayer; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoNewLayer::Undo() +{ + DBG_ASSERT(!bItsMine,"SdrUndoNewLayer::Undo(): Layer gehoert bereits der UndoAction"); + bItsMine=TRUE; +#ifdef DBG_UTIL + SdrLayer* pCmpLayer= +#endif + pLayerAdmin->RemoveLayer(nNum); + DBG_ASSERT(pCmpLayer==pLayer,"SdrUndoNewLayer::Undo(): Removter Layer ist != pLayer"); +} + +void SdrUndoNewLayer::Redo() +{ + DBG_ASSERT(bItsMine,"SdrUndoNewLayer::Undo(): Layer gehoert nicht der UndoAction"); + bItsMine=FALSE; + pLayerAdmin->InsertLayer(pLayer,nNum); +} + +XubString SdrUndoNewLayer::GetComment() const +{ + return ImpGetResStr(STR_UndoNewLayer); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoDelLayer::Undo() +{ + DBG_ASSERT(bItsMine,"SdrUndoDelLayer::Undo(): Layer gehoert nicht der UndoAction"); + bItsMine=FALSE; + pLayerAdmin->InsertLayer(pLayer,nNum); +} + +void SdrUndoDelLayer::Redo() +{ + DBG_ASSERT(!bItsMine,"SdrUndoDelLayer::Undo(): Layer gehoert bereits der UndoAction"); + bItsMine=TRUE; +#ifdef DBG_UTIL + SdrLayer* pCmpLayer= +#endif + pLayerAdmin->RemoveLayer(nNum); + DBG_ASSERT(pCmpLayer==pLayer,"SdrUndoDelLayer::Redo(): Removter Layer ist != pLayer"); +} + +XubString SdrUndoDelLayer::GetComment() const +{ + return ImpGetResStr(STR_UndoDelLayer); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoMoveLayer::Undo() +{ +#ifdef DBG_UTIL + SdrLayer* pCmpLayer= +#endif + pLayerAdmin->RemoveLayer(nNeuPos); + DBG_ASSERT(pCmpLayer==pLayer,"SdrUndoMoveLayer::Undo(): Removter Layer ist != pLayer"); + pLayerAdmin->InsertLayer(pLayer,nNum); +} + +void SdrUndoMoveLayer::Redo() +{ +#ifdef DBG_UTIL + SdrLayer* pCmpLayer= +#endif + pLayerAdmin->RemoveLayer(nNum); + DBG_ASSERT(pCmpLayer==pLayer,"SdrUndoMoveLayer::Redo(): Removter Layer ist != pLayer"); + pLayerAdmin->InsertLayer(pLayer,nNeuPos); +} + +XubString SdrUndoMoveLayer::GetComment() const +{ + return ImpGetResStr(STR_UndoMovLayer); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@@@@ @@@@ @@@@ @@@@@ @@@@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ +// @@@@@ @@@@@@ @@ @@@ @@@@ @@@@ +// @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@@@@ @@@@@ @@@@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoPage::SdrUndoPage(SdrPage& rNewPg) +: SdrUndoAction(*rNewPg.GetModel()), + mrPage(rNewPg) +{ +} + +void SdrUndoPage::ImpInsertPage(USHORT nNum) +{ + DBG_ASSERT(!mrPage.IsInserted(),"SdrUndoPage::ImpInsertPage(): mrPage ist bereits Inserted"); + if (!mrPage.IsInserted()) { + if (mrPage.IsMasterPage()) { + rMod.InsertMasterPage(&mrPage,nNum); + } else { + rMod.InsertPage(&mrPage,nNum); + } + } +} + +void SdrUndoPage::ImpRemovePage(USHORT nNum) +{ + DBG_ASSERT(mrPage.IsInserted(),"SdrUndoPage::ImpRemovePage(): mrPage ist nicht Inserted"); + if (mrPage.IsInserted()) { + SdrPage* pChkPg=NULL; + if (mrPage.IsMasterPage()) { + pChkPg=rMod.RemoveMasterPage(nNum); + } else { + pChkPg=rMod.RemovePage(nNum); + } + DBG_ASSERT(pChkPg==&mrPage,"SdrUndoPage::ImpRemovePage(): RemovePage!=&mrPage"); + } +} + +void SdrUndoPage::ImpMovePage(USHORT nOldNum, USHORT nNewNum) +{ + DBG_ASSERT(mrPage.IsInserted(),"SdrUndoPage::ImpMovePage(): mrPage ist nicht Inserted"); + if (mrPage.IsInserted()) { + if (mrPage.IsMasterPage()) { + rMod.MoveMasterPage(nOldNum,nNewNum); + } else { + rMod.MovePage(nOldNum,nNewNum); + } + } +} + +void SdrUndoPage::ImpTakeDescriptionStr(USHORT nStrCacheID, XubString& rStr, USHORT /*n*/, FASTBOOL /*bRepeat*/) const +{ + rStr=ImpGetResStr(nStrCacheID); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoPageList::SdrUndoPageList(SdrPage& rNewPg): + SdrUndoPage(rNewPg), + bItsMine(FALSE) +{ + nPageNum=rNewPg.GetPageNum(); +} + +SdrUndoPageList::~SdrUndoPageList() +{ + if(bItsMine) + { + delete (&mrPage); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoDelPage::SdrUndoDelPage(SdrPage& rNewPg): + SdrUndoPageList(rNewPg), + pUndoGroup(NULL) +{ + bItsMine = TRUE; + + // Und nun ggf. die MasterPage-Beziehungen merken + if(mrPage.IsMasterPage()) + { + sal_uInt16 nPageAnz(rMod.GetPageCount()); + + for(sal_uInt16 nPageNum2(0); nPageNum2 < nPageAnz; nPageNum2++) + { + SdrPage* pDrawPage = rMod.GetPage(nPageNum2); + + if(pDrawPage->TRG_HasMasterPage()) + { + SdrPage& rMasterPage = pDrawPage->TRG_GetMasterPage(); + + if(&mrPage == &rMasterPage) + { + if(!pUndoGroup) + { + pUndoGroup = new SdrUndoGroup(rMod); + } + + pUndoGroup->AddAction(rMod.GetSdrUndoFactory().CreateUndoPageRemoveMasterPage(*pDrawPage)); + } + } + } + } +} + +SdrUndoDelPage::~SdrUndoDelPage() +{ + if (pUndoGroup!=NULL) { + delete pUndoGroup; + } +} + +void SdrUndoDelPage::Undo() +{ + ImpInsertPage(nPageNum); + if (pUndoGroup!=NULL) { // MasterPage-Beziehungen wiederherstellen + pUndoGroup->Undo(); + } + DBG_ASSERT(bItsMine,"UndoDeletePage: mrPage gehoert nicht der UndoAction"); + bItsMine=FALSE; +} + +void SdrUndoDelPage::Redo() +{ + ImpRemovePage(nPageNum); + // Die MasterPage-Beziehungen werden ggf. von selbst geloesst + DBG_ASSERT(!bItsMine,"RedoDeletePage: mrPage gehoert bereits der UndoAction"); + bItsMine=TRUE; +} + +XubString SdrUndoDelPage::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoDelPage,aStr,0,FALSE); + return aStr; +} + +XubString SdrUndoDelPage::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoDelPage,aStr,0,FALSE); + return aStr; +} + +void SdrUndoDelPage::SdrRepeat(SdrView& /*rView*/) +{ +} + +bool SdrUndoDelPage::CanSdrRepeat(SdrView& /*rView*/) const +{ + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoNewPage::Undo() +{ + ImpRemovePage(nPageNum); + DBG_ASSERT(!bItsMine,"UndoNewPage: mrPage gehoert bereits der UndoAction"); + bItsMine=TRUE; +} + +void SdrUndoNewPage::Redo() +{ + ImpInsertPage(nPageNum); + DBG_ASSERT(bItsMine,"RedoNewPage: mrPage gehoert nicht der UndoAction"); + bItsMine=FALSE; +} + +XubString SdrUndoNewPage::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoNewPage,aStr,0,FALSE); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +XubString SdrUndoCopyPage::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoCopPage,aStr,0,FALSE); + return aStr; +} + +XubString SdrUndoCopyPage::GetSdrRepeatComment(SdrView& /*rView*/) const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoCopPage,aStr,0,FALSE); + return aStr; +} + +void SdrUndoCopyPage::SdrRepeat(SdrView& /*rView*/) +{ + +} + +bool SdrUndoCopyPage::CanSdrRepeat(SdrView& /*rView*/) const +{ + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrUndoSetPageNum::Undo() +{ + ImpMovePage(nNewPageNum,nOldPageNum); +} + +void SdrUndoSetPageNum::Redo() +{ + ImpMovePage(nOldPageNum,nNewPageNum); +} + +XubString SdrUndoSetPageNum::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoMovPage,aStr,0,FALSE); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@ @@ @@@@ @@@@ @@@@@@ @@@@@ @@@@@ @@@@@ @@@@ @@@@ @@@@@ @@@@ +// @@@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@@@@@@ @@@@@@ @@@@ @@ @@@@ @@@@@ @@@@@ @@@@@@ @@ @@@ @@@@ @@@@ +// @@ @ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@@@ @@ @@@@@ @@ @@ @@ @@ @@ @@@@@ @@@@@ @@@@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoPageMasterPage::SdrUndoPageMasterPage(SdrPage& rChangedPage) +: SdrUndoPage(rChangedPage), + mbOldHadMasterPage(mrPage.TRG_HasMasterPage()) +{ + // get current state from page + if(mbOldHadMasterPage) + { + maOldSet = mrPage.TRG_GetMasterPageVisibleLayers(); + maOldMasterPageNumber = mrPage.TRG_GetMasterPage().GetPageNum(); + } +} + +SdrUndoPageMasterPage::~SdrUndoPageMasterPage() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoPageRemoveMasterPage::SdrUndoPageRemoveMasterPage(SdrPage& rChangedPage) +: SdrUndoPageMasterPage(rChangedPage) +{ +} + +void SdrUndoPageRemoveMasterPage::Undo() +{ + if(mbOldHadMasterPage) + { + mrPage.TRG_SetMasterPage(*mrPage.GetModel()->GetMasterPage(maOldMasterPageNumber)); + mrPage.TRG_SetMasterPageVisibleLayers(maOldSet); + } +} + +void SdrUndoPageRemoveMasterPage::Redo() +{ + mrPage.TRG_ClearMasterPage(); +} + +XubString SdrUndoPageRemoveMasterPage::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoDelPageMasterDscr,aStr,0,FALSE); + return aStr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrUndoPageChangeMasterPage::SdrUndoPageChangeMasterPage(SdrPage& rChangedPage) +: SdrUndoPageMasterPage(rChangedPage), + mbNewHadMasterPage(sal_False) +{ +} + +void SdrUndoPageChangeMasterPage::Undo() +{ + // remember values from new page + if(mrPage.TRG_HasMasterPage()) + { + mbNewHadMasterPage = sal_True; + maNewSet = mrPage.TRG_GetMasterPageVisibleLayers(); + maNewMasterPageNumber = mrPage.TRG_GetMasterPage().GetPageNum(); + } + + // restore old values + if(mbOldHadMasterPage) + { + mrPage.TRG_ClearMasterPage(); + mrPage.TRG_SetMasterPage(*mrPage.GetModel()->GetMasterPage(maOldMasterPageNumber)); + mrPage.TRG_SetMasterPageVisibleLayers(maOldSet); + } +} + +void SdrUndoPageChangeMasterPage::Redo() +{ + // restore new values + if(mbNewHadMasterPage) + { + mrPage.TRG_ClearMasterPage(); + mrPage.TRG_SetMasterPage(*mrPage.GetModel()->GetMasterPage(maNewMasterPageNumber)); + mrPage.TRG_SetMasterPageVisibleLayers(maNewSet); + } +} + +XubString SdrUndoPageChangeMasterPage::GetComment() const +{ + XubString aStr; + ImpTakeDescriptionStr(STR_UndoChgPageMasterDscr,aStr,0,FALSE); + return aStr; +} + +/////////////////////////////////////////////////////////////////////// +SdrUndoFactory::~SdrUndoFactory(){} +// shapes +SdrUndoAction* SdrUndoFactory::CreateUndoMoveObject( SdrObject& rObject ) +{ + return new SdrUndoMoveObj( rObject ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoMoveObject( SdrObject& rObject, const Size& rDist ) +{ + return new SdrUndoMoveObj( rObject, rDist ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoGeoObject( SdrObject& rObject ) +{ + return new SdrUndoGeoObj( rObject ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoAttrObject( SdrObject& rObject, bool bStyleSheet1, bool bSaveText ) +{ + return new SdrUndoAttrObj( rObject, bStyleSheet1 ? TRUE : FALSE, bSaveText ? TRUE : FALSE ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoRemoveObject( SdrObject& rObject, bool bOrdNumDirect ) +{ + return new SdrUndoRemoveObj( rObject, bOrdNumDirect ? TRUE : FALSE ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoInsertObject( SdrObject& rObject, bool bOrdNumDirect ) +{ + return new SdrUndoInsertObj( rObject, bOrdNumDirect ? TRUE : FALSE ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoDeleteObject( SdrObject& rObject, bool bOrdNumDirect ) +{ + return new SdrUndoDelObj( rObject, bOrdNumDirect ? TRUE : FALSE ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoNewObject( SdrObject& rObject, bool bOrdNumDirect ) +{ + return new SdrUndoNewObj( rObject, bOrdNumDirect ? TRUE : FALSE ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoCopyObject( SdrObject& rObject, bool bOrdNumDirect ) +{ + return new SdrUndoCopyObj( rObject, bOrdNumDirect ? TRUE : FALSE ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoObjectOrdNum( SdrObject& rObject, sal_uInt32 nOldOrdNum1, sal_uInt32 nNewOrdNum1) +{ + return new SdrUndoObjOrdNum( rObject, nOldOrdNum1, nNewOrdNum1 ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject, bool bOrdNumDirect ) +{ + return new SdrUndoReplaceObj( rOldObject, rNewObject, bOrdNumDirect ? TRUE : FALSE ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoObjectLayerChange( SdrObject& rObject, SdrLayerID aOldLayer, SdrLayerID aNewLayer ) +{ + return new SdrUndoObjectLayerChange( rObject, aOldLayer, aNewLayer ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoObjectSetText( SdrObject& rNewObj, sal_Int32 nText ) +{ + return new SdrUndoObjSetText( rNewObj, nText ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoObjectStrAttr( SdrObject& rObject, + SdrUndoObjStrAttr::ObjStrAttrType eObjStrAttrType, + String sOldStr, + String sNewStr ) +{ + return new SdrUndoObjStrAttr( rObject, eObjStrAttrType, sOldStr, sNewStr ); +} + + +// layer +SdrUndoAction* SdrUndoFactory::CreateUndoNewLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel) +{ + return new SdrUndoNewLayer( nLayerNum, rNewLayerAdmin, rNewModel ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoDeleteLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel) +{ + return new SdrUndoDelLayer( nLayerNum, rNewLayerAdmin, rNewModel ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoMoveLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel, sal_uInt16 nNeuPos1) +{ + return new SdrUndoMoveLayer( nLayerNum, rNewLayerAdmin, rNewModel, nNeuPos1 ); +} + +// page +SdrUndoAction* SdrUndoFactory::CreateUndoDeletePage(SdrPage& rPage) +{ + return new SdrUndoDelPage( rPage ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoNewPage(SdrPage& rPage) +{ + return new SdrUndoNewPage( rPage ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoCopyPage(SdrPage& rPage) +{ + return new SdrUndoCopyPage( rPage ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoSetPageNum(SdrPage& rNewPg, sal_uInt16 nOldPageNum1, sal_uInt16 nNewPageNum1) +{ + return new SdrUndoSetPageNum( rNewPg, nOldPageNum1, nNewPageNum1 ); +} + // master page +SdrUndoAction* SdrUndoFactory::CreateUndoPageRemoveMasterPage(SdrPage& rChangedPage) +{ + return new SdrUndoPageRemoveMasterPage( rChangedPage ); +} + +SdrUndoAction* SdrUndoFactory::CreateUndoPageChangeMasterPage(SdrPage& rChangedPage) +{ + return new SdrUndoPageChangeMasterPage(rChangedPage); +} + +// eof diff --git a/svx/source/svdraw/svdview.cxx b/svx/source/svdraw/svdview.cxx new file mode 100644 index 000000000000..7a4305b9581f --- /dev/null +++ b/svx/source/svdraw/svdview.cxx @@ -0,0 +1,1606 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <editeng/eeitem.hxx> + +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include <svx/svdpagv.hxx> +#include <svx/svdmrkv.hxx> +#include <svx/svdedxv.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdopath.hxx> // fuer GetContext +#include <svx/svdograf.hxx> // fuer GetContext +#include <svx/svdomedia.hxx> // fuer GetContext +#include <svx/svdetc.hxx> // Fuer SdrEngineDefaults + +#ifdef DBG_UTIL +#include <svdibrow.hxx> +#endif + +#include "svx/svdoutl.hxx" +#include "svx/svdview.hxx" +#include "editeng/editview.hxx" // fuer GetField +#include "editeng/flditem.hxx" // fuer URLField +#include "svx/obj3d.hxx" +#include "svx/svddrgmt.hxx" +#include "svx/svdoutl.hxx" +#include "svx/svdotable.hxx" +#include <tools/tenccvt.hxx> +#include <svx/sdr/overlay/overlaypolypolygon.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <sdrpaintwindow.hxx> +#include <svx/sdrpagewindow.hxx> +#include <svx/sdrhittesthelper.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrViewEvent::SdrViewEvent() +: pHdl(NULL), + pObj(NULL), + pRootObj(NULL), + pPV(NULL), + pURLField(NULL), + eHit(SDRHIT_NONE), + eEvent(SDREVENT_NONE), + eHdlKind(HDL_MOVE), + eEndCreateCmd(SDRCREATE_NEXTPOINT), + nMouseClicks(0), + nMouseMode(0), + nMouseCode(0), + nHlplIdx(0), + nGlueId(0), + bMouseDown(FALSE), + bMouseUp(FALSE), + bDoubleHdlSize(FALSE), + bIsAction(FALSE), + bIsTextEdit(FALSE), + bTextEditHit(FALSE), + bAddMark(FALSE), + bUnmark(FALSE), + bPrevNextMark(FALSE), + bMarkPrev(FALSE), + bInsPointNewObj(FALSE), + bDragWithCopy(FALSE), + bCaptureMouse(FALSE), + bReleaseMouse(FALSE) +{ +} + +SdrViewEvent::~SdrViewEvent() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// helper class for all D&D overlays + +void SdrDropMarkerOverlay::ImplCreateOverlays(const SdrView& rView, const basegfx::B2DPolyPolygon& rPolyPolygon) +{ + for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) + { + SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); + ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); + + if(pTargetOverlay) + { + ::sdr::overlay::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped( + rPolyPolygon); + pTargetOverlay->add(*pNew); + maObjects.append(*pNew); + } + } +} + +SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const SdrObject& rObject) +{ + ImplCreateOverlays(rView, rObject.TakeXorPoly()); +} + +SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const Rectangle& rRectangle) +{ + basegfx::B2DPolygon aB2DPolygon; + aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top())); + aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top())); + aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom())); + aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom())); + aB2DPolygon.setClosed(true); + + basegfx::B2DPolyPolygon aB2DPolyPolygon; + aB2DPolyPolygon.append(aB2DPolygon); + + ImplCreateOverlays(rView, aB2DPolyPolygon); +} + +SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const Point& rStart, const Point& rEnd) +{ + basegfx::B2DPolygon aB2DPolygon; + aB2DPolygon.append(basegfx::B2DPoint(rStart.X(), rStart.Y())); + aB2DPolygon.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y())); + aB2DPolygon.setClosed(true); + + basegfx::B2DPolyPolygon aB2DPolyPolygon; + aB2DPolyPolygon.append(aB2DPolygon); + + ImplCreateOverlays(rView, aB2DPolyPolygon); +} + +SdrDropMarkerOverlay::~SdrDropMarkerOverlay() +{ + // The OverlayObjects are cleared using the destructor of OverlayObjectList. + // That destructor calls clear() at the list which removes all objects from the + // OverlayManager and deletes them. +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// @@ @@ @@ @@@@@ @@ @@ +// @@ @@ @@ @@ @@ @@ +// @@ @@ @@ @@ @@ @ @@ +// @@@@@ @@ @@@@ @@@@@@@ +// @@@ @@ @@ @@@@@@@ +// @@@ @@ @@ @@@ @@@ +// @ @@ @@@@@ @@ @@ +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(SdrView,SdrCreateView); + +SdrView::SdrView(SdrModel* pModel1, OutputDevice* pOut) +: SdrCreateView(pModel1,pOut), + bNoExtendedMouseDispatcher(FALSE), + bNoExtendedKeyDispatcher(FALSE), + bNoExtendedCommandDispatcher(FALSE), + mbMasterPagePaintCaching(sal_False) +{ + bTextEditOnObjectsWithoutTextIfTextTool=FALSE; + + maAccessibilityOptions.AddListener(this); + + onAccessibilityOptionsChanged(); +} + +SdrView::~SdrView() +{ + maAccessibilityOptions.RemoveListener(this); +} + +BOOL SdrView::KeyInput(const KeyEvent& rKEvt, Window* pWin) +{ + SetActualWin(pWin); + BOOL bRet=SdrCreateView::KeyInput(rKEvt,pWin); + if (!bRet && !IsExtendedKeyInputDispatcherEnabled()) { + bRet=TRUE; + switch (rKEvt.GetKeyCode().GetFullFunction()) { + case KEYFUNC_CUT : Cut(); break; + case KEYFUNC_COPY : Yank(); break; + case KEYFUNC_PASTE : Paste(pWin); break; + case KEYFUNC_DELETE: DeleteMarked(); break; + case KEYFUNC_UNDO: pMod->Undo(); break; + case KEYFUNC_REDO: pMod->Redo(); break; + case KEYFUNC_REPEAT: pMod->Repeat(*this); break; + default: { + switch (rKEvt.GetKeyCode().GetFullCode()) { + case KEY_ESCAPE: { + if (IsTextEdit()) SdrEndTextEdit(); + if (IsAction()) BrkAction(); + if (pWin!=NULL) pWin->ReleaseMouse(); + } break; + case KEY_DELETE: DeleteMarked(); break; + case KEY_CUT: case KEY_DELETE+KEY_SHIFT: Cut(); break; + case KEY_COPY: case KEY_INSERT+KEY_MOD1: Yank(); break; + case KEY_PASTE: case KEY_INSERT+KEY_SHIFT: Paste(pWin); break; + case KEY_UNDO: case KEY_BACKSPACE+KEY_MOD2: pMod->Undo(); break; + case KEY_BACKSPACE+KEY_MOD2+KEY_SHIFT: pMod->Redo(); break; + case KEY_REPEAT: case KEY_BACKSPACE+KEY_MOD2+KEY_MOD1: pMod->Repeat(*this); break; + case KEY_MOD1+KEY_A: MarkAll(); break; + default: bRet=FALSE; + } // switch + } + } // switch + if (bRet && pWin!=NULL) { + pWin->SetPointer(GetPreferedPointer( + pWin->PixelToLogic(pWin->ScreenToOutputPixel( pWin->GetPointerPosPixel() ) ), + pWin, + rKEvt.GetKeyCode().GetModifier())); + } + } + return bRet; +} + +BOOL SdrView::MouseButtonDown(const MouseEvent& rMEvt, Window* pWin) +{ + SetActualWin(pWin); + if (rMEvt.IsLeft()) aDragStat.SetMouseDown(TRUE); + BOOL bRet=SdrCreateView::MouseButtonDown(rMEvt,pWin); + if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) { + SdrViewEvent aVEvt; + PickAnything(rMEvt,SDRMOUSEBUTTONDOWN,aVEvt); + bRet=DoMouseEvent(aVEvt); + } + return bRet; +} + +BOOL SdrView::MouseButtonUp(const MouseEvent& rMEvt, Window* pWin) +{ + SetActualWin(pWin); + if (rMEvt.IsLeft()) aDragStat.SetMouseDown(FALSE); + BOOL bAction=IsAction(); + BOOL bRet=!bAction && SdrCreateView::MouseButtonUp(rMEvt,pWin); + if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) { + SdrViewEvent aVEvt; + PickAnything(rMEvt,SDRMOUSEBUTTONUP,aVEvt); + bRet=DoMouseEvent(aVEvt); + } + return bRet; +} + +BOOL SdrView::MouseMove(const MouseEvent& rMEvt, Window* pWin) +{ + SetActualWin(pWin); + aDragStat.SetMouseDown(rMEvt.IsLeft()); + BOOL bRet=SdrCreateView::MouseMove(rMEvt,pWin); + if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) { + SdrViewEvent aVEvt; + PickAnything(rMEvt,SDRMOUSEMOVE,aVEvt); + if (DoMouseEvent(aVEvt)) bRet=TRUE; + } + + // #87792# Removed code which did let the mouse snap on object + // points + + return bRet; +} + +BOOL SdrView::Command(const CommandEvent& rCEvt, Window* pWin) +{ + SetActualWin(pWin); + BOOL bRet=SdrCreateView::Command(rCEvt,pWin); + return bRet; +} + +/* new interface src537 */ +BOOL SdrView::GetAttributes(SfxItemSet& rTargetSet, BOOL bOnlyHardAttr) const +{ + return SdrCreateView::GetAttributes(rTargetSet, bOnlyHardAttr); +} + +SfxStyleSheet* SdrView::GetStyleSheet() const +{ + //BOOL bOk=FALSE; + return SdrCreateView::GetStyleSheet(); //bOk); +} + +SdrHitKind SdrView::PickAnything(const MouseEvent& rMEvt, USHORT nEventKind, SdrViewEvent& rVEvt) const +{ + rVEvt.bMouseDown=nEventKind==SDRMOUSEBUTTONDOWN; + rVEvt.bMouseUp=nEventKind==SDRMOUSEBUTTONUP; + rVEvt.nMouseClicks=rMEvt.GetClicks(); + rVEvt.nMouseMode=rMEvt.GetMode(); + rVEvt.nMouseCode=rMEvt.GetButtons() | rMEvt.GetModifier(); + const OutputDevice* pOut=pActualOutDev; + if (pOut==NULL) + { + pOut = GetFirstOutputDevice(); + //pOut=GetWin(0); + } + Point aPnt(rMEvt.GetPosPixel()); + if (pOut!=NULL) aPnt=pOut->PixelToLogic(aPnt); + rVEvt.aLogicPos=aPnt; + return PickAnything(aPnt,rVEvt); +} + +// Mit der Maus draggen (Move) +// Beispiel beim erzeugen eines Rechtecks. MouseDown muss ohne +// ModKey erfolgen, weil sonst i.d.R. Markieren forciert wird (s.u.) +// Drueckt man dann beim MouseMove gleichzeitig Shift, Ctrl, und Alt, +// so erzeugt man ein zentrisches Quadrat ohne Fang. +// Die Doppelbelegung von Ortho und Shift stellt i.d.R. kein Problem dar, +// da sich beides meisst gegenseitig ausschliesst. Einzig Shear (das beim +// Verzerren, nicht dass beim Drehen) beruecksichtigt beides gleichzeitig. +// Dass muss der Anwender erstmal noch umschiffen (z.B. mit einer Hilfslinie). +#define MODKEY_NoSnap bCtrl /* Fang temporaer aus */ +#define MODKEY_Ortho bShift /* na eben ortho */ +#define MODKEY_Center bAlt /* Zentrisch erzeugen/resizen */ +#define MODKEY_AngleSnap bShift +#define MODKEY_CopyDrag bCtrl /* Draggen mit kopieren */ + +// irgendwo hinklicken (MouseDown) +#define MODKEY_PolyPoly bAlt /* Neues Poly bei InsPt und bei Create */ +#define MODKEY_MultiMark bShift /* MarkObj ohne vorher UnmarkAll */ +#define MODKEY_Unmark bAlt /* Unmark durch Rahmenaufziehen */ +#define MODKEY_ForceMark bCtrl /* Rahmenaufziehen erzwingen, auch wenn Obj an MausPos */ +#define MODKEY_DeepMark bAlt /* MarkNextObj */ +#define MODKEY_DeepBackw bShift /* MarkNextObj rueckwaerts */ + +SdrHitKind SdrView::PickAnything(const Point& rLogicPos, SdrViewEvent& rVEvt) const +{ + const OutputDevice* pOut=pActualOutDev; + if (pOut==NULL) + { + pOut = GetFirstOutputDevice(); + //pOut=GetWin(0); + } + + // #i73628# Use a non-changeable copy of he logic pos + const Point aLocalLogicPosition(rLogicPos); + + BOOL bEditMode=IsEditMode(); + BOOL bPointMode=bEditMode && HasMarkablePoints(); + BOOL bGluePointMode=IsGluePointEditMode(); + BOOL bInsPolyPt=bPointMode && IsInsObjPointMode() && IsInsObjPointPossible(); + BOOL bInsGluePt=bGluePointMode && IsInsGluePointMode() && IsInsGluePointPossible(); + BOOL bIsTextEdit=IsTextEdit(); + BOOL bTextEditHit=IsTextEditHit(aLocalLogicPosition,0/*nHitTolLog*/); + BOOL bTextEditSel=IsTextEditInSelectionMode(); + BOOL bShift=(rVEvt.nMouseCode & KEY_SHIFT) !=0; + BOOL bCtrl=(rVEvt.nMouseCode & KEY_MOD1) !=0; + BOOL bAlt=(rVEvt.nMouseCode & KEY_MOD2) !=0; + SdrHitKind eHit=SDRHIT_NONE; + SdrHdl* pHdl=pOut!=NULL && !bTextEditSel ? PickHandle(aLocalLogicPosition) : NULL; + SdrPageView* pPV=NULL; + SdrObject* pObj=NULL; + SdrObject* pHitObj=NULL; + USHORT nHitPassNum=0; + USHORT nHlplIdx=0; + USHORT nGlueId=0; + BOOL bUnmarkedObjHit=FALSE; + if (bTextEditHit || bTextEditSel) + { + eHit=SDRHIT_TEXTEDIT; + bTextEditHit=TRUE; + } + else if (pHdl!=NULL) + { + eHit=SDRHIT_HANDLE; // Handle getroffen hat hoechste Prioritaet + } + else if (bEditMode && IsHlplVisible() && IsHlplFront() && pOut!=NULL && PickHelpLine(aLocalLogicPosition,nHitTolLog,*pOut,nHlplIdx,pPV)) + { + eHit=SDRHIT_HELPLINE; // Hilfslinie im Vordergrund getroffen zum verschieben + } + else if (bGluePointMode && PickGluePoint(aLocalLogicPosition,pObj,nGlueId,pPV)) + { + eHit=SDRHIT_GLUEPOINT; // nichtmarkierter Klebepunkt getroffen + } + else if (PickObj(aLocalLogicPosition,nHitTolLog,pHitObj,pPV,SDRSEARCH_DEEP|SDRSEARCH_MARKED,&pObj,NULL,&nHitPassNum)) + { + eHit=SDRHIT_MARKEDOBJECT; + ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( pObj ); + if( pTableObj ) + { + sal_Int32 nX = 0, nY = 0; + switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY, 0 ) ) + { + case sdr::table::SDRTABLEHIT_CELL: + eHit = SDRHIT_CELL; + break; + case sdr::table::SDRTABLEHIT_CELLTEXTAREA: + eHit = SDRHIT_TEXTEDITOBJ; + break; + default: + break; + } + } + } + else if (PickObj(aLocalLogicPosition,nHitTolLog,pHitObj,pPV,SDRSEARCH_DEEP|/*SDRSEARCH_TESTMARKABLE|*/SDRSEARCH_ALSOONMASTER|SDRSEARCH_WHOLEPAGE,&pObj,NULL,&nHitPassNum)) + { + // MasterPages und WholePage fuer Macro und URL + eHit=SDRHIT_UNMARKEDOBJECT; + ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( pObj ); + if( pTableObj ) + { + sal_Int32 nX = 0, nY = 0; + switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY, 0 ) ) + { + case sdr::table::SDRTABLEHIT_CELL: + eHit = SDRHIT_CELL; + break; + case sdr::table::SDRTABLEHIT_CELLTEXTAREA: + eHit = SDRHIT_TEXTEDITOBJ; + break; + default: + break; + } + } + bUnmarkedObjHit=TRUE; + } + else if (bEditMode && IsHlplVisible() && !IsHlplFront() && pOut!=NULL && PickHelpLine(aLocalLogicPosition,nHitTolLog,*pOut,nHlplIdx,pPV)) + { + eHit=SDRHIT_HELPLINE; // Hilfslinie im Vordergrund getroffen zum verschieben + } + if (IsMacroMode() && eHit==SDRHIT_UNMARKEDOBJECT) + { + bool bRoot=pObj->HasMacro(); + BOOL bDeep=pObj!=pHitObj && pHitObj->HasMacro(); + BOOL bMid=FALSE; // Gruppierte Gruppe mit Macro getroffen? + SdrObject* pMidObj=NULL; + if (pObj!=pHitObj) + { + SdrObject* pObjTmp=NULL; + pObjTmp=pHitObj->GetUpGroup(); + if (pObjTmp==pObj) pObjTmp=NULL; + while (pObjTmp!=NULL) + { + if (pObjTmp->HasMacro()) + { + bMid=TRUE; + pMidObj=pObjTmp; + } + pObjTmp=pObjTmp->GetUpGroup(); + if (pObjTmp==pObj) pObjTmp=NULL; + } + } + + if (bDeep || bMid || bRoot) + { + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=aLocalLogicPosition; + aHitRec.aDownPos=aLocalLogicPosition; + aHitRec.nTol=nHitTolLog; + aHitRec.pVisiLayer=&pPV->GetVisibleLayers(); + aHitRec.pPageView=pPV; + if (bDeep) bDeep=pHitObj->IsMacroHit(aHitRec); + if (bMid ) bMid =pMidObj->IsMacroHit(aHitRec); + if (bRoot) bRoot=pObj->IsMacroHit(aHitRec); + if (bRoot || bMid || bDeep) + { + // Prio: 1.Root, 2.Mid, 3.Deep + rVEvt.pRootObj=pObj; + if (!bRoot) pObj=pMidObj; + if (!bRoot && !bMid) pObj=pHitObj; + eHit=SDRHIT_MACRO; + } + } + } + // auf URL-Field checken + if (IsMacroMode() && eHit==SDRHIT_UNMARKEDOBJECT) + { + SdrTextObj* pTextObj=PTR_CAST(SdrTextObj,pHitObj); + if (pTextObj!=NULL && pTextObj->HasText()) + { + bool bTEHit(pPV && + SdrObjectPrimitiveHit(*pTextObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true)); + + if (bTEHit) + { + Rectangle aTextRect; + Rectangle aAnchor; + SdrOutliner* pOutliner = &pTextObj->ImpGetDrawOutliner(); + if( pTextObj->GetModel() ) + pOutliner = &pTextObj->GetModel()->GetHitTestOutliner(); + + pTextObj->TakeTextRect( *pOutliner, aTextRect, FALSE, &aAnchor, FALSE ); + + // #i73628# Use a text-relative position for hit test in hit test outliner + Point aTemporaryTextRelativePosition(aLocalLogicPosition - aTextRect.TopLeft()); + + // FitToSize berueksichtigen + SdrFitToSizeType eFit=pTextObj->GetFitToSize(); + BOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); + if (bFitToSize) { + Fraction aX(aTextRect.GetWidth()-1,aAnchor.GetWidth()-1); + Fraction aY(aTextRect.GetHeight()-1,aAnchor.GetHeight()-1); + ResizePoint(aTemporaryTextRelativePosition,Point(),aX,aY); + } + // Drehung berueksichtigen + const GeoStat& rGeo=pTextObj->GetGeoStat(); + if (rGeo.nDrehWink!=0) RotatePoint(aTemporaryTextRelativePosition,Point(),-rGeo.nSin,rGeo.nCos); // -sin fuer Unrotate + // Laufschrift berueksichtigen fehlt noch ... + if(pActualOutDev && pActualOutDev->GetOutDevType() == OUTDEV_WINDOW) + { + OutlinerView aOLV(pOutliner, (Window*)pActualOutDev); + const EditView& aEV=aOLV.GetEditView(); + const SvxFieldItem* pItem=aEV.GetField(aTemporaryTextRelativePosition); + if (pItem!=NULL) { + const SvxFieldData* pFld=pItem->GetField(); + const SvxURLField* pURL=PTR_CAST(SvxURLField,pFld); + if (pURL!=NULL) { + eHit=SDRHIT_URLFIELD; + rVEvt.pURLField=pURL; + } + } + } + } + } + } + + if (nHitPassNum==SDRSEARCHPASS_DIRECT && + (eHit==SDRHIT_MARKEDOBJECT || eHit==SDRHIT_UNMARKEDOBJECT) && + (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj->HasTextEdit()) + { + // Ringsum die TextEditArea ein Rand zum Selektieren ohne Textedit + Rectangle aBoundRect(pHitObj->GetCurrentBoundRect()); + + // #105130# Force to SnapRect when Fontwork + if(pHitObj->ISA(SdrTextObj) && ((SdrTextObj*)pHitObj)->IsFontwork()) + { + aBoundRect = pHitObj->GetSnapRect(); + } + + // #105130# Old test for hit on BoundRect is completely wrong + // and never worked, doing it new here. + sal_Int32 nTolerance(nHitTolLog); + sal_Bool bBoundRectHit(sal_False); + + if(pOut) + { + nTolerance = pOut->PixelToLogic(Size(2, 0)).Width(); + } + + if( (aLocalLogicPosition.X() >= aBoundRect.Left() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Left() + nTolerance) + || (aLocalLogicPosition.X() >= aBoundRect.Right() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Right() + nTolerance) + || (aLocalLogicPosition.Y() >= aBoundRect.Top() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Top() + nTolerance) + || (aLocalLogicPosition.Y() >= aBoundRect.Bottom() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Bottom() + nTolerance)) + { + bBoundRectHit = sal_True; + } + + if(!bBoundRectHit) + { + bool bTEHit(pPV && + SdrObjectPrimitiveHit(*pHitObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true)); + + // TextEdit an Objekten im gesperrten Layer + if (pPV->GetLockedLayers().IsSet(pHitObj->GetLayer())) + { + bTEHit=FALSE; + } + + if (bTEHit) + { + rVEvt.pRootObj=pObj; + pObj=pHitObj; + eHit=SDRHIT_TEXTEDITOBJ; + } + } + } + if (nHitPassNum!=SDRSEARCHPASS_DIRECT && eHit==SDRHIT_UNMARKEDOBJECT) { + eHit=SDRHIT_NONE; + pObj=NULL; + pPV=NULL; + } + BOOL bMouseLeft=(rVEvt.nMouseCode&MOUSE_LEFT)!=0; + BOOL bMouseRight=(rVEvt.nMouseCode&MOUSE_RIGHT)!=0; + BOOL bMouseDown=rVEvt.bMouseDown; + BOOL bMouseUp=rVEvt.bMouseUp; + SdrEventKind eEvent=SDREVENT_NONE; + BOOL bIsAction=IsAction(); + + if (bIsAction) + { + if (bMouseDown) + { + if (bMouseRight) eEvent=SDREVENT_BCKACTION; + } + else if (bMouseUp) + { + if (bMouseLeft) + { + eEvent=SDREVENT_ENDACTION; + if (IsDragObj()) + { + eEvent=SDREVENT_ENDDRAG; + rVEvt.bDragWithCopy=MODKEY_CopyDrag; + } + else if (IsCreateObj() || IsInsObjPoint()) + { + eEvent=IsCreateObj() ? SDREVENT_ENDCREATE : SDREVENT_ENDINSOBJPOINT; + rVEvt.eEndCreateCmd=SDRCREATE_NEXTPOINT; + if (MODKEY_PolyPoly) rVEvt.eEndCreateCmd=SDRCREATE_NEXTOBJECT; + if (rVEvt.nMouseClicks>1) rVEvt.eEndCreateCmd=SDRCREATE_FORCEEND; + } + else if (IsMarking()) + { + eEvent=SDREVENT_ENDMARK; + if (!aDragStat.IsMinMoved()) + { + eEvent=SDREVENT_BRKMARK; + rVEvt.bAddMark=MODKEY_MultiMark; + } + } + } + } + else + { + eEvent=SDREVENT_MOVACTION; + } + } + else if (eHit==SDRHIT_TEXTEDIT) + { + eEvent=SDREVENT_TEXTEDIT; + } + else if (bMouseDown && bMouseLeft) + { + if (rVEvt.nMouseClicks==2 && rVEvt.nMouseCode==MOUSE_LEFT && pObj!=NULL && pHitObj!=NULL && pHitObj->HasTextEdit() && eHit==SDRHIT_MARKEDOBJECT) + { + rVEvt.pRootObj=pObj; + pObj=pHitObj; + eEvent=SDREVENT_BEGTEXTEDIT; + } + else if (MODKEY_ForceMark && eHit!=SDRHIT_URLFIELD) + { + eEvent=SDREVENT_BEGMARK; // AddMark,Unmark */ + } + else if (eHit==SDRHIT_HELPLINE) + { + eEvent=SDREVENT_BEGDRAGHELPLINE; // nix weiter + } + else if (eHit==SDRHIT_GLUEPOINT) + { + eEvent=SDREVENT_MARKGLUEPOINT; // AddMark+Drag + rVEvt.bAddMark=MODKEY_MultiMark || MODKEY_DeepMark; // falls bei Deep nicht getroffen + } + else if (eHit==SDRHIT_HANDLE) + { + eEvent=SDREVENT_BEGDRAGOBJ; // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark + BOOL bGlue=pHdl->GetKind()==HDL_GLUE; + BOOL bPoly=!bGlue && IsPointMarkable(*pHdl); + BOOL bMarked=bGlue || bPoly && pHdl->IsSelected(); + if (bGlue || bPoly) + { + eEvent=bGlue ? SDREVENT_MARKGLUEPOINT : SDREVENT_MARKPOINT; + if (MODKEY_DeepMark) + { + rVEvt.bAddMark=TRUE; + rVEvt.bPrevNextMark=TRUE; + rVEvt.bMarkPrev=MODKEY_DeepBackw; + } + else if (MODKEY_MultiMark) + { + rVEvt.bAddMark=TRUE; + rVEvt.bUnmark=bMarked; // Toggle + if (bGlue) + { + pObj=pHdl->GetObj(); + nGlueId=(sal_uInt16)pHdl->GetObjHdlNum(); + } + } + else if (bMarked) + { + eEvent=SDREVENT_BEGDRAGOBJ; // MarkState nicht aendern, nur Drag + } + } + } + else if (bInsPolyPt && (MODKEY_PolyPoly || (!MODKEY_MultiMark && !MODKEY_DeepMark))) + { + eEvent=SDREVENT_BEGINSOBJPOINT; + rVEvt.bInsPointNewObj=MODKEY_PolyPoly; + } + else if (bInsGluePt && !MODKEY_MultiMark && !MODKEY_DeepMark) + { + eEvent=SDREVENT_BEGINSGLUEPOINT; + } + else if (eHit==SDRHIT_TEXTEDITOBJ) + { + eEvent=SDREVENT_BEGTEXTEDIT; // AddMark+Drag,DeepMark+Drag,Unmark + if (MODKEY_MultiMark || MODKEY_DeepMark) + { // falls bei Deep nicht getroffen + eEvent=SDREVENT_MARKOBJ; + } + } + else if (eHit==SDRHIT_MACRO) + { + eEvent=SDREVENT_BEGMACROOBJ; // AddMark+Drag + if (MODKEY_MultiMark || MODKEY_DeepMark) + { // falls bei Deep nicht getroffen + eEvent=SDREVENT_MARKOBJ; + } + } + else if (eHit==SDRHIT_URLFIELD) + { + eEvent=SDREVENT_EXECUTEURL; // AddMark+Drag + if (MODKEY_MultiMark || MODKEY_DeepMark) + { // falls bei Deep nicht getroffen + eEvent=SDREVENT_MARKOBJ; + } + } + else if (eHit==SDRHIT_MARKEDOBJECT) + { + eEvent=SDREVENT_BEGDRAGOBJ; // DeepMark+Drag,Unmark + + if (MODKEY_MultiMark || MODKEY_DeepMark) + { // falls bei Deep nicht getroffen + eEvent=SDREVENT_MARKOBJ; + } + } + else if (IsCreateMode()) + { + eEvent=SDREVENT_BEGCREATEOBJ; // Nix weiter + } + else if (eHit==SDRHIT_UNMARKEDOBJECT) + { + eEvent=SDREVENT_MARKOBJ; // AddMark+Drag + } + else + { + eEvent=SDREVENT_BEGMARK; + } + + if (eEvent==SDREVENT_MARKOBJ) + { + rVEvt.bAddMark=MODKEY_MultiMark || MODKEY_DeepMark; // falls bei Deep nicht getroffen + rVEvt.bPrevNextMark=MODKEY_DeepMark; + rVEvt.bMarkPrev=MODKEY_DeepMark && MODKEY_DeepBackw; + } + if (eEvent==SDREVENT_BEGMARK) + { + rVEvt.bAddMark=MODKEY_MultiMark; + rVEvt.bUnmark=MODKEY_Unmark; + } + } + rVEvt.bIsAction=bIsAction; + rVEvt.bIsTextEdit=bIsTextEdit; + rVEvt.bTextEditHit=bTextEditHit; + rVEvt.aLogicPos=aLocalLogicPosition; + rVEvt.pHdl=pHdl; + rVEvt.pObj=pObj; + if(rVEvt.pRootObj==NULL) + rVEvt.pRootObj=pObj; + rVEvt.pPV=pPV; + rVEvt.nHlplIdx=nHlplIdx; + rVEvt.nGlueId=nGlueId; + rVEvt.eHit=eHit; + rVEvt.eEvent=eEvent; + rVEvt.bCaptureMouse=bMouseLeft && bMouseDown && eEvent!=SDREVENT_NONE; + rVEvt.bReleaseMouse=bMouseLeft && bMouseUp; +#ifdef DGB_UTIL + if (rVEvt.pRootObj!=NULL) { + if (rVEvt.pRootObj->GetObjList()!=rVEvt.pPV->GetObjList()) { + DBG_ERROR("SdrView::PickAnything(): pRootObj->GetObjList()!=pPV->GetObjList() !"); + } + } +#endif + return eHit; +} + +BOOL SdrView::DoMouseEvent(const SdrViewEvent& rVEvt) +{ + BOOL bRet=FALSE; + SdrHitKind eHit=rVEvt.eHit; + Point aLogicPos(rVEvt.aLogicPos); + + BOOL bShift=(rVEvt.nMouseCode & KEY_SHIFT) !=0; + BOOL bCtrl=(rVEvt.nMouseCode & KEY_MOD1) !=0; + BOOL bAlt=(rVEvt.nMouseCode & KEY_MOD2) !=0; + BOOL bMouseLeft=(rVEvt.nMouseCode&MOUSE_LEFT)!=0; + //BOOL bMouseRight=(rVEvt.nMouseCode&MOUSE_RIGHT)!=0; + BOOL bMouseDown=rVEvt.bMouseDown; + BOOL bMouseUp=rVEvt.bMouseUp; + if (bMouseDown) { + if (bMouseLeft) aDragStat.SetMouseDown(TRUE); + } else if (bMouseUp) { + if (bMouseLeft) aDragStat.SetMouseDown(FALSE); + } else { // ansonsten MoueMove + aDragStat.SetMouseDown(bMouseLeft); + } + +#ifdef MODKEY_NoSnap + SetSnapEnabled(!MODKEY_NoSnap); +#endif +#ifdef MODKEY_Ortho + SetOrtho(MODKEY_Ortho!=IsOrthoDesired()); +#endif +#ifdef MODKEY_BigOrtho + SetBigOrtho(MODKEY_BigOrtho); +#endif +#ifdef MODKEY_AngleSnap + SetAngleSnapEnabled(MODKEY_AngleSnap); +#endif +#ifdef MODKEY_CopyDrag + SetDragWithCopy(MODKEY_CopyDrag); +#endif +#ifdef MODKEY_Center + SetCreate1stPointAsCenter(MODKEY_Center); + SetResizeAtCenter(MODKEY_Center); + SetCrookAtCenter(MODKEY_Center); +#endif + if (bMouseLeft && bMouseDown && rVEvt.bIsTextEdit && (eHit==SDRHIT_UNMARKEDOBJECT || eHit==SDRHIT_NONE)) { + SdrEndTextEdit(); // Danebengeklickt, Ende mit Edit + // pHdl ist dann ungueltig. Sollte aber egal sein, wein pHdl==NULL + // sein muesste (wg. eHit). + } + switch (rVEvt.eEvent) { + case SDREVENT_NONE: bRet=FALSE; break; + case SDREVENT_TEXTEDIT: bRet=FALSE; break; // Events an die OutlinerView werden hier nicht beruecksichtigt + case SDREVENT_MOVACTION: MovAction(aLogicPos); bRet=TRUE; break; + case SDREVENT_ENDACTION: EndAction(); bRet=TRUE; break; + case SDREVENT_BCKACTION: BckAction(); bRet=TRUE; break; + case SDREVENT_BRKACTION: BrkAction(); bRet=TRUE; break; + case SDREVENT_ENDMARK : EndAction(); bRet=TRUE; break; + case SDREVENT_BRKMARK : { + BrkAction(); + if (!MarkObj(aLogicPos,nHitTolLog,rVEvt.bAddMark)) { + // Kein Obj getroffen. Dann werden zuerst + // - Markierte Klebepunkte deselektiert + // - dann ggf. selektierte Polygonpunkte + // - und ansonsten Objekte + if (!rVEvt.bAddMark) UnmarkAll(); + } + bRet=TRUE; + } break; + case SDREVENT_ENDCREATE: { // ggf. MarkObj + SdrCreateCmd eCmd=SDRCREATE_NEXTPOINT; + if (MODKEY_PolyPoly) eCmd=SDRCREATE_NEXTOBJECT; + if (rVEvt.nMouseClicks>1) eCmd=SDRCREATE_FORCEEND; + if (!EndCreateObj(eCmd)) { // Event fuer Create nicht ausgewerten? -> Markieren + if (eHit==SDRHIT_UNMARKEDOBJECT || eHit==SDRHIT_TEXTEDIT) { + MarkObj(rVEvt.pRootObj,rVEvt.pPV); + if (eHit==SDRHIT_TEXTEDIT) + { + BOOL bRet2(pActualOutDev && OUTDEV_WINDOW == pActualOutDev->GetOutDevType() && + SdrBeginTextEdit(rVEvt.pObj, rVEvt.pPV, (Window*)pActualOutDev, sal_False, (SdrOutliner*)0L)); + + if(bRet2) + { + MouseEvent aMEvt(pActualOutDev->LogicToPixel(aLogicPos), + 1,rVEvt.nMouseMode,rVEvt.nMouseCode,rVEvt.nMouseCode); + + OutlinerView* pOLV=GetTextEditOutlinerView(); + if (pOLV!=NULL) { + pOLV->MouseButtonDown(aMEvt); // Event an den Outliner, aber ohne Doppelklick + pOLV->MouseButtonUp(aMEvt); // Event an den Outliner, aber ohne Doppelklick + } + } + } + bRet=TRUE; // Obj markiert und ggf. TextEdit gestartet + } else bRet=FALSE; // Create abgebrochen, sonst nix weiter. + } else bRet=TRUE; // EndCreate mit TRUE returniert + } break; + case SDREVENT_ENDDRAG: { + bRet=EndDragObj(IsDragWithCopy()); + ForceMarkedObjToAnotherPage(); // Undo+Klammerung fehlt noch !!! + } break; + case SDREVENT_MARKOBJ: { // + ggf. BegDrag + if (!rVEvt.bAddMark) UnmarkAllObj(); + BOOL bUnmark=rVEvt.bUnmark; + if (rVEvt.bPrevNextMark) { + bRet=MarkNextObj(aLogicPos,nHitTolLog,rVEvt.bMarkPrev); + } else { + SortMarkedObjects(); + ULONG nAnz0=GetMarkedObjectCount(); + bRet=MarkObj(aLogicPos,nHitTolLog,rVEvt.bAddMark); + SortMarkedObjects(); + ULONG nAnz1=GetMarkedObjectCount(); + bUnmark=nAnz1<nAnz0; + } + if (!bUnmark) { + BegDragObj(aLogicPos,NULL,(SdrHdl*)NULL,nMinMovLog); + bRet=TRUE; + } + } break; + case SDREVENT_MARKPOINT: { // + ggf. BegDrag + if (!rVEvt.bAddMark) UnmarkAllPoints(); + if (rVEvt.bPrevNextMark) { + bRet=MarkNextPoint(aLogicPos,rVEvt.bMarkPrev); + } else { + bRet=MarkPoint(*rVEvt.pHdl,rVEvt.bUnmark); + } + if (!rVEvt.bUnmark && !rVEvt.bPrevNextMark) { + BegDragObj(aLogicPos,NULL,rVEvt.pHdl,nMinMovLog); + bRet=TRUE; + } + } break; + case SDREVENT_MARKGLUEPOINT: { // + ggf. BegDrag + if (!rVEvt.bAddMark) UnmarkAllGluePoints(); + if (rVEvt.bPrevNextMark) { + bRet=MarkNextGluePoint(aLogicPos,rVEvt.bMarkPrev); + } else { + bRet=MarkGluePoint(rVEvt.pObj,rVEvt.nGlueId,rVEvt.pPV,rVEvt.bUnmark); + } + if (!rVEvt.bUnmark && !rVEvt.bPrevNextMark) { + SdrHdl* pHdl=GetGluePointHdl(rVEvt.pObj,rVEvt.nGlueId); + BegDragObj(aLogicPos,NULL,pHdl,nMinMovLog); + bRet=TRUE; + } + } break; + case SDREVENT_BEGMARK: bRet=BegMark(aLogicPos,rVEvt.bAddMark,rVEvt.bUnmark); break; + case SDREVENT_BEGINSOBJPOINT: bRet = BegInsObjPoint(aLogicPos, MODKEY_PolyPoly); break; + case SDREVENT_ENDINSOBJPOINT: { + SdrCreateCmd eCmd=SDRCREATE_NEXTPOINT; + if (MODKEY_PolyPoly) eCmd=SDRCREATE_NEXTOBJECT; + if (rVEvt.nMouseClicks>1) eCmd=SDRCREATE_FORCEEND; + EndInsObjPoint(eCmd); + bRet=TRUE; + } break; + case SDREVENT_BEGINSGLUEPOINT: bRet=BegInsGluePoint(aLogicPos); break; + case SDREVENT_BEGDRAGHELPLINE: bRet=BegDragHelpLine(rVEvt.nHlplIdx,rVEvt.pPV); break; + case SDREVENT_BEGDRAGOBJ: bRet=BegDragObj(aLogicPos,NULL,rVEvt.pHdl,nMinMovLog); break; + case SDREVENT_BEGCREATEOBJ: { + if (nAktInvent==SdrInventor && nAktIdent==OBJ_CAPTION) { + long nHgt=SdrEngineDefaults::GetFontHeight(); + bRet=BegCreateCaptionObj(aLogicPos,Size(5*nHgt,2*nHgt)); + } else bRet=BegCreateObj(aLogicPos); + } break; + case SDREVENT_BEGMACROOBJ: bRet=BegMacroObj(aLogicPos,nHitTolLog,rVEvt.pObj,rVEvt.pPV,(Window*)pActualOutDev); break; + case SDREVENT_BEGTEXTEDIT: { + if (!IsObjMarked(rVEvt.pObj)) { + UnmarkAllObj(); + MarkObj(rVEvt.pRootObj,rVEvt.pPV); + } + + bRet = pActualOutDev && OUTDEV_WINDOW == pActualOutDev->GetOutDevType()&& + SdrBeginTextEdit(rVEvt.pObj, rVEvt.pPV, (Window*)pActualOutDev, sal_False, (SdrOutliner*)0L); + + if(bRet) + { + MouseEvent aMEvt(pActualOutDev->LogicToPixel(aLogicPos), + 1,rVEvt.nMouseMode,rVEvt.nMouseCode,rVEvt.nMouseCode); + OutlinerView* pOLV=GetTextEditOutlinerView(); + if (pOLV!=NULL) pOLV->MouseButtonDown(aMEvt); // Event an den Outliner, aber ohne Doppelklick + } + } break; + default: break; + } // switch + if (bRet && pActualOutDev!=NULL && pActualOutDev->GetOutDevType()==OUTDEV_WINDOW) { + Window* pWin=(Window*)pActualOutDev; + // Maus links gedrueckt? + BOOL bLeftDown=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && rVEvt.bMouseDown; + // Maus links losgelassen? + BOOL bLeftUp=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && rVEvt.bMouseUp; + // Maus links gedrueckt oder gehalten? + BOOL bLeftDown1=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && !rVEvt.bMouseUp; + pWin->SetPointer(GetPreferedPointer(rVEvt.aLogicPos,pWin, + rVEvt.nMouseCode & (KEY_SHIFT|KEY_MOD1|KEY_MOD2),bLeftDown1)); + BOOL bAction=IsAction(); + if (bLeftDown && bAction) pWin->CaptureMouse(); + else if (bLeftUp || (rVEvt.bIsAction && !bAction)) pWin->ReleaseMouse(); + } + return bRet; +} +#include <editeng/outlobj.hxx> + +Pointer SdrView::GetPreferedPointer(const Point& rMousePos, const OutputDevice* pOut, USHORT nModifier, BOOL bLeftDown) const +{ + // Actions + if (IsCreateObj()) + { + return pAktCreate->GetCreatePointer(); + } + if (mpCurrentSdrDragMethod) + { + if ((IsDraggingPoints() || IsDraggingGluePoints()) && IsMouseHideWhileDraggingPoints()) + return Pointer(POINTER_NULL); + + OSL_TRACE("SdrView::GetPreferedPointer(%lx) %lx\n", this, mpCurrentSdrDragMethod); + + return mpCurrentSdrDragMethod->GetSdrDragPointer(); + } + if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsEncirclement() || IsSetPageOrg()) return Pointer(POINTER_ARROW); + if (IsDragHelpLine()) return GetDraggedHelpLinePointer(); + if (IsMacroObj()) { + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=pOut->LogicToPixel(rMousePos); + aHitRec.aDownPos=aMacroDownPos; + aHitRec.nTol=nMacroTol; + aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers(); + aHitRec.pPageView=pMacroPV; + aHitRec.pOut=pMacroWin; + aHitRec.bDown=bMacroDown; + return pMacroObj->GetMacroPointer(aHitRec); + } + //USHORT nTol=nHitTolLog; + // TextEdit, ObjEdit, Macro + if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos,0/*nTol*/))) + { + if(!pOut || IsTextEditInSelectionMode()) + { + if(pTextEditOutliner->IsVertical()) + return Pointer(POINTER_TEXT_VERTICAL); + else + return Pointer(POINTER_TEXT); + } + // hier muss besser der Outliner was liefern: + Point aPos(pOut->LogicToPixel(rMousePos)); + Pointer aPointer(pTextEditOutlinerView->GetPointer(aPos)); + if (aPointer==POINTER_ARROW) + { + if(pTextEditOutliner->IsVertical()) + aPointer = POINTER_TEXT_VERTICAL; + else + aPointer = POINTER_TEXT; + } + return aPointer; + } + + SdrViewEvent aVEvt; + aVEvt.nMouseCode=(nModifier&(KEY_SHIFT|KEY_MOD1|KEY_MOD2))|MOUSE_LEFT; // um zu sehen, was bei MouseLeftDown passieren wuerde + aVEvt.bMouseDown=!bLeftDown; // Was waere wenn ... + aVEvt.bMouseUp=bLeftDown; // Was waere wenn ... + if (pOut!=NULL) + ((SdrView*)this)->SetActualWin(pOut); + SdrHitKind eHit=PickAnything(rMousePos,aVEvt); + SdrEventKind eEvent=aVEvt.eEvent; + switch (eEvent) + { + case SDREVENT_BEGCREATEOBJ: + return aAktCreatePointer; + case SDREVENT_MARKOBJ: + case SDREVENT_BEGMARK: + return Pointer(POINTER_ARROW); + case SDREVENT_MARKPOINT: + case SDREVENT_MARKGLUEPOINT: + return Pointer(POINTER_MOVEPOINT); + case SDREVENT_BEGINSOBJPOINT: + case SDREVENT_BEGINSGLUEPOINT: + return Pointer(POINTER_CROSS); + case SDREVENT_EXECUTEURL: + return Pointer(POINTER_REFHAND); + case SDREVENT_BEGMACROOBJ: + { + SdrObjMacroHitRec aHitRec; + aHitRec.aPos=aVEvt.aLogicPos; + aHitRec.aDownPos=aHitRec.aPos; + aHitRec.nTol=nHitTolLog; + aHitRec.pVisiLayer=&aVEvt.pPV->GetVisibleLayers(); + aHitRec.pPageView=aVEvt.pPV; + aHitRec.pOut=(OutputDevice*)pOut; + return aVEvt.pObj->GetMacroPointer(aHitRec); + } + default: break; + } // switch + + switch(eHit) + { + case SDRHIT_CELL: + return Pointer(POINTER_ARROW); + case SDRHIT_HELPLINE : + return aVEvt.pPV->GetHelpLines()[aVEvt.nHlplIdx].GetPointer(); + case SDRHIT_GLUEPOINT: + return Pointer(POINTER_MOVEPOINT); + case SDRHIT_TEXTEDIT : + case SDRHIT_TEXTEDITOBJ: + { + SdrTextObj* pText = dynamic_cast< SdrTextObj* >( aVEvt.pObj ); + if(pText && pText->HasText()) + { + OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject(); + if(pParaObj && pParaObj->IsVertical()) + return Pointer(POINTER_TEXT_VERTICAL); + } + return Pointer(POINTER_TEXT); + } + default: break; + } + + BOOL bMarkHit=eHit==SDRHIT_MARKEDOBJECT; + SdrHdl* pHdl=aVEvt.pHdl; + // Nun die Pointer fuer Dragging checken + if (pHdl!=NULL || bMarkHit) { + SdrHdlKind eHdl= pHdl!=NULL ? pHdl->GetKind() : HDL_MOVE; + BOOL bCorner=pHdl!=NULL && pHdl->IsCornerHdl(); + BOOL bVertex=pHdl!=NULL && pHdl->IsVertexHdl(); + BOOL bMov=eHdl==HDL_MOVE; + if (bMov && (eDragMode==SDRDRAG_MOVE || eDragMode==SDRDRAG_RESIZE || bMarkedHitMovesAlways)) { + if (!IsMoveAllowed()) return Pointer(POINTER_ARROW); // weil Doppelklick oder Drag&Drop moeglich + return Pointer(POINTER_MOVE); + } + switch (eDragMode) { + case SDRDRAG_ROTATE: { + if ((bCorner || bMov) && !IsRotateAllowed(TRUE)) + return Pointer(POINTER_NOTALLOWED); + + // Sind 3D-Objekte selektiert? + BOOL b3DObjSelected = FALSE; +#ifndef SVX_LIGHT + for (UINT32 a=0; !b3DObjSelected && a<GetMarkedObjectCount(); a++) { + SdrObject* pObj = GetMarkedObjectByIndex(a); + if(pObj && pObj->ISA(E3dObject)) + b3DObjSelected = TRUE; + } +#endif + // Falls es um ein 3D-Objekt geht, muss trotz !IsShearAllowed + // weitergemacht werden, da es sich um eine Rotation statt um + // einen Shear handelt + if (bVertex && !IsShearAllowed() && !b3DObjSelected) + return Pointer(POINTER_NOTALLOWED); + if (bMov) + return Pointer(POINTER_ROTATE); + } break; + case SDRDRAG_SHEAR: case SDRDRAG_DISTORT: { + if (bCorner) { + if (!IsDistortAllowed(TRUE) && !IsDistortAllowed(FALSE)) return Pointer(POINTER_NOTALLOWED); + else return Pointer(POINTER_REFHAND); + } + if (bVertex && !IsShearAllowed()) return Pointer(POINTER_NOTALLOWED); + if (bMov) { + if (!IsMoveAllowed()) return Pointer(POINTER_ARROW); // weil Doppelklick oder Drag&Drop moeglich + return Pointer(POINTER_MOVE); + } + } break; + case SDRDRAG_MIRROR: { + if (bCorner || bVertex || bMov) { + SdrHdl* pH1=aHdl.GetHdl(HDL_REF1); + SdrHdl* pH2=aHdl.GetHdl(HDL_REF2); + BOOL b90=FALSE; + BOOL b45=FALSE; + Point aDif; + if (pH1!=NULL && pH2!=NULL) { + aDif=pH2->GetPos()-pH1->GetPos(); + b90=(aDif.X()==0) || aDif.Y()==0; + b45=b90 || (Abs(aDif.X())==Abs(aDif.Y())); + } + BOOL bNo=FALSE; + if (!IsMirrorAllowed(TRUE,TRUE)) bNo=TRUE; // Spiegeln ueberhaupt nicht erlaubt + if (!IsMirrorAllowed(FALSE,FALSE) && !b45) bNo=TRUE; // freies Spiegeln nicht erlaubt + if (!IsMirrorAllowed(TRUE,FALSE) && !b90) bNo=TRUE; // Spiegeln hor/ver erlaubt + if (bNo) return Pointer(POINTER_NOTALLOWED); + if (b90) { + return Pointer(POINTER_MIRROR); + } + return Pointer(POINTER_MIRROR); + } + } break; + + case SDRDRAG_TRANSPARENCE: + { + if(!IsTransparenceAllowed()) + return Pointer(POINTER_NOTALLOWED); + + return Pointer(POINTER_REFHAND); + } + + case SDRDRAG_GRADIENT: + { + if(!IsGradientAllowed()) + return Pointer(POINTER_NOTALLOWED); + + return Pointer(POINTER_REFHAND); + } + + case SDRDRAG_CROOK: { + if (bCorner || bVertex || bMov) { + if (!IsCrookAllowed(TRUE) && !IsCrookAllowed(FALSE)) return Pointer(POINTER_NOTALLOWED); + return Pointer(POINTER_CROOK); + } + } + + case SDRDRAG_CROP: + { + return Pointer(POINTER_CROP); + } + + default: { + if ((bCorner || bVertex) && !IsResizeAllowed(TRUE)) return Pointer(POINTER_NOTALLOWED); + } + } + if (pHdl!=NULL) return pHdl->GetPointer(); + if (bMov) { + if (!IsMoveAllowed()) return Pointer(POINTER_ARROW); // weil Doppelklick oder Drag&Drop moeglich + return Pointer(POINTER_MOVE); + } + } + if (eEditMode==SDREDITMODE_CREATE) return aAktCreatePointer; + return Pointer(POINTER_ARROW); +} + +XubString SdrView::GetStatusText() +{ + XubString aStr; + XubString aName; + + aStr.AppendAscii("nix"); + + if (pAktCreate!=NULL) + { + aStr=pAktCreate->getSpecialDragComment(aDragStat); + + if(!aStr.Len()) + { + pAktCreate->TakeObjNameSingul(aName); + aStr = ImpGetResStr(STR_ViewCreateObj); + } + } + else if (mpCurrentSdrDragMethod) + { + if (bInsPolyPoint || IsInsertGluePoint()) + { + aStr=aInsPointUndoStr; + } + else + { + if (aDragStat.IsMinMoved()) + { + OSL_TRACE("SdrView::GetStatusText(%lx) %lx\n", this, mpCurrentSdrDragMethod); + mpCurrentSdrDragMethod->TakeSdrDragComment(aStr); + } + } + } + else if(IsMarkObj()) + { + if(AreObjectsMarked()) + { + aStr = ImpGetResStr(STR_ViewMarkMoreObjs); + } + else + { + aStr = ImpGetResStr(STR_ViewMarkObjs); + } + } + else if(IsMarkPoints()) + { + if(HasMarkedPoints()) + { + aStr = ImpGetResStr(STR_ViewMarkMorePoints); + } + else + { + aStr = ImpGetResStr(STR_ViewMarkPoints); + } + } else if (IsMarkGluePoints()) + { + if(HasMarkedGluePoints()) + { + aStr = ImpGetResStr(STR_ViewMarkMoreGluePoints); + } + else + { + aStr = ImpGetResStr(STR_ViewMarkGluePoints); + } + } + else if (IsTextEdit() && pTextEditOutlinerView!=NULL) { + aStr=ImpGetResStr(STR_ViewTextEdit); // "TextEdit - Zeile y Spalte x"; + ESelection aSel(pTextEditOutlinerView->GetSelection()); + long nPar=aSel.nEndPara,nLin=0,nCol=aSel.nEndPos; + if (aSel.nEndPara>0) { + for (USHORT nParaNum=0; nParaNum<aSel.nEndPara; nParaNum++) { + nLin+=pTextEditOutliner->GetLineCount(nParaNum); + } + } + // Noch 'ne kleine Unschoenheit: + // Am Ende einer Zeile eines mehrzeiligen Absatzes wird die Position + // der naechsten Zeile des selben Absatzes angezeigt, so es eine solche + // gibt. + USHORT nParaLine=0; + ULONG nParaLineAnz=pTextEditOutliner->GetLineCount(aSel.nEndPara); + BOOL bBrk=FALSE; + while (!bBrk) { + USHORT nLen=pTextEditOutliner->GetLineLen(aSel.nEndPara,nParaLine); + BOOL bLastLine=(nParaLine==nParaLineAnz-1); + if (nCol>nLen || (!bLastLine && nCol==nLen)) { + nCol-=nLen; + nLin++; + nParaLine++; + } else bBrk=TRUE; + if (nLen==0) bBrk=TRUE; // Sicherheitshalber + } + + aStr.SearchAndReplaceAscii("%1", UniString::CreateFromInt32(nPar + 1)); + aStr.SearchAndReplaceAscii("%2", UniString::CreateFromInt32(nLin + 1)); + aStr.SearchAndReplaceAscii("%3", UniString::CreateFromInt32(nCol + 1)); + +#ifdef DBG_UTIL + aStr += UniString( RTL_CONSTASCII_USTRINGPARAM( ", Level " ) ); + aStr += UniString::CreateFromInt32( pTextEditOutliner->GetDepth( aSel.nEndPara ) ); +#endif + } + + if(aStr.EqualsAscii("nix")) + { + if (AreObjectsMarked()) { + ImpTakeDescriptionStr(STR_ViewMarked,aStr); + if (IsGluePointEditMode()) { + if (HasMarkedGluePoints()) { + ImpTakeDescriptionStr(STR_ViewMarked,aStr,0,IMPSDR_GLUEPOINTSDESCRIPTION); + } + } else { + if (HasMarkedPoints()) { + ImpTakeDescriptionStr(STR_ViewMarked,aStr,0,IMPSDR_POINTSDESCRIPTION); + } + } + } else { + aStr.Erase(); + } + } + else if(aName.Len()) + { + aStr.SearchAndReplaceAscii("%1", aName); + } + + if(aStr.Len()) + { + // ersten Buchstaben gross schreiben + String aTmpStr(aStr.Copy(0, 1)); + aTmpStr.ToUpperAscii(); + aStr.Replace(0, 1, aTmpStr); + } + return aStr; +} + +SdrViewContext SdrView::GetContext() const +{ + if( IsGluePointEditMode() ) + return SDRCONTEXT_GLUEPOINTEDIT; + + const ULONG nMarkAnz = GetMarkedObjectCount(); + + if( HasMarkablePoints() && !IsFrameHandles() ) + { + BOOL bPath=TRUE; + for( ULONG nMarkNum = 0; nMarkNum < nMarkAnz && bPath; nMarkNum++ ) + if (!GetMarkedObjectByIndex(nMarkNum)->ISA(SdrPathObj)) + bPath=FALSE; + + if( bPath ) + return SDRCONTEXT_POINTEDIT; + } + + if( GetMarkedObjectCount() ) + { + BOOL bGraf = TRUE, bMedia = TRUE, bTable = TRUE; + + for( ULONG nMarkNum = 0; nMarkNum < nMarkAnz && ( bGraf || bMedia ); nMarkNum++ ) + { + const SdrObject* pMarkObj = GetMarkedObjectByIndex( nMarkNum ); + DBG_ASSERT( pMarkObj, "SdrView::GetContext(), null pointer in mark list!" ); + + if( !pMarkObj ) + continue; + + if( !pMarkObj->ISA( SdrGrafObj ) ) + bGraf = FALSE; + + if( !pMarkObj->ISA( SdrMediaObj ) ) + bMedia = FALSE; + + if( !pMarkObj->ISA( ::sdr::table::SdrTableObj ) ) + bTable = FALSE; + } + + if( bGraf ) + return SDRCONTEXT_GRAPHIC; + else if( bMedia ) + return SDRCONTEXT_MEDIA; + else if( bTable ) + return SDRCONTEXT_TABLE; + } + + return SDRCONTEXT_STANDARD; +} + +void SdrView::MarkAll() +{ + if (IsTextEdit()) { + GetTextEditOutlinerView()->SetSelection(ESelection(0,0,0xFFFF,0xFFFF)); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + } else if (IsGluePointEditMode()) MarkAllGluePoints(); + else if (HasMarkablePoints()) MarkAllPoints(); + else MarkAllObj(); +} + +void SdrView::UnmarkAll() +{ + if (IsTextEdit()) { + ESelection eSel=GetTextEditOutlinerView()->GetSelection(); + eSel.nStartPara=eSel.nEndPara; + eSel.nStartPos=eSel.nEndPos; + GetTextEditOutlinerView()->SetSelection(eSel); +#ifdef DBG_UTIL + if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); +#endif + } else if (HasMarkedGluePoints()) UnmarkAllGluePoints(); + else if (HasMarkedPoints()) UnmarkAllPoints(); // ! Marked statt Markable ! + else UnmarkAllObj(); +} + +BOOL SdrView::IsAllMarked() const +{ + if (IsTextEdit()) { + return ImpIsTextEditAllSelected(); + } + if (IsGluePointEditMode()) { + ULONG nAnz=GetMarkableGluePointCount(); + return nAnz!=0 && nAnz==GetMarkedGluePointCount(); + } + if (HasMarkedPoints()) { + ULONG nAnz=GetMarkablePointCount(); + return nAnz!=0 && nAnz==GetMarkedPointCount(); + } + ULONG nAnz=GetMarkableObjCount(); + return nAnz!=0 && nAnz == GetMarkedObjectCount(); +} + +BOOL SdrView::IsMarkPossible() const +{ + if(IsTextEdit()) + { + return SdrTextObj::HasTextImpl( pTextEditOutliner ); + } + + if(IsGluePointEditMode()) + { + return HasMarkableGluePoints(); + } + + if(HasMarkedPoints()) + { + return HasMarkablePoints(); + } + + return HasMarkableObj(); +} + +BOOL SdrView::IsAllMarkPrevNextPossible() const +{ + if (IsTextEdit()) { + return FALSE; + } + if (IsGluePointEditMode()) { + return HasMarkableGluePoints(); + } + if (HasMarkedPoints()) { + return HasMarkablePoints(); + } + return HasMarkableObj(); +} + +BOOL SdrView::MarkNext(BOOL bPrev) +{ + if (IsTextEdit()) { + return FALSE; + } + if (IsGluePointEditMode() && HasMarkedGluePoints()) { + return MarkNextGluePoint(bPrev); + } + if (HasMarkedPoints()) { + return MarkNextPoint(bPrev); + } + return MarkNextObj(bPrev); +} + +BOOL SdrView::MarkNext(const Point& rPnt, BOOL bPrev) +{ + if (IsTextEdit()) { + return FALSE; + } + if (IsGluePointEditMode() && HasMarkedGluePoints()) { + //return MarkNextGluePoint(rPnt,bPrev); fehlende Implementation !!! + } + if (HasMarkedPoints()) { + //return MarkNextPoint(rPnt,bPrev); fehlende Implementation !!! + } + return MarkNextObj(rPnt,-2,bPrev); +} + +const Rectangle& SdrView::GetMarkedRect() const +{ + if (IsGluePointEditMode() && HasMarkedGluePoints()) { + return GetMarkedGluePointsRect(); + } + if (HasMarkedPoints()) { + return GetMarkedPointsRect(); + } + return GetMarkedObjRect(); +} + +void SdrView::SetMarkedRect(const Rectangle& rRect) +{ + if (IsGluePointEditMode() && HasMarkedGluePoints()) { + //SetMarkedGluePointsRect(rRect); fehlende Implementation !!! + } else if (HasMarkedPoints()) { + //SetMarkedPointsRect(rRect); fehlende Implementation !!! + } else SetMarkedObjRect(rRect); +} + +void SdrView::DeleteMarked() +{ + if (IsTextEdit()) + { + SdrObjEditView::KeyInput(KeyEvent(0,KeyCode(KEYFUNC_DELETE)),pTextEditWin); + } + else + { + if( mxSelectionController.is() && mxSelectionController->DeleteMarked() ) + { + // action already performed by current selection controller, do nothing + } + else if (IsGluePointEditMode() && HasMarkedGluePoints()) + { + DeleteMarkedGluePoints(); + } + else if (GetContext()==SDRCONTEXT_POINTEDIT && HasMarkedPoints()) + { + DeleteMarkedPoints(); + } + else + { + DeleteMarkedObj(); + } + } +} + +BOOL SdrView::BegMark(const Point& rPnt, BOOL bAddMark, BOOL bUnmark) +{ + if (bUnmark) bAddMark=TRUE; + if (IsGluePointEditMode()) { + if (!bAddMark) UnmarkAllGluePoints(); + return BegMarkGluePoints(rPnt,bUnmark); + } else if (HasMarkablePoints()) { + if (!bAddMark) UnmarkAllPoints(); + return BegMarkPoints(rPnt,bUnmark); + } else { + if (!bAddMark) UnmarkAllObj(); + return BegMarkObj(rPnt,bUnmark); + } +} + +BOOL SdrView::IsDeleteMarkedPossible() const +{ + if (IsReadOnly()) return FALSE; + if (IsTextEdit()) return TRUE; + if (IsGluePointEditMode() && HasMarkedGluePoints()) return TRUE; + if (HasMarkedPoints()) return TRUE; + return IsDeleteMarkedObjPossible(); +} + +void SdrView::ConfigurationChanged( ::utl::ConfigurationBroadcaster*p, sal_uInt32 nHint) +{ + onAccessibilityOptionsChanged(); + SdrCreateView::ConfigurationChanged(p, nHint); +} + +SvtAccessibilityOptions& SdrView::getAccessibilityOptions() +{ + return maAccessibilityOptions; +} + +/** method is called whenever the global SvtAccessibilityOptions is changed */ +void SdrView::onAccessibilityOptionsChanged() +{ +} + +void SdrView::SetMasterPagePaintCaching(sal_Bool bOn) +{ + if(mbMasterPagePaintCaching != bOn) + { + mbMasterPagePaintCaching = bOn; + + // reset at all SdrPageWindow's + SdrPageView* pPageView = GetSdrPageView(); + + if(pPageView) + { + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + SdrPageWindow* pPageWindow = pPageView->GetPageWindow(b); + DBG_ASSERT(pPageWindow, "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)"); + + // force deletion of ObjectContact, so at re-display all VOCs + // will be re-created with updated flag setting + pPageWindow->ResetObjectContact(); + } + + // force redraw of this view + pPageView->InvalidateAllWin(); + } + } +} +// eof diff --git a/svx/source/svdraw/svdviter.cxx b/svx/source/svdraw/svdviter.cxx new file mode 100644 index 000000000000..9c52ee87cf23 --- /dev/null +++ b/svx/source/svdraw/svdviter.cxx @@ -0,0 +1,351 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include "svdviter.hxx" +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdsob.hxx> +#include <svl/brdcst.hxx> +#include <sdrpaintwindow.hxx> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrViewIter::ImpInitVars() +{ + mnListenerNum = 0L; + mnPageViewNum = 0L; + mnOutDevNum = 0L; + mpAktView = 0L; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrViewIter::SdrViewIter(const SdrModel* pModel) +{ + mpModel = pModel; + mpPage = 0L; + mpObject = 0L; + ImpInitVars(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrViewIter::SdrViewIter(const SdrPage* pPage, sal_Bool bNoMasterPage) +{ + mpPage = pPage; + mpModel = (pPage) ? pPage->GetModel() : 0L; + mpObject = 0L; + mbNoMasterPage = bNoMasterPage; + ImpInitVars(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrViewIter::SdrViewIter(const SdrObject* pObject, sal_Bool bNoMasterPage) +{ + mpObject = pObject; + mpModel = (pObject) ? pObject->GetModel() : 0L; + mpPage = (pObject) ? pObject->GetPage() : 0L; + mbNoMasterPage = bNoMasterPage; + + if(!mpModel || !mpPage) + { + mpModel = 0L; + mpPage = 0L; + } + + ImpInitVars(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_Bool SdrViewIter::ImpCheckPageView(SdrPageView* pPV) const +{ + if(mpPage) + { + sal_Bool bMaster(mpPage->IsMasterPage()); + SdrPage* pPg = pPV->GetPage(); + + if(pPg == mpPage) + { + if(mpObject) + { + // Objekt gewuenscht? Na dann erstmal sehen, ob + // das Obj in dieser PageView auch sichtbar ist. + SetOfByte aObjLay; + mpObject->getMergedHierarchyLayerSet(aObjLay); + aObjLay &= pPV->GetVisibleLayers(); + return !aObjLay.IsEmpty(); + } + else + { + return sal_True; + } + } + else + { + if(!mbNoMasterPage && bMaster && (!mpObject || !mpObject->IsNotVisibleAsMaster())) + { + if(pPg->TRG_HasMasterPage()) + { + SdrPage& rMasterPage = pPg->TRG_GetMasterPage(); + + if(&rMasterPage == mpPage) + { + // Aha, die gewuenschte Page ist also MasterPage in dieser PageView + if(mpObject) + { + // Objekt gewuenscht? Na dann erstmal sehen, ob + // das Obj in dieser PageView auch sichtbar ist. + SetOfByte aObjLay; + mpObject->getMergedHierarchyLayerSet(aObjLay); + aObjLay &= pPV->GetVisibleLayers(); + aObjLay &= pPg->TRG_GetMasterPageVisibleLayers(); + + if(!aObjLay.IsEmpty()) + { + return TRUE; + } // ansonsten die naechste MasterPage der Page ansehen... + } + else + { + return sal_True; + } + } + } + } + + // MasterPage nicht erlaubt oder keine passende gefunden + return sal_False; + } + } + else + { + return sal_True; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrView* SdrViewIter::ImpFindView() +{ + if(mpModel) + { + sal_uInt32 nLsAnz(mpModel->GetListenerCount()); + + while(mnListenerNum < nLsAnz) + { + SfxListener* pLs = mpModel->GetListener((sal_uInt16)mnListenerNum); + mpAktView = PTR_CAST(SdrView, pLs); + + if(mpAktView) + { + if(mpPage) + { + SdrPageView* pPV = mpAktView->GetSdrPageView(); + + if(pPV) + { + if(ImpCheckPageView(pPV)) + { + return mpAktView; + } + } + } + else + { + return mpAktView; + } + } + + mnListenerNum++; + } + } + + mpAktView = 0L; + return mpAktView; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrPageView* SdrViewIter::ImpFindPageView() +{ + if(mpModel) + { + while(mpAktView) + { + SdrPageView* pPV = mpAktView->GetSdrPageView(); + + if(pPV) + { + if(mpPage) + { + if(ImpCheckPageView(pPV)) + { + return pPV; + } + } + else + { + return pPV; + } + + mnPageViewNum++; + } + + mnListenerNum++; + ImpFindView(); + } + } + + return 0L; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +OutputDevice* SdrViewIter::ImpFindOutDev() +{ + while(mpAktView) + { + const sal_uInt32 nOutDevAnz(mpAktView->PaintWindowCount()); + + if(mnOutDevNum < nOutDevAnz) + { + SdrPaintWindow* pPaintWindow = mpAktView->GetPaintWindow(mnOutDevNum); + return &pPaintWindow->GetOutputDevice(); + } + + mnListenerNum++; + ImpFindView(); + } + + return 0L; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Window* SdrViewIter::ImpFindWindow() +{ + while(mpAktView) + { + const sal_uInt32 nOutDevAnz(mpAktView->PaintWindowCount()); + + while(mnOutDevNum < nOutDevAnz) + { + SdrPaintWindow* pPaintWindow = mpAktView->GetPaintWindow(mnOutDevNum); + OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); + + if(OUTDEV_WINDOW == rOutDev.GetOutDevType()) + { + return (Window*)(&rOutDev); + } + + mnOutDevNum++; + } + + mnListenerNum++; + ImpFindView(); + } + + return 0L; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrView* SdrViewIter::FirstView() +{ + ImpInitVars(); + return ImpFindView(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrView* SdrViewIter::NextView() +{ + mnListenerNum++; + return ImpFindView(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrPageView* SdrViewIter::FirstPageView() +{ + ImpInitVars(); + ImpFindView(); + return ImpFindPageView(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrPageView* SdrViewIter::NextPageView() +{ + mnPageViewNum++; + return ImpFindPageView(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +OutputDevice* SdrViewIter::FirstOutDev() +{ + ImpInitVars(); + ImpFindView(); + return ImpFindOutDev(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +OutputDevice* SdrViewIter::NextOutDev() +{ + mnOutDevNum++; + return ImpFindOutDev(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Window* SdrViewIter::FirstWindow() +{ + ImpInitVars(); + ImpFindView(); + return ImpFindWindow(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Window* SdrViewIter::NextWindow() +{ + mnOutDevNum++; + return ImpFindWindow(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/svx/source/svdraw/svdxcgv.cxx b/svx/source/svdraw/svdxcgv.cxx new file mode 100644 index 000000000000..d19b190b3d6a --- /dev/null +++ b/svx/source/svdraw/svdxcgv.cxx @@ -0,0 +1,894 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <vector> +#include <editeng/editeng.hxx> +#include "xexch.hxx" +#include <svx/xflclit.hxx> +#include <svx/svdxcgv.hxx> +#include <svx/svdoutl.hxx> +#include "svditext.hxx" +#include <svx/svdetc.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdoole2.hxx> // fuer kein OLE im SdrClipboardFormat +#include <svx/svdorect.hxx> +#include <svx/svdoedge.hxx> // fuer Konnektoren uebers Clipboard +#include <svx/svdopage.hxx> // fuer Konnektoren uebers Clipboard +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdtrans.hxx> // Fuer GetMapFactor zum umskalieren bei PasteModel +#include "svdstr.hrc" // Namen aus der Resource +#include "svdglob.hxx" // StringCache +#include "xoutbmp.hxx" +#include <vcl/metaact.hxx> +#include <svl/poolitem.hxx> +#include <svl/itempool.hxx> +#include <tools/bigint.hxx> +#include <sot/formats.hxx> + +// #i13033# +#include <clonelist.hxx> +#include <vcl/virdev.hxx> + +// b4967543 +#include <svl/style.hxx> + +// #i72535# +#include "fmobj.hxx" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrExchangeView::SdrExchangeView(SdrModel* pModel1, OutputDevice* pOut): + SdrObjEditView(pModel1,pOut) +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Point SdrExchangeView::GetViewCenter(const OutputDevice* pOut) const +{ + Point aCenter; + if (pOut==NULL) + { + pOut = GetFirstOutputDevice(); + } + if (pOut!=NULL) { + Point aOfs=pOut->GetMapMode().GetOrigin(); + Size aOutSiz=pOut->GetOutputSize(); + aOutSiz.Width()/=2; + aOutSiz.Height()/=2; + aCenter.X()=aOutSiz.Width() -aOfs.X(); + aCenter.Y()=aOutSiz.Height()-aOfs.Y(); + } + return aCenter; +} + +Point SdrExchangeView::GetPastePos(SdrObjList* pLst, OutputDevice* pOut) +{ + Point aP(GetViewCenter(pOut)); + SdrPage* pPg=NULL; + if (pLst!=NULL) pPg=pLst->GetPage(); + if (pPg!=NULL) { + Size aSiz(pPg->GetSize()); + aP.X()=aSiz.Width()/2; + aP.Y()=aSiz.Height()/2; + } + return aP; +} + +BOOL SdrExchangeView::ImpLimitToWorkArea(Point& rPt) const +{ + BOOL bRet(FALSE); + + if(!aMaxWorkArea.IsEmpty()) + { + if(rPt.X()<aMaxWorkArea.Left()) + { + rPt.X() = aMaxWorkArea.Left(); + bRet = TRUE; + } + + if(rPt.X()>aMaxWorkArea.Right()) + { + rPt.X() = aMaxWorkArea.Right(); + bRet = TRUE; + } + + if(rPt.Y()<aMaxWorkArea.Top()) + { + rPt.Y() = aMaxWorkArea.Top(); + bRet = TRUE; + } + + if(rPt.Y()>aMaxWorkArea.Bottom()) + { + rPt.Y() = aMaxWorkArea.Bottom(); + bRet = TRUE; + } + } + return bRet; +} + +void SdrExchangeView::ImpGetPasteObjList(Point& /*rPos*/, SdrObjList*& rpLst) +{ + if (rpLst==NULL) + { + SdrPageView* pPV = GetSdrPageView(); + + if (pPV!=NULL) { + rpLst=pPV->GetObjList(); + } + } +} + +BOOL SdrExchangeView::ImpGetPasteLayer(const SdrObjList* pObjList, SdrLayerID& rLayer) const +{ + BOOL bRet=FALSE; + rLayer=0; + if (pObjList!=NULL) { + const SdrPage* pPg=pObjList->GetPage(); + if (pPg!=NULL) { + rLayer=pPg->GetLayerAdmin().GetLayerID(aAktLayer,TRUE); + if (rLayer==SDRLAYER_NOTFOUND) rLayer=0; + SdrPageView* pPV = GetSdrPageView(); + if (pPV!=NULL) { + bRet=!pPV->GetLockedLayers().IsSet(rLayer) && pPV->GetVisibleLayers().IsSet(rLayer); + } + } + } + return bRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL SdrExchangeView::Paste(const GDIMetaFile& rMtf, const Point& rPos, SdrObjList* pLst, UINT32 nOptions) +{ + Point aPos(rPos); + ImpGetPasteObjList(aPos,pLst); + ImpLimitToWorkArea( aPos ); + if (pLst==NULL) return FALSE; + SdrLayerID nLayer; + if (!ImpGetPasteLayer(pLst,nLayer)) return FALSE; + BOOL bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit(); + if (bUnmark) UnmarkAllObj(); + SdrGrafObj* pObj=new SdrGrafObj(Graphic(rMtf)); + pObj->SetLayer(nLayer); + ImpPasteObject(pObj,*pLst,aPos,rMtf.GetPrefSize(),rMtf.GetPrefMapMode(),nOptions); + return TRUE; +} + +BOOL SdrExchangeView::Paste(const Bitmap& rBmp, const Point& rPos, SdrObjList* pLst, UINT32 nOptions) +{ + Point aPos(rPos); + ImpGetPasteObjList(aPos,pLst); + ImpLimitToWorkArea( aPos ); + if (pLst==NULL) return FALSE; + SdrLayerID nLayer; + if (!ImpGetPasteLayer(pLst,nLayer)) return FALSE; + BOOL bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit(); + if (bUnmark) UnmarkAllObj(); + SdrGrafObj* pObj=new SdrGrafObj(Graphic(rBmp)); + pObj->SetLayer(nLayer); + ImpPasteObject(pObj,*pLst,aPos,rBmp.GetSizePixel(),MapMode(MAP_PIXEL),nOptions); + return TRUE; +} + +BOOL SdrExchangeView::Paste(const XubString& rStr, const Point& rPos, SdrObjList* pLst, UINT32 nOptions) +{ + if(!rStr.Len()) + return FALSE; + + Point aPos(rPos); + ImpGetPasteObjList(aPos,pLst); + ImpLimitToWorkArea( aPos ); + if (pLst==NULL) return FALSE; + SdrLayerID nLayer; + if (!ImpGetPasteLayer(pLst,nLayer)) return FALSE; + BOOL bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit(); + if (bUnmark) UnmarkAllObj(); + Rectangle aTextRect(0,0,500,500); + SdrPage* pPage=pLst->GetPage(); + if (pPage!=NULL) { + aTextRect.SetSize(pPage->GetSize()); + } + SdrRectObj* pObj=new SdrRectObj(OBJ_TEXT,aTextRect); + pObj->SetModel(pMod); + pObj->SetLayer(nLayer); + pObj->NbcSetText(rStr); // #32424# SetText vor SetAttr, weil SetAttr sonst unwirksam! + if (pDefaultStyleSheet!=NULL) pObj->NbcSetStyleSheet(pDefaultStyleSheet, sal_False); + + pObj->SetMergedItemSet(aDefaultAttr); + + SfxItemSet aTempAttr(pMod->GetItemPool()); // Keine Fuellung oder Linie + aTempAttr.Put(XLineStyleItem(XLINE_NONE)); + aTempAttr.Put(XFillStyleItem(XFILL_NONE)); + + pObj->SetMergedItemSet(aTempAttr); + + pObj->FitFrameToTextSize(); + Size aSiz(pObj->GetLogicRect().GetSize()); + MapUnit eMap=pMod->GetScaleUnit(); + Fraction aMap=pMod->GetScaleFraction(); + ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions); + return TRUE; +} + +BOOL SdrExchangeView::Paste(SvStream& rInput, const String& rBaseURL, USHORT eFormat, const Point& rPos, SdrObjList* pLst, UINT32 nOptions) +{ + Point aPos(rPos); + ImpGetPasteObjList(aPos,pLst); + ImpLimitToWorkArea( aPos ); + if (pLst==NULL) return FALSE; + SdrLayerID nLayer; + if (!ImpGetPasteLayer(pLst,nLayer)) return FALSE; + BOOL bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit(); + if (bUnmark) UnmarkAllObj(); + Rectangle aTextRect(0,0,500,500); + SdrPage* pPage=pLst->GetPage(); + if (pPage!=NULL) { + aTextRect.SetSize(pPage->GetSize()); + } + SdrRectObj* pObj=new SdrRectObj(OBJ_TEXT,aTextRect); + pObj->SetModel(pMod); + pObj->SetLayer(nLayer); + if (pDefaultStyleSheet!=NULL) pObj->NbcSetStyleSheet(pDefaultStyleSheet, sal_False); + + pObj->SetMergedItemSet(aDefaultAttr); + + SfxItemSet aTempAttr(pMod->GetItemPool()); // Keine Fuellung oder Linie + aTempAttr.Put(XLineStyleItem(XLINE_NONE)); + aTempAttr.Put(XFillStyleItem(XFILL_NONE)); + + pObj->SetMergedItemSet(aTempAttr); + + pObj->NbcSetText(rInput,rBaseURL,eFormat); + pObj->FitFrameToTextSize(); + Size aSiz(pObj->GetLogicRect().GetSize()); + MapUnit eMap=pMod->GetScaleUnit(); + Fraction aMap=pMod->GetScaleFraction(); + ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions); + + // b4967543 + if(pObj && pObj->GetModel() && pObj->GetOutlinerParaObject()) + { + SdrOutliner& rOutliner = pObj->GetModel()->GetHitTestOutliner(); + rOutliner.SetText(*pObj->GetOutlinerParaObject()); + + if(1L == rOutliner.GetParagraphCount()) + { + SfxStyleSheet* pCandidate = rOutliner.GetStyleSheet(0L); + + if(pCandidate) + { + if(pObj->GetModel()->GetStyleSheetPool() == &pCandidate->GetPool()) + { + pObj->NbcSetStyleSheet(pCandidate, sal_True); + } + } + } + } + + return TRUE; +} + +BOOL SdrExchangeView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, UINT32 nOptions) +{ + const SdrModel* pSrcMod=&rMod; + if (pSrcMod==pMod) + return FALSE; // na so geht's ja nun nicht + + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + BegUndo(ImpGetResStr(STR_ExchangePaste)); + + if( mxSelectionController.is() && mxSelectionController->PasteObjModel( rMod ) ) + { + if( bUndo ) + EndUndo(); + return TRUE; + } + + Point aPos(rPos); + ImpGetPasteObjList(aPos,pLst); + SdrPageView* pMarkPV=NULL; + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + if ( pPV->GetObjList() == pLst ) + pMarkPV=pPV; + } + + ImpLimitToWorkArea( aPos ); + if (pLst==NULL) + return FALSE; + + BOOL bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit(); + if (bUnmark) + UnmarkAllObj(); + + // evtl. umskalieren bei unterschiedlicher MapUnit am Model + // Dafuer erstmal die Faktoren berechnen + MapUnit eSrcUnit=pSrcMod->GetScaleUnit(); + MapUnit eDstUnit=pMod->GetScaleUnit(); + BOOL bResize=eSrcUnit!=eDstUnit; + Fraction xResize,yResize; + Point aPt0; + if (bResize) + { + FrPair aResize(GetMapFactor(eSrcUnit,eDstUnit)); + xResize=aResize.X(); + yResize=aResize.Y(); + } + SdrObjList* pDstLst=pLst; + USHORT nPg,nPgAnz=pSrcMod->GetPageCount(); + for (nPg=0; nPg<nPgAnz; nPg++) + { + const SdrPage* pSrcPg=pSrcMod->GetPage(nPg); + + // #104148# Use SnapRect, not BoundRect here + Rectangle aR=pSrcPg->GetAllObjSnapRect(); + + if (bResize) + ResizeRect(aR,aPt0,xResize,yResize); + Point aDist(aPos-aR.Center()); + Size aSiz(aDist.X(),aDist.Y()); + //ULONG nDstObjAnz0=pDstLst->GetObjCount(); + ULONG nCloneErrCnt=0; + ULONG nOb,nObAnz=pSrcPg->GetObjCount(); + BOOL bMark=pMarkPV!=NULL && !IsTextEdit() && (nOptions&SDRINSERT_DONTMARK)==0; + + // #i13033# + // New mechanism to re-create the connections of cloned connectors + CloneList aCloneList; + + for (nOb=0; nOb<nObAnz; nOb++) + { + const SdrObject* pSrcOb=pSrcPg->GetObj(nOb); + + // #116235# + SdrObject* pNeuObj = pSrcOb->Clone(); + + if (pNeuObj!=NULL) + { + if(bResize) + { + pNeuObj->GetModel()->SetPasteResize(TRUE); // #51139# + pNeuObj->NbcResize(aPt0,xResize,yResize); + pNeuObj->GetModel()->SetPasteResize(FALSE); // #51139# + } + + // #i39861# + pNeuObj->SetModel(pDstLst->GetModel()); + pNeuObj->SetPage(pDstLst->GetPage()); + + pNeuObj->NbcMove(aSiz); + + const SdrPage* pPg = pDstLst->GetPage(); + + if(pPg) + { + // #i72535# + const SdrLayerAdmin& rAd = pPg->GetLayerAdmin(); + SdrLayerID nLayer(0); + + if(pNeuObj->ISA(FmFormObj)) + { + // for FormControls, force to form layer + nLayer = rAd.GetLayerID(rAd.GetControlLayerName(), true); + } + else + { + nLayer = rAd.GetLayerID(aAktLayer, TRUE); + } + + if(SDRLAYER_NOTFOUND == nLayer) + { + nLayer = 0; + } + + pNeuObj->SetLayer(nLayer); + } + + SdrInsertReason aReason(SDRREASON_VIEWCALL); + pDstLst->InsertObject(pNeuObj,CONTAINER_APPEND,&aReason); + + if( bUndo ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNeuObj)); + + if (bMark) { + // Markhandles noch nicht sofort setzen! + // Das erledigt das ModelHasChanged der MarkView. + MarkObj(pNeuObj,pMarkPV,FALSE,TRUE); + } + + // #i13033# + aCloneList.AddPair(pSrcOb, pNeuObj); + } + else + { + nCloneErrCnt++; + } + } + + // #i13033# + // New mechanism to re-create the connections of cloned connectors + aCloneList.CopyConnections(); + + if(0L != nCloneErrCnt) + { +#ifdef DBG_UTIL + ByteString aStr("SdrExchangeView::Paste(): Fehler beim Clonen "); + + if(nCloneErrCnt == 1) + { + aStr += "eines Zeichenobjekts."; + } + else + { + aStr += "von "; + aStr += ByteString::CreateFromInt32( nCloneErrCnt ); + aStr += " Zeichenobjekten."; + } + + aStr += " Objektverbindungen werden nicht mitkopiert."; + + DBG_ERROR(aStr.GetBuffer()); +#endif + } + } + + if( bUndo ) + EndUndo(); + + return TRUE; +} + +BOOL SdrExchangeView::IsExchangeFormatSupported(ULONG nFormat) const +{ + return( FORMAT_PRIVATE == nFormat || + FORMAT_GDIMETAFILE == nFormat || + FORMAT_BITMAP == nFormat || + FORMAT_RTF == nFormat || + FORMAT_STRING == nFormat || + SOT_FORMATSTR_ID_DRAWING == nFormat || + SOT_FORMATSTR_ID_EDITENGINE == nFormat ); +} + +void SdrExchangeView::ImpPasteObject(SdrObject* pObj, SdrObjList& rLst, const Point& rCenter, const Size& rSiz, const MapMode& rMap, UINT32 nOptions) +{ + BigInt nSizX(rSiz.Width()); + BigInt nSizY(rSiz.Height()); + MapUnit eSrcMU=rMap.GetMapUnit(); + MapUnit eDstMU=pMod->GetScaleUnit(); + FrPair aMapFact(GetMapFactor(eSrcMU,eDstMU)); + Fraction aDstFr(pMod->GetScaleFraction()); + nSizX*=aMapFact.X().GetNumerator(); + nSizX*=rMap.GetScaleX().GetNumerator(); + nSizX*=aDstFr.GetDenominator(); + nSizX/=aMapFact.X().GetDenominator(); + nSizX/=rMap.GetScaleX().GetDenominator(); + nSizX/=aDstFr.GetNumerator(); + nSizY*=aMapFact.Y().GetNumerator(); + nSizY*=rMap.GetScaleY().GetNumerator(); + nSizX*=aDstFr.GetDenominator(); + nSizY/=aMapFact.Y().GetDenominator(); + nSizY/=rMap.GetScaleY().GetDenominator(); + nSizY/=aDstFr.GetNumerator(); + long xs=nSizX; + long ys=nSizY; + Point aPos(rCenter.X()-xs/2,rCenter.Y()-ys/2); + Rectangle aR(aPos.X(),aPos.Y(),aPos.X()+xs,aPos.Y()+ys); + pObj->SetLogicRect(aR); + SdrInsertReason aReason(SDRREASON_VIEWCALL); + rLst.InsertObject(pObj,CONTAINER_APPEND,&aReason); + + if( IsUndoEnabled() ) + AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pObj)); + + SdrPageView* pMarkPV=NULL; + SdrPageView* pPV = GetSdrPageView(); + + if(pPV) + { + if (pPV->GetObjList()==&rLst) + pMarkPV=pPV; + } + + BOOL bMark=pMarkPV!=NULL && !IsTextEdit() && (nOptions&SDRINSERT_DONTMARK)==0; + if (bMark) + { // Obj in der ersten gefundenen PageView markieren + MarkObj(pObj,pMarkPV); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Bitmap SdrExchangeView::GetMarkedObjBitmap( BOOL bNoVDevIfOneBmpMarked ) const +{ + Bitmap aBmp; + + if( AreObjectsMarked() ) + { + if( bNoVDevIfOneBmpMarked ) + { + SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 ); + SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() == 1 ) ? PTR_CAST( SdrGrafObj, pGrafObjTmp ) : NULL; + + if( pGrafObj && ( pGrafObj->GetGraphicType() == GRAPHIC_BITMAP ) ) + aBmp = pGrafObj->GetTransformedGraphic().GetBitmap(); + } + + if( !aBmp ) + { + const Graphic aGraphic( GetMarkedObjMetaFile( bNoVDevIfOneBmpMarked ) ); + + // #i102089# support user's settings of AA and LineSnap when the MetaFile gets + // rasterconverted to a bitmap + const SvtOptionsDrawinglayer aDrawinglayerOpt; + const GraphicConversionParameters aParameters( + Size(), + false, + aDrawinglayerOpt.IsAntiAliasing(), + aDrawinglayerOpt.IsSnapHorVerLinesToDiscrete()); + + aBmp = aGraphic.GetBitmap(aParameters); + } + } + + return aBmp; +} + +// ----------------------------------------------------------------------------- + +GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile( BOOL bNoVDevIfOneMtfMarked ) const +{ + GDIMetaFile aMtf; + + if( AreObjectsMarked() ) + { + Rectangle aBound( GetMarkedObjBoundRect() ); + Size aBoundSize( aBound.GetWidth(), aBound.GetHeight() ); + MapMode aMap( pMod->GetScaleUnit(), Point(), pMod->GetScaleFraction(), pMod->GetScaleFraction() ); + + if( bNoVDevIfOneMtfMarked ) + { + SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 ); + SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() ==1 ) ? PTR_CAST( SdrGrafObj, pGrafObjTmp ) : NULL; + + if( pGrafObj ) + { + Graphic aGraphic( pGrafObj->GetTransformedGraphic() ); + + if( aGraphic.GetType() == GRAPHIC_BITMAP ) + { + const Point aPos; + + aMtf.AddAction( new MetaBmpExScaleAction( aPos, aBoundSize, aGraphic.GetBitmapEx() ) ); + aMtf.SetPrefMapMode( aMap ); + aMtf.SetPrefSize( aBoundSize ); + } + else + aMtf = aGraphic.GetGDIMetaFile(); + } + } + + if( !aMtf.GetActionCount() ) + { + VirtualDevice aOut; + Size aDummySize( 2, 2 ); + + aOut.SetOutputSizePixel( aDummySize ); + aOut.EnableOutput( FALSE ); + aOut.SetMapMode( aMap ); + + aMtf.Clear(); + aMtf.Record( &aOut ); + + // Replace offset given formally to DrawMarkedObj and used at XOutDev with relative + // MapMode (which was also used in XOutDev in that case). Goal is to paint the object + // as if TopLeft point is (0,0) + const Fraction aNeutralFraction(1, 1); + const MapMode aRelativeMapMode(MAP_RELATIVE, Point(-aBound.Left(), -aBound.Top()), aNeutralFraction, aNeutralFraction); + aOut.SetMapMode(aRelativeMapMode); + + DrawMarkedObj(aOut); + + aMtf.Stop(); + aMtf.WindStart(); + aMtf.SetPrefMapMode( aMap ); + + // removed PrefSize extension. It is principially wrong to set a reduced size at + // the created MetaFile. The mentioned errors occurr at output time since the integer + // MapModes from VCL lead to errors. It is now corrected in the VCLRenderer for + // primitives (and may later be done in breaking up a MetaFile to primitives) + aMtf.SetPrefSize(aBoundSize); + } + } + + return aMtf; +} + +// ----------------------------------------------------------------------------- + +Graphic SdrExchangeView::GetAllMarkedGraphic() const +{ + Graphic aRet; + + if( AreObjectsMarked() ) + { + if( ( 1 == GetMarkedObjectCount() ) && GetSdrMarkByIndex( 0 ) ) + aRet = SdrExchangeView::GetObjGraphic( pMod, GetMarkedObjectByIndex( 0 ) ); + else + aRet = GetMarkedObjMetaFile( FALSE ); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +Graphic SdrExchangeView::GetObjGraphic( const SdrModel* pModel, const SdrObject* pObj ) +{ + Graphic aRet; + + if( pModel && pObj ) + { + // try to get a graphic from the object first + const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj); + const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj); + + if(pSdrGrafObj) + { + // #110981# Make behaviour coherent with metafile + // recording below (which of course also takes + // view-transformed objects) + aRet = pSdrGrafObj->GetTransformedGraphic(); + } + else if(pSdrOle2Obj) + { + if ( pSdrOle2Obj->GetGraphic() ) + aRet = *pSdrOle2Obj->GetGraphic(); + } + + // if graphic could not be retrieved => go the hard way and create a MetaFile + if( ( GRAPHIC_NONE == aRet.GetType() ) || ( GRAPHIC_DEFAULT == aRet.GetType() ) ) + { + VirtualDevice aOut; + GDIMetaFile aMtf; + const Rectangle aBoundRect( pObj->GetCurrentBoundRect() ); + const MapMode aMap( pModel->GetScaleUnit(), + Point(), + pModel->GetScaleFraction(), + pModel->GetScaleFraction() ); + + aOut.EnableOutput( FALSE ); + aOut.SetMapMode( aMap ); + aMtf.Record( &aOut ); + pObj->SingleObjectPainter( aOut ); // #110094#-17 + aMtf.Stop(); + aMtf.WindStart(); + + // #i99268# replace the original offset from using XOutDev's SetOffset + // NOT (as tried with #i92760#) with another MapMode which gets recorded + // by the Metafile itself (what always leads to problems), but by hardly + // moving the result + aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top()); + + aMtf.SetPrefMapMode( aMap ); + aMtf.SetPrefSize( aBoundRect.GetSize() ); + + if( aMtf.GetActionCount() ) + aRet = aMtf; + } + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +void SdrExchangeView::DrawMarkedObj(OutputDevice& rOut) const +{ + SortMarkedObjects(); + + ::std::vector< ::std::vector< SdrMark* > > aObjVectors( 2 ); + ::std::vector< SdrMark* >& rObjVector1 = aObjVectors[ 0 ]; + ::std::vector< SdrMark* >& rObjVector2 = aObjVectors[ 1 ]; + const SdrLayerAdmin& rLayerAdmin = pMod->GetLayerAdmin(); + const sal_uInt32 nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName(), FALSE ); + sal_uInt32 n, nCount; + + for( n = 0, nCount = GetMarkedObjectCount(); n < nCount; n++ ) + { + SdrMark* pMark = GetSdrMarkByIndex( n ); + + // paint objects on control layer on top of all otherobjects + if( nControlLayerId == pMark->GetMarkedSdrObj()->GetLayer() ) + rObjVector2.push_back( pMark ); + else + rObjVector1.push_back( pMark ); + } + + for( n = 0, nCount = aObjVectors.size(); n < nCount; n++ ) + { + ::std::vector< SdrMark* >& rObjVector = aObjVectors[ n ]; + + for( sal_uInt32 i = 0; i < rObjVector.size(); i++ ) + { + SdrMark* pMark = rObjVector[ i ]; + pMark->GetMarkedSdrObj()->SingleObjectPainter( rOut ); // #110094#-17 + } + } +} + +// ----------------------------------------------------------------------------- + +SdrModel* SdrExchangeView::GetMarkedObjModel() const +{ + // Wenn das sortieren der MarkList mal stoeren sollte, + // werde ich sie mir wohl kopieren muessen. + SortMarkedObjects(); + SdrModel* pNeuMod=pMod->AllocModel(); + SdrPage* pNeuPag=pNeuMod->AllocPage(FALSE); + pNeuMod->InsertPage(pNeuPag); + + if( !mxSelectionController.is() || !mxSelectionController->GetMarkedObjModel( pNeuPag ) ) + { + ::std::vector< ::std::vector< SdrMark* > > aObjVectors( 2 ); + ::std::vector< SdrMark* >& rObjVector1 = aObjVectors[ 0 ]; + ::std::vector< SdrMark* >& rObjVector2 = aObjVectors[ 1 ]; + const SdrLayerAdmin& rLayerAdmin = pMod->GetLayerAdmin(); + const sal_uInt32 nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName(), FALSE ); + sal_uInt32 n, nCount, nCloneErrCnt = 0; + + for( n = 0, nCount = GetMarkedObjectCount(); n < nCount; n++ ) + { + SdrMark* pMark = GetSdrMarkByIndex( n ); + + // paint objects on control layer on top of all otherobjects + if( nControlLayerId == pMark->GetMarkedSdrObj()->GetLayer() ) + rObjVector2.push_back( pMark ); + else + rObjVector1.push_back( pMark ); + } + + // #i13033# + // New mechanism to re-create the connections of cloned connectors + CloneList aCloneList; + + for( n = 0, nCount = aObjVectors.size(); n < nCount; n++ ) + { + ::std::vector< SdrMark* >& rObjVector = aObjVectors[ n ]; + + for( sal_uInt32 i = 0; i < rObjVector.size(); i++ ) + { + const SdrMark* pMark = rObjVector[ i ]; + const SdrObject* pObj = pMark->GetMarkedSdrObj(); + SdrObject* pNeuObj; + + if( pObj->ISA( SdrPageObj ) ) + { + // convert SdrPageObj's to a graphic representation, because + // virtual connection to referenced page gets lost in new model + pNeuObj = new SdrGrafObj( GetObjGraphic( pMod, pObj ), pObj->GetLogicRect() ); + pNeuObj->SetPage( pNeuPag ); + pNeuObj->SetModel( pNeuMod ); + } + else + { + // #116235# + // pNeuObj = pObj->Clone( pNeuPag, pNeuMod ); + pNeuObj = pObj->Clone(); + pNeuObj->SetPage( pNeuPag ); + pNeuObj->SetModel( pNeuMod ); + } + + if( pNeuObj ) + { + SdrInsertReason aReason(SDRREASON_VIEWCALL); + pNeuPag->InsertObject(pNeuObj,CONTAINER_APPEND,&aReason); + + // #i13033# + aCloneList.AddPair(pObj, pNeuObj); + } + else + nCloneErrCnt++; + } + } + + // #i13033# + // New mechanism to re-create the connections of cloned connectors + aCloneList.CopyConnections(); + + if(0L != nCloneErrCnt) + { +#ifdef DBG_UTIL + ByteString aStr("SdrExchangeView::GetMarkedObjModel(): Fehler beim Clonen "); + + if(nCloneErrCnt == 1) + { + aStr += "eines Zeichenobjekts."; + } + else + { + aStr += "von "; + aStr += ByteString::CreateFromInt32( nCloneErrCnt ); + aStr += " Zeichenobjekten."; + } + + aStr += " Objektverbindungen werden nicht mitkopiert."; + + DBG_ERROR(aStr.GetBuffer()); +#endif + } + } + return pNeuMod; +} + +// ----------------------------------------------------------------------------- + +BOOL SdrExchangeView::Cut( ULONG /*nFormat */) +{ + DBG_ERROR( "SdrExchangeView::Cut: Not supported anymore" ); + return FALSE; +} + +// ----------------------------------------------------------------------------- + +void SdrExchangeView::CutMarked( ULONG /*nFormat */) +{ + DBG_ERROR( "SdrExchangeView::CutMarked: Not supported anymore" ); +} + +// ----------------------------------------------------------------------------- + +BOOL SdrExchangeView::Yank(ULONG /*nFormat*/) +{ + DBG_ERROR( "SdrExchangeView::Yank: Not supported anymore" ); + return FALSE; +} + +// ----------------------------------------------------------------------------- + +void SdrExchangeView::YankMarked(ULONG /*nFormat*/) +{ + DBG_ERROR( "YankMarked: Not supported anymore" ); +} + +// ----------------------------------------------------------------------------- + +BOOL SdrExchangeView::Paste(Window* /*pWin*/, ULONG /*nFormat*/) +{ + DBG_ERROR( "SdrExchangeView::Paste: Not supported anymore" ); + return FALSE; +} |