summaryrefslogtreecommitdiff
path: root/svx/source/svdraw/svdocapt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/svdraw/svdocapt.cxx')
-rw-r--r--svx/source/svdraw/svdocapt.cxx851
1 files changed, 851 insertions, 0 deletions
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