merge the formfield patch from ooo-build
[ooovba.git] / svx / source / svdraw / svdocapt.cxx
blob8630d2c1d19dc36f335708a464763980a4dd9039
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svdocapt.cxx,v $
10 * $Revision: 1.30.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <tools/bigint.hxx>
34 #include <svx/xlnwtit.hxx>
35 #include <svtools/style.hxx>
36 #include <svx/svdocapt.hxx>
37 #include <svx/xpool.hxx>
38 #include <svx/xpoly.hxx>
39 #include <svx/svdattrx.hxx>
40 #include <svx/svdpool.hxx>
41 #include <svx/svdetc.hxx>
42 #include <svx/svdtrans.hxx>
43 #include <svx/svdhdl.hxx>
44 #include <svx/svddrag.hxx>
45 #include <svx/svdmodel.hxx>
46 #include <svx/svdview.hxx> // fuer RectSnap
47 #include "svdglob.hxx" // StringCache
48 #include "svdstr.hrc" // Objektname
49 #include <svx/svdogrp.hxx>
50 #include <svx/svdpage.hxx>
51 #include <svx/xflhtit.hxx>
52 #include <svx/xflclit.hxx>
53 #include <svx/xfltrit.hxx>
54 #include <svx/eeitem.hxx>
55 #include <svx/sdr/properties/captionproperties.hxx>
56 #include <vcl/salbtype.hxx> // FRound
57 #include <svx/sdr/contact/viewcontactofsdrcaptionobj.hxx>
58 #include <basegfx/tuple/b2dtuple.hxx>
59 #include <basegfx/matrix/b2dhommatrix.hxx>
60 #include <basegfx/polygon/b2dpolygon.hxx>
61 #include <basegfx/range/b2drange.hxx>
62 #include <basegfx/polygon/b2dpolygontools.hxx>
63 #include <svx/sdrhittesthelper.hxx>
65 // #i32599#
66 inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); }
67 inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); }
69 ////////////////////////////////////////////////////////////////////////////////////////////////////
71 enum EscDir {LKS,RTS,OBN,UNT};
73 class ImpCaptParams
75 public:
76 SdrCaptionType eType;
77 long nAngle;
78 long nGap;
79 long nEscRel;
80 long nEscAbs;
81 long nLineLen;
82 SdrCaptionEscDir eEscDir;
83 FASTBOOL bFitLineLen;
84 FASTBOOL bEscRel;
85 FASTBOOL bFixedAngle;
87 public:
88 ImpCaptParams()
90 eType =SDRCAPT_TYPE3;
91 bFixedAngle=FALSE;
92 nAngle =4500;
93 nGap =0;
94 eEscDir =SDRCAPT_ESCHORIZONTAL;
95 bEscRel =TRUE;
96 nEscRel =5000;
97 nEscAbs =0;
98 nLineLen =0;
99 bFitLineLen=TRUE;
101 void CalcEscPos(const Point& rTail, const Rectangle& rRect, Point& rPt, EscDir& rDir) const;
104 void ImpCaptParams::CalcEscPos(const Point& rTailPt, const Rectangle& rRect, Point& rPt, EscDir& rDir) const
106 Point aTl(rTailPt); // lokal kopieren wg. Performance
107 long nX,nY;
108 if (bEscRel) {
109 nX=rRect.Right()-rRect.Left();
110 nX=BigMulDiv(nX,nEscRel,10000);
111 nY=rRect.Bottom()-rRect.Top();
112 nY=BigMulDiv(nY,nEscRel,10000);
113 } else {
114 nX=nEscAbs;
115 nY=nEscAbs;
117 nX+=rRect.Left();
118 nY+=rRect.Top();
119 Point aBestPt;
120 EscDir eBestDir=LKS;
121 FASTBOOL bTryH=eEscDir==SDRCAPT_ESCBESTFIT;
122 if (!bTryH) {
123 if (eType!=SDRCAPT_TYPE1) {
124 bTryH=eEscDir==SDRCAPT_ESCHORIZONTAL;
125 } else {
126 bTryH=eEscDir==SDRCAPT_ESCVERTICAL;
129 FASTBOOL bTryV=eEscDir==SDRCAPT_ESCBESTFIT;
130 if (!bTryV) {
131 if (eType!=SDRCAPT_TYPE1) {
132 bTryV=eEscDir==SDRCAPT_ESCVERTICAL;
133 } else {
134 bTryV=eEscDir==SDRCAPT_ESCHORIZONTAL;
138 if (bTryH) {
139 Point aLft(rRect.Left()-nGap,nY);
140 Point aRgt(rRect.Right()+nGap,nY);
141 FASTBOOL bLft=(aTl.X()-aLft.X()<aRgt.X()-aTl.X());
142 if (bLft) {
143 eBestDir=LKS;
144 aBestPt=aLft;
145 } else {
146 eBestDir=RTS;
147 aBestPt=aRgt;
150 if (bTryV) {
151 Point aTop(nX,rRect.Top()-nGap);
152 Point aBtm(nX,rRect.Bottom()+nGap);
153 FASTBOOL bTop=(aTl.Y()-aTop.Y()<aBtm.Y()-aTl.Y());
154 Point aBest2;
155 EscDir eBest2;
156 if (bTop) {
157 eBest2=OBN;
158 aBest2=aTop;
159 } else {
160 eBest2=UNT;
161 aBest2=aBtm;
163 FASTBOOL bTakeIt=eEscDir!=SDRCAPT_ESCBESTFIT;
164 if (!bTakeIt) {
165 BigInt aHorX(aBestPt.X()-aTl.X()); aHorX*=aHorX;
166 BigInt aHorY(aBestPt.Y()-aTl.Y()); aHorY*=aHorY;
167 BigInt aVerX(aBest2.X()-aTl.X()); aVerX*=aVerX;
168 BigInt aVerY(aBest2.Y()-aTl.Y()); aVerY*=aVerY;
169 if (eType!=SDRCAPT_TYPE1) {
170 bTakeIt=aVerX+aVerY<aHorX+aHorY;
171 } else {
172 bTakeIt=aVerX+aVerY>=aHorX+aHorY;
175 if (bTakeIt) {
176 aBestPt=aBest2;
177 eBestDir=eBest2;
180 rPt=aBestPt;
181 rDir=eBestDir;
184 //////////////////////////////////////////////////////////////////////////////
185 // BaseProperties section
187 sdr::properties::BaseProperties* SdrCaptionObj::CreateObjectSpecificProperties()
189 return new sdr::properties::CaptionProperties(*this);
192 //////////////////////////////////////////////////////////////////////////////
193 // DrawContact section
195 sdr::contact::ViewContact* SdrCaptionObj::CreateObjectSpecificViewContact()
197 return new sdr::contact::ViewContactOfSdrCaptionObj(*this);
200 //////////////////////////////////////////////////////////////////////////////
202 TYPEINIT1(SdrCaptionObj,SdrRectObj);
204 SdrCaptionObj::SdrCaptionObj():
205 SdrRectObj(OBJ_TEXT),
206 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien
207 mbSpecialTextBoxShadow(FALSE),
208 mbFixedTail(FALSE)
212 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect):
213 SdrRectObj(OBJ_TEXT,rRect),
214 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien
215 mbSpecialTextBoxShadow(FALSE),
216 mbFixedTail(FALSE)
220 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect, const Point& rTail):
221 SdrRectObj(OBJ_TEXT,rRect),
222 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien
223 mbSpecialTextBoxShadow(FALSE),
224 mbFixedTail(FALSE)
226 aTailPoly[0]=maFixedTailPos=rTail;
229 SdrCaptionObj::~SdrCaptionObj()
233 void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
235 rInfo.bRotateFreeAllowed=FALSE;
236 rInfo.bRotate90Allowed =FALSE;
237 rInfo.bMirrorFreeAllowed=FALSE;
238 rInfo.bMirror45Allowed =FALSE;
239 rInfo.bMirror90Allowed =FALSE;
240 rInfo.bTransparenceAllowed = FALSE;
241 rInfo.bGradientAllowed = FALSE;
242 rInfo.bShearAllowed =FALSE;
243 rInfo.bEdgeRadiusAllowed=FALSE;
244 rInfo.bCanConvToPath =TRUE;
245 rInfo.bCanConvToPoly =TRUE;
246 rInfo.bCanConvToPathLineToArea=FALSE;
247 rInfo.bCanConvToPolyLineToArea=FALSE;
248 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
251 UINT16 SdrCaptionObj::GetObjIdentifier() const
253 return UINT16(OBJ_CAPTION);
256 void SdrCaptionObj::operator=(const SdrObject& rObj)
258 SdrRectObj::operator=(rObj);
259 aTailPoly=((SdrCaptionObj&)rObj).aTailPoly;
262 void SdrCaptionObj::TakeObjNameSingul(XubString& rName) const
264 rName=ImpGetResStr(STR_ObjNameSingulCAPTION);
266 String aName( GetName() );
267 if(aName.Len())
269 rName += sal_Unicode(' ');
270 rName += sal_Unicode('\'');
271 rName += aName;
272 rName += sal_Unicode('\'');
276 void SdrCaptionObj::TakeObjNamePlural(XubString& rName) const
278 rName=ImpGetResStr(STR_ObjNamePluralCAPTION);
281 basegfx::B2DPolyPolygon SdrCaptionObj::TakeXorPoly() const
283 basegfx::B2DPolyPolygon aPolyPoly(SdrRectObj::TakeXorPoly());
284 aPolyPoly.append(aTailPoly.getB2DPolygon());
286 return aPolyPoly;
289 sal_uInt32 SdrCaptionObj::GetHdlCount() const
291 sal_uInt32 nAnz1(SdrRectObj::GetHdlCount());
292 // sal_uInt32 nAnz2(aTailPoly.GetSize());
293 // Derzeit ist nur das Draggen des Schwanzendes implementiert
294 return nAnz1 + 1L;
297 SdrHdl* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum) const
299 const sal_uInt32 nRectHdlAnz(SdrRectObj::GetHdlCount());
301 if(nHdlNum < nRectHdlAnz)
303 return SdrRectObj::GetHdl(nHdlNum);
305 else
307 sal_uInt32 nPntNum(nHdlNum);
308 nPntNum -= nRectHdlAnz;
310 if(nPntNum < aTailPoly.GetSize())
312 SdrHdl* pHdl = new SdrHdl(aTailPoly.GetPoint((sal_uInt16)nPntNum), HDL_POLY);
313 pHdl->SetPolyNum(1L);
314 pHdl->SetPointNum(nPntNum);
315 return pHdl;
317 else
319 return 0L;
324 ////////////////////////////////////////////////////////////////////////////////////////////////////
326 bool SdrCaptionObj::hasSpecialDrag() const
328 return true;
331 bool SdrCaptionObj::beginSpecialDrag(SdrDragStat& rDrag) const
333 const SdrHdl* pHdl = rDrag.GetHdl();
334 rDrag.SetEndDragChangesAttributes(true);
335 rDrag.SetEndDragChangesGeoAndAttributes(true);
337 if(pHdl && 0 == pHdl->GetPolyNum())
339 return SdrRectObj::beginSpecialDrag(rDrag);
341 else
343 rDrag.SetOrtho8Possible(true);
345 if(!pHdl)
347 if (bMovProt)
348 return 0;
350 rDrag.SetNoSnap(true);
351 rDrag.SetActionRect(aRect);
353 Point aHit(rDrag.GetStart());
355 if(rDrag.GetPageView() && SdrObjectPrimitiveHit(*this, aHit, 0, *rDrag.GetPageView(), 0, false))
357 return true;
360 else
362 if((1 == pHdl->GetPolyNum()) && (0 == pHdl->GetPointNum()))
363 return true;
367 return false;
370 bool SdrCaptionObj::applySpecialDrag(SdrDragStat& rDrag)
372 const SdrHdl* pHdl = rDrag.GetHdl();
374 if(pHdl && 0 == pHdl->GetPolyNum())
376 const bool bRet(SdrRectObj::applySpecialDrag(rDrag));
377 ImpRecalcTail();
378 ActionChanged();
380 return bRet;
382 else
384 Point aDelt(rDrag.GetNow()-rDrag.GetStart());
386 if(!pHdl)
388 aRect.Move(aDelt.X(),aDelt.Y());
390 else
392 aTailPoly[0] += aDelt;
395 ImpRecalcTail();
396 ActionChanged();
398 return true;
402 String SdrCaptionObj::getSpecialDragComment(const SdrDragStat& rDrag) const
404 const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
406 if(bCreateComment)
408 return String();
410 else
412 const SdrHdl* pHdl = rDrag.GetHdl();
414 if(pHdl && 0 == pHdl->GetPolyNum())
416 return SdrRectObj::getSpecialDragComment(rDrag);
418 else
420 XubString aStr;
422 if(!pHdl)
424 ImpTakeDescriptionStr(STR_DragCaptFram, aStr);
426 else
428 ImpTakeDescriptionStr(STR_DragCaptTail, aStr);
431 return aStr;
436 ////////////////////////////////////////////////////////////////////////////////////////////////////
438 void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams& rPara) const
440 const SfxItemSet& rSet = GetObjectItemSet();
441 rPara.eType =((SdrCaptionTypeItem&) (rSet.Get(SDRATTR_CAPTIONTYPE ))).GetValue();
442 rPara.bFixedAngle=((SdrCaptionFixedAngleItem&)(rSet.Get(SDRATTR_CAPTIONANGLE ))).GetValue();
443 rPara.nAngle =((SdrCaptionAngleItem&) (rSet.Get(SDRATTR_CAPTIONFIXEDANGLE))).GetValue();
444 rPara.nGap =((SdrCaptionGapItem&) (rSet.Get(SDRATTR_CAPTIONGAP ))).GetValue();
445 rPara.eEscDir =((SdrCaptionEscDirItem&) (rSet.Get(SDRATTR_CAPTIONESCDIR ))).GetValue();
446 rPara.bEscRel =((SdrCaptionEscIsRelItem&) (rSet.Get(SDRATTR_CAPTIONESCISREL ))).GetValue();
447 rPara.nEscRel =((SdrCaptionEscRelItem&) (rSet.Get(SDRATTR_CAPTIONESCREL ))).GetValue();
448 rPara.nEscAbs =((SdrCaptionEscAbsItem&) (rSet.Get(SDRATTR_CAPTIONESCABS ))).GetValue();
449 rPara.nLineLen =((SdrCaptionLineLenItem&) (rSet.Get(SDRATTR_CAPTIONLINELEN ))).GetValue();
450 rPara.bFitLineLen=((SdrCaptionFitLineLenItem&)(rSet.Get(SDRATTR_CAPTIONFITLINELEN))).GetValue();
453 void SdrCaptionObj::ImpRecalcTail()
455 ImpCaptParams aPara;
456 ImpGetCaptParams(aPara);
457 ImpCalcTail(aPara,aTailPoly,aRect);
458 SetRectsDirty();
459 SetXPolyDirty();
462 // #i35971#
463 // SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack.
464 // I really wonder why this had not triggered problems before. I am
465 // sure there are some places where SetTailPos() is called at least
466 // twice or SetSnapRect after it again just to work around this.
467 // Changed this method to not do that.
468 // Also found why this has been done: For interactive dragging of the
469 // tail end pos for SDRCAPT_TYPE1. This sure was the simplest method
470 // to achieve this, for the cost to make a whole group of const methods
471 // of this object implicitly chainging the object's position.
472 void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
474 Polygon aPol(2);
475 Point aTl(rPoly[0]);
477 aPol[0] = aTl;
478 aPol[1] = aTl;
480 EscDir eEscDir;
481 Point aEscPos;
483 rPara.CalcEscPos(aTl, rRect, aEscPos, eEscDir);
484 aPol[1] = aEscPos;
486 if(eEscDir==LKS || eEscDir==RTS)
488 aPol[0].X() = aEscPos.X();
490 else
492 aPol[0].Y() = aEscPos.Y();
495 rPoly = aPol;
498 void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
499 { // Gap/EscDir/EscPos/Angle
500 Polygon aPol(2);
501 Point aTl(rPoly[0]);
502 aPol[0]=aTl;
504 EscDir eEscDir;
505 Point aEscPos;
506 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
507 aPol[1]=aEscPos;
509 if (!rPara.bFixedAngle) {
510 // fehlende Implementation
512 rPoly=aPol;
515 void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
516 { // Gap/EscDir/EscPos/Angle/LineLen
517 Polygon aPol(3);
518 Point aTl(rPoly[0]);
519 aPol[0]=aTl;
521 EscDir eEscDir;
522 Point aEscPos;
523 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
524 aPol[1]=aEscPos;
525 aPol[2]=aEscPos;
527 if (eEscDir==LKS || eEscDir==RTS) {
528 if (rPara.bFitLineLen) {
529 aPol[1].X()=(aTl.X()+aEscPos.X())/2;
530 } else {
531 if (eEscDir==LKS) aPol[1].X()-=rPara.nLineLen;
532 else aPol[1].X()+=rPara.nLineLen;
534 } else {
535 if (rPara.bFitLineLen) {
536 aPol[1].Y()=(aTl.Y()+aEscPos.Y())/2;
537 } else {
538 if (eEscDir==OBN) aPol[1].Y()-=rPara.nLineLen;
539 else aPol[1].Y()+=rPara.nLineLen;
542 if (!rPara.bFixedAngle) {
543 // fehlende Implementation
545 rPoly=aPol;
548 void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
550 ImpCalcTail3(rPara,rPoly,rRect);
553 void SdrCaptionObj::ImpCalcTail(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
555 switch (rPara.eType) {
556 case SDRCAPT_TYPE1: ImpCalcTail1(rPara,rPoly,rRect); break;
557 case SDRCAPT_TYPE2: ImpCalcTail2(rPara,rPoly,rRect); break;
558 case SDRCAPT_TYPE3: ImpCalcTail3(rPara,rPoly,rRect); break;
559 case SDRCAPT_TYPE4: ImpCalcTail4(rPara,rPoly,rRect); break;
563 FASTBOOL SdrCaptionObj::BegCreate(SdrDragStat& rStat)
565 if (aRect.IsEmpty()) return FALSE; // Create z.Zt. nur mit vorgegebenen Rect
567 ImpCaptParams aPara;
568 ImpGetCaptParams(aPara);
569 aRect.SetPos(rStat.GetNow());
570 aTailPoly[0]=rStat.GetStart();
571 ImpCalcTail(aPara,aTailPoly,aRect);
572 rStat.SetActionRect(aRect);
573 return TRUE;
576 FASTBOOL SdrCaptionObj::MovCreate(SdrDragStat& rStat)
578 ImpCaptParams aPara;
579 ImpGetCaptParams(aPara);
580 aRect.SetPos(rStat.GetNow());
581 ImpCalcTail(aPara,aTailPoly,aRect);
582 rStat.SetActionRect(aRect);
583 SetBoundRectDirty();
584 bSnapRectDirty=TRUE;
585 return TRUE;
588 FASTBOOL SdrCaptionObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
590 ImpCaptParams aPara;
591 ImpGetCaptParams(aPara);
592 aRect.SetPos(rStat.GetNow());
593 ImpCalcTail(aPara,aTailPoly,aRect);
594 SetRectsDirty();
595 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
598 FASTBOOL SdrCaptionObj::BckCreate(SdrDragStat& /*rStat*/)
600 return FALSE;
603 void SdrCaptionObj::BrkCreate(SdrDragStat& /*rStat*/)
607 basegfx::B2DPolyPolygon SdrCaptionObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
609 basegfx::B2DPolyPolygon aRetval;
610 const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
611 aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
612 aRetval.append(aTailPoly.getB2DPolygon());
613 return aRetval;
616 Pointer SdrCaptionObj::GetCreatePointer() const
618 return Pointer(POINTER_DRAW_CAPTION);
621 void SdrCaptionObj::NbcMove(const Size& rSiz)
623 SdrRectObj::NbcMove(rSiz);
624 MovePoly(aTailPoly,rSiz);
625 if(mbFixedTail)
626 SetTailPos(GetFixedTailPos());
629 void SdrCaptionObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
631 SdrRectObj::NbcResize(rRef,xFact,yFact);
632 ResizePoly(aTailPoly,rRef,xFact,yFact);
633 ImpRecalcTail();
634 if(mbFixedTail)
635 SetTailPos(GetFixedTailPos());
638 void SdrCaptionObj::NbcSetRelativePos(const Point& rPnt)
640 Point aRelPos0(aTailPoly.GetPoint(0)-aAnchor);
641 Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
642 NbcMove(aSiz); // Der ruft auch das SetRectsDirty()
645 Point SdrCaptionObj::GetRelativePos() const
647 return aTailPoly.GetPoint(0)-aAnchor;
650 void SdrCaptionObj::NbcSetAnchorPos(const Point& rPnt)
652 SdrRectObj::NbcSetAnchorPos(rPnt);
653 // !!!!! fehlende Impl.
656 const Point& SdrCaptionObj::GetAnchorPos() const
658 // !!!!! fehlende Impl.
659 return SdrRectObj::GetAnchorPos();
662 void SdrCaptionObj::RecalcSnapRect()
664 SdrRectObj::RecalcSnapRect();
665 // #i32599#
666 // maSnapRect.Union(aTailPoly.GetBoundRect());
667 // !!!!! fehlende Impl.
670 const Rectangle& SdrCaptionObj::GetSnapRect() const
672 return SdrRectObj::GetSnapRect();
675 void SdrCaptionObj::NbcSetSnapRect(const Rectangle& rRect)
677 // #i32599#
678 // Move back to see the rectangle of the underlying SdrRectObj
679 // as the SnapRect, without the TailPos. That simplifies SnapRect
680 // handling again, if not allows it at all...
681 SdrRectObj::NbcSetSnapRect(rRect);
684 const Rectangle& SdrCaptionObj::GetLogicRect() const
686 return aRect;
689 void SdrCaptionObj::NbcSetLogicRect(const Rectangle& rRect)
691 SdrRectObj::NbcSetLogicRect(rRect);
692 ImpRecalcTail();
695 const Point& SdrCaptionObj::GetTailPos() const
697 return aTailPoly[0];
700 void SdrCaptionObj::SetTailPos(const Point& rPos)
702 if (aTailPoly.GetSize()==0 || aTailPoly[0]!=rPos) {
703 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
704 // #110094#-14 SendRepaintBroadcast();
705 NbcSetTailPos(rPos);
706 SetChanged();
707 BroadcastObjectChange();
708 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
712 void SdrCaptionObj::NbcSetTailPos(const Point& rPos)
714 aTailPoly[0]=rPos;
715 ImpRecalcTail();
718 sal_uInt32 SdrCaptionObj::GetSnapPointCount() const
720 // !!!!! fehlende Impl.
721 return 0L;
724 Point SdrCaptionObj::GetSnapPoint(sal_uInt32 /*i*/) const
726 // !!!!! fehlende Impl.
727 return Point(0,0);
730 void SdrCaptionObj::SetModel(SdrModel* pNewModel)
732 SdrRectObj::SetModel(pNewModel);
733 ImpRecalcTail();
736 void SdrCaptionObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
738 SdrRectObj::Notify(rBC,rHint);
739 ImpRecalcTail();
742 SdrObjGeoData* SdrCaptionObj::NewGeoData() const
744 return new SdrCaptObjGeoData;
747 void SdrCaptionObj::SaveGeoData(SdrObjGeoData& rGeo) const
749 SdrRectObj::SaveGeoData(rGeo);
750 SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo;
751 rCGeo.aTailPoly=aTailPoly;
754 void SdrCaptionObj::RestGeoData(const SdrObjGeoData& rGeo)
756 SdrRectObj::RestGeoData(rGeo);
757 SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo;
758 aTailPoly=rCGeo.aTailPoly;
761 SdrObject* SdrCaptionObj::DoConvertToPolyObj(BOOL bBezier) const
762 { // #42334# - Convert implementiert
763 SdrObject* pRect=SdrRectObj::DoConvertToPolyObj(bBezier);
764 SdrObject* pTail = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly.getB2DPolygon()), sal_False, bBezier);
765 SdrObject* pRet=(pTail!=NULL) ? pTail : pRect;
766 if (pTail!=NULL && pRect!=NULL) {
767 FASTBOOL bInsRect=TRUE;
768 FASTBOOL bInsTail=TRUE;
769 SdrObjList* pOL=pTail->GetSubList();
770 if (pOL!=NULL) { pRet=pRect; bInsTail=FALSE; }
771 if (pOL==NULL) pOL=pRect->GetSubList();
772 if (pOL!=NULL) { pRet=pRect; bInsRect=FALSE; }
773 if (pOL==NULL) {
774 SdrObjGroup* pGrp=new SdrObjGroup;
775 pOL=pGrp->GetSubList();
776 pRet=pGrp;
778 if (bInsRect) pOL->NbcInsertObject(pRect);
779 if (bInsTail) pOL->NbcInsertObject(pTail,0);
781 return pRet;
784 // #i32599#
785 // Add own implementation for TRSetBaseGeometry to handle TailPos over changes.
786 void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
788 // break up matrix
789 basegfx::B2DTuple aScale;
790 basegfx::B2DTuple aTranslate;
791 double fRotate, fShearX;
792 rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
794 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
795 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
796 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
798 aScale.setX(fabs(aScale.getX()));
799 aScale.setY(fabs(aScale.getY()));
800 fRotate = fmod(fRotate + F_PI, F_2PI);
803 // force metric to pool metric
804 SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0);
805 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
807 switch(eMapUnit)
809 case SFX_MAPUNIT_TWIP :
811 // position
812 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
813 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
815 // size
816 aScale.setX(ImplMMToTwips(aScale.getX()));
817 aScale.setY(ImplMMToTwips(aScale.getY()));
819 break;
821 default:
823 DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
828 // if anchor is used, make position relative to it
829 if( pModel->IsWriter() )
831 if(GetAnchorPos().X() || GetAnchorPos().Y())
833 aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
837 // build BaseRect
838 Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY()));
839 Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY())));
841 // set BaseRect, but rescue TailPos over this call
842 const Point aTailPoint = GetTailPos();
843 SetSnapRect(aBaseRect);
844 SetTailPos(aTailPoint);
845 ImpRecalcTail();
848 // geometry access
849 ::basegfx::B2DPolygon SdrCaptionObj::getTailPolygon() const
851 return aTailPoly.getB2DPolygon();
854 // eof