bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdocapt.cxx
blob342f392c8f803c561788a258771b0bc8af0f0496
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <basegfx/matrix/b2dhommatrix.hxx>
21 #include <basegfx/polygon/b2dpolygon.hxx>
22 #include <basegfx/polygon/b2dpolygontools.hxx>
23 #include <basegfx/range/b2drange.hxx>
24 #include <basegfx/tuple/b2dtuple.hxx>
25 #include <editeng/eeitem.hxx>
26 #include <svl/style.hxx>
27 #include <tools/bigint.hxx>
28 #include <tools/helpers.hxx>
30 #include "svdconv.hxx"
31 #include "svdglob.hxx"
32 #include "svx/svdstr.hrc"
34 #include <sdr/contact/viewcontactofsdrcaptionobj.hxx>
35 #include <sdr/properties/captionproperties.hxx>
36 #include <svx/sdrhittesthelper.hxx>
37 #include <svx/svddrag.hxx>
38 #include <svx/svdetc.hxx>
39 #include <svx/svdhdl.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdocapt.hxx>
42 #include <svx/svdogrp.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdpool.hxx>
45 #include <svx/svdtrans.hxx>
46 #include <svx/svdview.hxx>
47 #include <svx/sxcaitm.hxx>
48 #include <svx/sxcecitm.hxx>
49 #include <svx/sxcgitm.hxx>
50 #include <svx/sxcllitm.hxx>
51 #include <svx/sxctitm.hxx>
52 #include <svx/xflclit.hxx>
53 #include <svx/xflhtit.hxx>
54 #include <svx/xfltrit.hxx>
55 #include <svx/xlnwtit.hxx>
56 #include <svx/xpoly.hxx>
57 #include <svx/xpool.hxx>
61 enum EscDir {LKS,RTS,OBN,UNT};
63 class ImpCaptParams
65 public:
66 SdrCaptionType eType;
67 long nAngle;
68 long nGap;
69 long nEscRel;
70 long nEscAbs;
71 long nLineLen;
72 SdrCaptionEscDir eEscDir;
73 bool bFitLineLen;
74 bool bEscRel;
75 bool bFixedAngle;
77 public:
78 ImpCaptParams()
80 eType =SDRCAPT_TYPE3;
81 bFixedAngle=false;
82 nAngle =4500;
83 nGap =0;
84 eEscDir =SDRCAPT_ESCHORIZONTAL;
85 bEscRel =true;
86 nEscRel =5000;
87 nEscAbs =0;
88 nLineLen =0;
89 bFitLineLen=true;
91 void CalcEscPos(const Point& rTail, const Rectangle& rRect, Point& rPt, EscDir& rDir) const;
94 void ImpCaptParams::CalcEscPos(const Point& rTailPt, const Rectangle& rRect, Point& rPt, EscDir& rDir) const
96 Point aTl(rTailPt); // copy locally for performance reasons
97 long nX,nY;
98 if (bEscRel) {
99 nX=rRect.Right()-rRect.Left();
100 nX=BigMulDiv(nX,nEscRel,10000);
101 nY=rRect.Bottom()-rRect.Top();
102 nY=BigMulDiv(nY,nEscRel,10000);
103 } else {
104 nX=nEscAbs;
105 nY=nEscAbs;
107 nX+=rRect.Left();
108 nY+=rRect.Top();
109 Point aBestPt;
110 EscDir eBestDir=LKS;
111 bool bTryH=eEscDir==SDRCAPT_ESCBESTFIT;
112 if (!bTryH) {
113 if (eType!=SDRCAPT_TYPE1) {
114 bTryH=eEscDir==SDRCAPT_ESCHORIZONTAL;
115 } else {
116 bTryH=eEscDir==SDRCAPT_ESCVERTICAL;
119 bool bTryV=eEscDir==SDRCAPT_ESCBESTFIT;
120 if (!bTryV) {
121 if (eType!=SDRCAPT_TYPE1) {
122 bTryV=eEscDir==SDRCAPT_ESCVERTICAL;
123 } else {
124 bTryV=eEscDir==SDRCAPT_ESCHORIZONTAL;
128 if (bTryH) {
129 Point aLft(rRect.Left()-nGap,nY);
130 Point aRgt(rRect.Right()+nGap,nY);
131 bool bLft=(aTl.X()-aLft.X()<aRgt.X()-aTl.X());
132 if (bLft) {
133 eBestDir=LKS;
134 aBestPt=aLft;
135 } else {
136 eBestDir=RTS;
137 aBestPt=aRgt;
140 if (bTryV) {
141 Point aTop(nX,rRect.Top()-nGap);
142 Point aBtm(nX,rRect.Bottom()+nGap);
143 bool bTop=(aTl.Y()-aTop.Y()<aBtm.Y()-aTl.Y());
144 Point aBest2;
145 EscDir eBest2;
146 if (bTop) {
147 eBest2=OBN;
148 aBest2=aTop;
149 } else {
150 eBest2=UNT;
151 aBest2=aBtm;
153 bool bTakeIt=eEscDir!=SDRCAPT_ESCBESTFIT;
154 if (!bTakeIt) {
155 BigInt aHorX(aBestPt.X()-aTl.X()); aHorX*=aHorX;
156 BigInt aHorY(aBestPt.Y()-aTl.Y()); aHorY*=aHorY;
157 BigInt aVerX(aBest2.X()-aTl.X()); aVerX*=aVerX;
158 BigInt aVerY(aBest2.Y()-aTl.Y()); aVerY*=aVerY;
159 if (eType!=SDRCAPT_TYPE1) {
160 bTakeIt=aVerX+aVerY<aHorX+aHorY;
161 } else {
162 bTakeIt=aVerX+aVerY>=aHorX+aHorY;
165 if (bTakeIt) {
166 aBestPt=aBest2;
167 eBestDir=eBest2;
170 rPt=aBestPt;
171 rDir=eBestDir;
175 // BaseProperties section
177 sdr::properties::BaseProperties* SdrCaptionObj::CreateObjectSpecificProperties()
179 return new sdr::properties::CaptionProperties(*this);
183 // DrawContact section
185 sdr::contact::ViewContact* SdrCaptionObj::CreateObjectSpecificViewContact()
187 return new sdr::contact::ViewContactOfSdrCaptionObj(*this);
192 TYPEINIT1(SdrCaptionObj,SdrRectObj);
194 SdrCaptionObj::SdrCaptionObj():
195 SdrRectObj(OBJ_TEXT),
196 aTailPoly(3), // default size: 3 points = 2 lines
197 mbSpecialTextBoxShadow(false),
198 mbFixedTail(false)
202 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect, const Point& rTail):
203 SdrRectObj(OBJ_TEXT,rRect),
204 aTailPoly(3), // default size: 3 points = 2 lines
205 mbSpecialTextBoxShadow(false),
206 mbFixedTail(false)
208 aTailPoly[0]=maFixedTailPos=rTail;
211 SdrCaptionObj::~SdrCaptionObj()
215 void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
217 rInfo.bRotateFreeAllowed=false;
218 rInfo.bRotate90Allowed =false;
219 rInfo.bMirrorFreeAllowed=false;
220 rInfo.bMirror45Allowed =false;
221 rInfo.bMirror90Allowed =false;
222 rInfo.bTransparenceAllowed = false;
223 rInfo.bGradientAllowed = false;
224 rInfo.bShearAllowed =false;
225 rInfo.bEdgeRadiusAllowed=false;
226 rInfo.bCanConvToPath =true;
227 rInfo.bCanConvToPoly =true;
228 rInfo.bCanConvToPathLineToArea=false;
229 rInfo.bCanConvToPolyLineToArea=false;
230 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
233 sal_uInt16 SdrCaptionObj::GetObjIdentifier() const
235 return sal_uInt16(OBJ_CAPTION);
238 SdrCaptionObj* SdrCaptionObj::Clone() const
240 return CloneHelper< SdrCaptionObj >();
243 OUString SdrCaptionObj::TakeObjNameSingul() const
245 OUStringBuffer sName(ImpGetResStr(STR_ObjNameSingulCAPTION));
247 OUString aName(GetName());
248 if (!aName.isEmpty())
250 sName.append(' ');
251 sName.append('\'');
252 sName.append(aName);
253 sName.append('\'');
256 return sName.makeStringAndClear();
259 OUString SdrCaptionObj::TakeObjNamePlural() const
261 return ImpGetResStr(STR_ObjNamePluralCAPTION);
264 basegfx::B2DPolyPolygon SdrCaptionObj::TakeXorPoly() const
266 basegfx::B2DPolyPolygon aPolyPoly(SdrRectObj::TakeXorPoly());
267 aPolyPoly.append(aTailPoly.getB2DPolygon());
269 return aPolyPoly;
272 sal_uInt32 SdrCaptionObj::GetHdlCount() const
274 sal_uInt32 nCount1(SdrRectObj::GetHdlCount());
275 // Currently only dragging the tail's end is implemented.
276 return nCount1 + 1L;
279 SdrHdl* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum) const
281 const sal_uInt32 nRectHdlAnz(SdrRectObj::GetHdlCount());
283 if(nHdlNum < nRectHdlAnz)
285 return SdrRectObj::GetHdl(nHdlNum);
287 else
289 sal_uInt32 nPntNum(nHdlNum);
290 nPntNum -= nRectHdlAnz;
292 if(nPntNum < aTailPoly.GetSize())
294 SdrHdl* pHdl = new SdrHdl(aTailPoly.GetPoint((sal_uInt16)nPntNum), HDL_POLY);
295 pHdl->SetPolyNum(1L);
296 pHdl->SetPointNum(nPntNum);
297 return pHdl;
299 else
301 return 0L;
308 bool SdrCaptionObj::hasSpecialDrag() const
310 return true;
313 bool SdrCaptionObj::beginSpecialDrag(SdrDragStat& rDrag) const
315 const SdrHdl* pHdl = rDrag.GetHdl();
316 rDrag.SetEndDragChangesAttributes(true);
317 rDrag.SetEndDragChangesGeoAndAttributes(true);
319 if(pHdl && 0 == pHdl->GetPolyNum())
321 return SdrRectObj::beginSpecialDrag(rDrag);
323 else
325 rDrag.SetOrtho8Possible(true);
327 if(!pHdl)
329 if (bMovProt)
330 return false;
332 rDrag.SetNoSnap(true);
333 rDrag.SetActionRect(maRect);
335 Point aHit(rDrag.GetStart());
337 if(rDrag.GetPageView() && SdrObjectPrimitiveHit(*this, aHit, 0, *rDrag.GetPageView(), 0, false))
339 return true;
342 else
344 if((1 == pHdl->GetPolyNum()) && (0 == pHdl->GetPointNum()))
345 return true;
349 return false;
352 bool SdrCaptionObj::applySpecialDrag(SdrDragStat& rDrag)
354 const SdrHdl* pHdl = rDrag.GetHdl();
356 if(pHdl && 0 == pHdl->GetPolyNum())
358 const bool bRet(SdrRectObj::applySpecialDrag(rDrag));
359 ImpRecalcTail();
360 ActionChanged();
362 return bRet;
364 else
366 Point aDelt(rDrag.GetNow()-rDrag.GetStart());
368 if(!pHdl)
370 maRect.Move(aDelt.X(),aDelt.Y());
372 else
374 aTailPoly[0] += aDelt;
377 ImpRecalcTail();
378 ActionChanged();
380 return true;
384 OUString SdrCaptionObj::getSpecialDragComment(const SdrDragStat& rDrag) const
386 const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
388 if(bCreateComment)
390 return OUString();
392 else
394 const SdrHdl* pHdl = rDrag.GetHdl();
396 if(pHdl && 0 == pHdl->GetPolyNum())
398 return SdrRectObj::getSpecialDragComment(rDrag);
400 else
402 OUString aStr;
404 if(!pHdl)
406 ImpTakeDescriptionStr(STR_DragCaptFram, aStr);
408 else
410 ImpTakeDescriptionStr(STR_DragCaptTail, aStr);
413 return aStr;
420 void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams& rPara) const
422 const SfxItemSet& rSet = GetObjectItemSet();
423 rPara.eType =static_cast<const SdrCaptionTypeItem&> (rSet.Get(SDRATTR_CAPTIONTYPE )).GetValue();
424 rPara.bFixedAngle=static_cast<const SdrOnOffItem&> (rSet.Get(SDRATTR_CAPTIONFIXEDANGLE)).GetValue();
425 rPara.nAngle =static_cast<const SdrCaptionAngleItem&> (rSet.Get(SDRATTR_CAPTIONANGLE )).GetValue();
426 rPara.nGap =static_cast<const SdrCaptionGapItem&> (rSet.Get(SDRATTR_CAPTIONGAP )).GetValue();
427 rPara.eEscDir =static_cast<const SdrCaptionEscDirItem&> (rSet.Get(SDRATTR_CAPTIONESCDIR )).GetValue();
428 rPara.bEscRel =static_cast<const SdrCaptionEscIsRelItem&> (rSet.Get(SDRATTR_CAPTIONESCISREL )).GetValue();
429 rPara.nEscRel =static_cast<const SdrCaptionEscRelItem&> (rSet.Get(SDRATTR_CAPTIONESCREL )).GetValue();
430 rPara.nEscAbs =static_cast<const SdrCaptionEscAbsItem&> (rSet.Get(SDRATTR_CAPTIONESCABS )).GetValue();
431 rPara.nLineLen =static_cast<const SdrCaptionLineLenItem&> (rSet.Get(SDRATTR_CAPTIONLINELEN )).GetValue();
432 rPara.bFitLineLen=static_cast<const SdrCaptionFitLineLenItem&>(rSet.Get(SDRATTR_CAPTIONFITLINELEN)).GetValue();
435 void SdrCaptionObj::ImpRecalcTail()
437 ImpCaptParams aPara;
438 ImpGetCaptParams(aPara);
439 ImpCalcTail(aPara, aTailPoly, maRect);
440 SetRectsDirty();
441 SetXPolyDirty();
444 // #i35971#
445 // SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack.
446 // I really wonder why this had not triggered problems before. I am
447 // sure there are some places where SetTailPos() is called at least
448 // twice or SetSnapRect after it again just to work around this.
449 // Changed this method to not do that.
450 // Also found why this has been done: For interactive dragging of the
451 // tail end pos for SDRCAPT_TYPE1. This sure was the simplest method
452 // to achieve this, at the cost of making a whole group of const methods
453 // of this object implicitly change the object's position.
454 void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
456 Polygon aPol(2);
457 Point aTl(rPoly[0]);
459 aPol[0] = aTl;
460 aPol[1] = aTl;
462 EscDir eEscDir;
463 Point aEscPos;
465 rPara.CalcEscPos(aTl, rRect, aEscPos, eEscDir);
466 aPol[1] = aEscPos;
468 if(eEscDir==LKS || eEscDir==RTS)
470 aPol[0].X() = aEscPos.X();
472 else
474 aPol[0].Y() = aEscPos.Y();
477 rPoly = aPol;
480 void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
481 { // Gap/EscDir/EscPos/Angle
482 Polygon aPol(2);
483 Point aTl(rPoly[0]);
484 aPol[0]=aTl;
486 EscDir eEscDir;
487 Point aEscPos;
488 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
489 aPol[1]=aEscPos;
491 if (!rPara.bFixedAngle) {
492 // TODO: Implementation missing.
494 rPoly=aPol;
497 void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
498 { // Gap/EscDir/EscPos/Angle/LineLen
499 Polygon aPol(3);
500 Point aTl(rPoly[0]);
501 aPol[0]=aTl;
503 EscDir eEscDir;
504 Point aEscPos;
505 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
506 aPol[1]=aEscPos;
507 aPol[2]=aEscPos;
509 if (eEscDir==LKS || eEscDir==RTS) {
510 if (rPara.bFitLineLen) {
511 aPol[1].X()=(aTl.X()+aEscPos.X())/2;
512 } else {
513 if (eEscDir==LKS) aPol[1].X()-=rPara.nLineLen;
514 else aPol[1].X()+=rPara.nLineLen;
516 } else {
517 if (rPara.bFitLineLen) {
518 aPol[1].Y()=(aTl.Y()+aEscPos.Y())/2;
519 } else {
520 if (eEscDir==OBN) aPol[1].Y()-=rPara.nLineLen;
521 else aPol[1].Y()+=rPara.nLineLen;
524 if (!rPara.bFixedAngle) {
525 // TODO: Implementation missing.
527 rPoly=aPol;
530 void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
532 ImpCalcTail3(rPara,rPoly,rRect);
535 void SdrCaptionObj::ImpCalcTail(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
537 switch (rPara.eType) {
538 case SDRCAPT_TYPE1: ImpCalcTail1(rPara,rPoly,rRect); break;
539 case SDRCAPT_TYPE2: ImpCalcTail2(rPara,rPoly,rRect); break;
540 case SDRCAPT_TYPE3: ImpCalcTail3(rPara,rPoly,rRect); break;
541 case SDRCAPT_TYPE4: ImpCalcTail4(rPara,rPoly,rRect); break;
545 bool SdrCaptionObj::BegCreate(SdrDragStat& rStat)
547 if (maRect.IsEmpty()) return false; // Create currently only works with the given Rect
549 ImpCaptParams aPara;
550 ImpGetCaptParams(aPara);
551 maRect.SetPos(rStat.GetNow());
552 aTailPoly[0]=rStat.GetStart();
553 ImpCalcTail(aPara,aTailPoly,maRect);
554 rStat.SetActionRect(maRect);
555 return true;
558 bool SdrCaptionObj::MovCreate(SdrDragStat& rStat)
560 ImpCaptParams aPara;
561 ImpGetCaptParams(aPara);
562 maRect.SetPos(rStat.GetNow());
563 ImpCalcTail(aPara,aTailPoly,maRect);
564 rStat.SetActionRect(maRect);
565 SetBoundRectDirty();
566 bSnapRectDirty=true;
567 return true;
570 bool SdrCaptionObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
572 ImpCaptParams aPara;
573 ImpGetCaptParams(aPara);
574 maRect.SetPos(rStat.GetNow());
575 ImpCalcTail(aPara,aTailPoly,maRect);
576 SetRectsDirty();
577 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
580 bool SdrCaptionObj::BckCreate(SdrDragStat& /*rStat*/)
582 return false;
585 void SdrCaptionObj::BrkCreate(SdrDragStat& /*rStat*/)
589 basegfx::B2DPolyPolygon SdrCaptionObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
591 basegfx::B2DPolyPolygon aRetval;
592 const basegfx::B2DRange aRange(maRect.Left(), maRect.Top(), maRect.Right(), maRect.Bottom());
593 aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
594 aRetval.append(aTailPoly.getB2DPolygon());
595 return aRetval;
598 Pointer SdrCaptionObj::GetCreatePointer() const
600 return Pointer(PointerStyle::DrawCaption);
603 void SdrCaptionObj::NbcMove(const Size& rSiz)
605 SdrRectObj::NbcMove(rSiz);
606 MovePoly(aTailPoly,rSiz);
607 if(mbFixedTail)
608 SetTailPos(GetFixedTailPos());
611 void SdrCaptionObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
613 SdrRectObj::NbcResize(rRef,xFact,yFact);
614 ResizePoly(aTailPoly,rRef,xFact,yFact);
615 ImpRecalcTail();
616 if(mbFixedTail)
617 SetTailPos(GetFixedTailPos());
620 void SdrCaptionObj::NbcSetRelativePos(const Point& rPnt)
622 Point aRelPos0(aTailPoly.GetPoint(0)-aAnchor);
623 Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
624 NbcMove(aSiz); // This also calls SetRectsDirty()
627 Point SdrCaptionObj::GetRelativePos() const
629 return aTailPoly.GetPoint(0)-aAnchor;
632 void SdrCaptionObj::NbcSetAnchorPos(const Point& rPnt)
634 SdrRectObj::NbcSetAnchorPos(rPnt);
635 // TODO: Implementation missing.
638 const Point& SdrCaptionObj::GetAnchorPos() const
640 // TODO: Implementation missing.
641 return SdrRectObj::GetAnchorPos();
644 void SdrCaptionObj::RecalcSnapRect()
646 SdrRectObj::RecalcSnapRect();
647 // #i32599#
648 // TODO: Implementation missing.
651 const Rectangle& SdrCaptionObj::GetSnapRect() const
653 return SdrRectObj::GetSnapRect();
656 void SdrCaptionObj::NbcSetSnapRect(const Rectangle& rRect)
658 // #i32599#
659 // Move back to see the rectangle of the underlying SdrRectObj
660 // as the SnapRect, without the TailPos. That simplifies SnapRect
661 // handling again, if not allows it at all...
662 SdrRectObj::NbcSetSnapRect(rRect);
665 const Rectangle& SdrCaptionObj::GetLogicRect() const
667 return maRect;
670 void SdrCaptionObj::NbcSetLogicRect(const Rectangle& rRect)
672 SdrRectObj::NbcSetLogicRect(rRect);
673 ImpRecalcTail();
676 const Point& SdrCaptionObj::GetTailPos() const
678 return aTailPoly[0];
681 void SdrCaptionObj::SetTailPos(const Point& rPos)
683 if (aTailPoly.GetSize()==0 || aTailPoly[0]!=rPos) {
684 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
685 NbcSetTailPos(rPos);
686 SetChanged();
687 BroadcastObjectChange();
688 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
692 void SdrCaptionObj::NbcSetTailPos(const Point& rPos)
694 aTailPoly[0]=rPos;
695 ImpRecalcTail();
698 sal_uInt32 SdrCaptionObj::GetSnapPointCount() const
700 // TODO: Implementation missing.
701 return 0L;
704 Point SdrCaptionObj::GetSnapPoint(sal_uInt32 /*i*/) const
706 // TODO: Implementation missing.
707 return Point(0,0);
710 void SdrCaptionObj::SetModel(SdrModel* pNewModel)
712 SdrRectObj::SetModel(pNewModel);
713 ImpRecalcTail();
716 void SdrCaptionObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
718 SdrRectObj::Notify(rBC,rHint);
719 ImpRecalcTail();
722 SdrObjGeoData* SdrCaptionObj::NewGeoData() const
724 return new SdrCaptObjGeoData;
727 void SdrCaptionObj::SaveGeoData(SdrObjGeoData& rGeo) const
729 SdrRectObj::SaveGeoData(rGeo);
730 SdrCaptObjGeoData& rCGeo=static_cast<SdrCaptObjGeoData&>(rGeo);
731 rCGeo.aTailPoly=aTailPoly;
734 void SdrCaptionObj::RestGeoData(const SdrObjGeoData& rGeo)
736 SdrRectObj::RestGeoData(rGeo);
737 const SdrCaptObjGeoData& rCGeo=static_cast<const SdrCaptObjGeoData&>(rGeo);
738 aTailPoly=rCGeo.aTailPoly;
741 SdrObject* SdrCaptionObj::DoConvertToPolyObj(bool bBezier, bool bAddText) const
743 SdrObject* pRect=SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
744 SdrObject* pTail = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly.getB2DPolygon()), false, bBezier);
745 SdrObject* pRet=(pTail!=NULL) ? pTail : pRect;
746 if (pTail!=NULL && pRect!=NULL) {
747 bool bInsRect = true;
748 bool bInsTail = true;
749 SdrObjList* pOL=pTail->GetSubList();
750 if (pOL!=NULL) { pRet=pRect; bInsTail = false; }
751 if (pOL==NULL) pOL=pRect->GetSubList();
752 if (pOL!=NULL) { pRet=pRect; bInsRect = false; }
753 if (pOL==NULL) {
754 SdrObjGroup* pGrp=new SdrObjGroup;
755 pOL=pGrp->GetSubList();
756 pRet=pGrp;
758 if (bInsRect) pOL->NbcInsertObject(pRect);
759 if (bInsTail) pOL->NbcInsertObject(pTail,0);
761 return pRet;
764 // #i32599#
765 // Add own implementation for TRSetBaseGeometry to handle TailPos over changes.
766 void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
768 // break up matrix
769 basegfx::B2DTuple aScale;
770 basegfx::B2DTuple aTranslate;
771 double fRotate, fShearX;
772 rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
774 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
775 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
776 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
778 aScale.setX(fabs(aScale.getX()));
779 aScale.setY(fabs(aScale.getY()));
780 fRotate = fmod(fRotate + F_PI, F_2PI);
783 // force metric to pool metric
784 SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0);
785 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
787 switch(eMapUnit)
789 case SFX_MAPUNIT_TWIP :
791 // position
792 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
793 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
795 // size
796 aScale.setX(ImplMMToTwips(aScale.getX()));
797 aScale.setY(ImplMMToTwips(aScale.getY()));
799 break;
801 default:
803 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
808 // if anchor is used, make position relative to it
809 if( pModel->IsWriter() )
811 if(GetAnchorPos().X() || GetAnchorPos().Y())
813 aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
817 // build BaseRect
818 Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY()));
819 Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY())));
821 // set BaseRect, but rescue TailPos over this call
822 const Point aTailPoint = GetTailPos();
823 SetSnapRect(aBaseRect);
824 SetTailPos(aTailPoint);
825 ImpRecalcTail();
828 // geometry access
829 basegfx::B2DPolygon SdrCaptionObj::getTailPolygon() const
831 return aTailPoly.getB2DPolygon();
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */