update credits
[LibreOffice.git] / svx / source / svdraw / svdocapt.cxx
blobde6779e1c78cee164d706627a751a249375510fd
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 <tools/bigint.hxx>
21 #include <tools/helpers.hxx>
22 #include <svx/xlnwtit.hxx>
23 #include <svl/style.hxx>
24 #include <svx/svdocapt.hxx>
25 #include <svx/xpool.hxx>
26 #include <svx/xpoly.hxx>
27 #include <svx/svdattrx.hxx>
28 #include <svx/svdpool.hxx>
29 #include <svx/svdetc.hxx>
30 #include <svx/svdtrans.hxx>
31 #include <svx/svdhdl.hxx>
32 #include <svx/svddrag.hxx>
33 #include <svx/svdmodel.hxx>
34 #include <svx/svdview.hxx> // for RectSnap
35 #include "svx/svdglob.hxx" // StringCache
36 #include "svx/svdstr.hrc" // the object's name
37 #include <svx/svdogrp.hxx>
38 #include <svx/svdpage.hxx>
39 #include <svx/xflhtit.hxx>
40 #include <svx/xflclit.hxx>
41 #include <svx/xfltrit.hxx>
42 #include <editeng/eeitem.hxx>
43 #include <svx/sdr/properties/captionproperties.hxx>
44 #include <svx/sdr/contact/viewcontactofsdrcaptionobj.hxx>
45 #include <basegfx/tuple/b2dtuple.hxx>
46 #include <basegfx/matrix/b2dhommatrix.hxx>
47 #include <basegfx/polygon/b2dpolygon.hxx>
48 #include <basegfx/range/b2drange.hxx>
49 #include <basegfx/polygon/b2dpolygontools.hxx>
50 #include <svx/sdrhittesthelper.hxx>
51 #include "svdconv.hxx"
53 ////////////////////////////////////////////////////////////////////////////////////////////////////
55 enum EscDir {LKS,RTS,OBN,UNT};
57 class ImpCaptParams
59 public:
60 SdrCaptionType eType;
61 long nAngle;
62 long nGap;
63 long nEscRel;
64 long nEscAbs;
65 long nLineLen;
66 SdrCaptionEscDir eEscDir;
67 bool bFitLineLen;
68 bool bEscRel;
69 bool bFixedAngle;
71 public:
72 ImpCaptParams()
74 eType =SDRCAPT_TYPE3;
75 bFixedAngle=sal_False;
76 nAngle =4500;
77 nGap =0;
78 eEscDir =SDRCAPT_ESCHORIZONTAL;
79 bEscRel =sal_True;
80 nEscRel =5000;
81 nEscAbs =0;
82 nLineLen =0;
83 bFitLineLen=sal_True;
85 void CalcEscPos(const Point& rTail, const Rectangle& rRect, Point& rPt, EscDir& rDir) const;
88 void ImpCaptParams::CalcEscPos(const Point& rTailPt, const Rectangle& rRect, Point& rPt, EscDir& rDir) const
90 Point aTl(rTailPt); // copy locally for performance reasons
91 long nX,nY;
92 if (bEscRel) {
93 nX=rRect.Right()-rRect.Left();
94 nX=BigMulDiv(nX,nEscRel,10000);
95 nY=rRect.Bottom()-rRect.Top();
96 nY=BigMulDiv(nY,nEscRel,10000);
97 } else {
98 nX=nEscAbs;
99 nY=nEscAbs;
101 nX+=rRect.Left();
102 nY+=rRect.Top();
103 Point aBestPt;
104 EscDir eBestDir=LKS;
105 bool bTryH=eEscDir==SDRCAPT_ESCBESTFIT;
106 if (!bTryH) {
107 if (eType!=SDRCAPT_TYPE1) {
108 bTryH=eEscDir==SDRCAPT_ESCHORIZONTAL;
109 } else {
110 bTryH=eEscDir==SDRCAPT_ESCVERTICAL;
113 bool bTryV=eEscDir==SDRCAPT_ESCBESTFIT;
114 if (!bTryV) {
115 if (eType!=SDRCAPT_TYPE1) {
116 bTryV=eEscDir==SDRCAPT_ESCVERTICAL;
117 } else {
118 bTryV=eEscDir==SDRCAPT_ESCHORIZONTAL;
122 if (bTryH) {
123 Point aLft(rRect.Left()-nGap,nY);
124 Point aRgt(rRect.Right()+nGap,nY);
125 bool bLft=(aTl.X()-aLft.X()<aRgt.X()-aTl.X());
126 if (bLft) {
127 eBestDir=LKS;
128 aBestPt=aLft;
129 } else {
130 eBestDir=RTS;
131 aBestPt=aRgt;
134 if (bTryV) {
135 Point aTop(nX,rRect.Top()-nGap);
136 Point aBtm(nX,rRect.Bottom()+nGap);
137 bool bTop=(aTl.Y()-aTop.Y()<aBtm.Y()-aTl.Y());
138 Point aBest2;
139 EscDir eBest2;
140 if (bTop) {
141 eBest2=OBN;
142 aBest2=aTop;
143 } else {
144 eBest2=UNT;
145 aBest2=aBtm;
147 bool bTakeIt=eEscDir!=SDRCAPT_ESCBESTFIT;
148 if (!bTakeIt) {
149 BigInt aHorX(aBestPt.X()-aTl.X()); aHorX*=aHorX;
150 BigInt aHorY(aBestPt.Y()-aTl.Y()); aHorY*=aHorY;
151 BigInt aVerX(aBest2.X()-aTl.X()); aVerX*=aVerX;
152 BigInt aVerY(aBest2.Y()-aTl.Y()); aVerY*=aVerY;
153 if (eType!=SDRCAPT_TYPE1) {
154 bTakeIt=aVerX+aVerY<aHorX+aHorY;
155 } else {
156 bTakeIt=aVerX+aVerY>=aHorX+aHorY;
159 if (bTakeIt) {
160 aBestPt=aBest2;
161 eBestDir=eBest2;
164 rPt=aBestPt;
165 rDir=eBestDir;
168 //////////////////////////////////////////////////////////////////////////////
169 // BaseProperties section
171 sdr::properties::BaseProperties* SdrCaptionObj::CreateObjectSpecificProperties()
173 return new sdr::properties::CaptionProperties(*this);
176 //////////////////////////////////////////////////////////////////////////////
177 // DrawContact section
179 sdr::contact::ViewContact* SdrCaptionObj::CreateObjectSpecificViewContact()
181 return new sdr::contact::ViewContactOfSdrCaptionObj(*this);
184 //////////////////////////////////////////////////////////////////////////////
186 TYPEINIT1(SdrCaptionObj,SdrRectObj);
188 SdrCaptionObj::SdrCaptionObj():
189 SdrRectObj(OBJ_TEXT),
190 aTailPoly(3), // default size: 3 points = 2 lines
191 mbSpecialTextBoxShadow(sal_False),
192 mbFixedTail(sal_False)
196 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect, const Point& rTail):
197 SdrRectObj(OBJ_TEXT,rRect),
198 aTailPoly(3), // default size: 3 points = 2 lines
199 mbSpecialTextBoxShadow(sal_False),
200 mbFixedTail(sal_False)
202 aTailPoly[0]=maFixedTailPos=rTail;
205 SdrCaptionObj::~SdrCaptionObj()
209 void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
211 rInfo.bRotateFreeAllowed=sal_False;
212 rInfo.bRotate90Allowed =sal_False;
213 rInfo.bMirrorFreeAllowed=sal_False;
214 rInfo.bMirror45Allowed =sal_False;
215 rInfo.bMirror90Allowed =sal_False;
216 rInfo.bTransparenceAllowed = sal_False;
217 rInfo.bGradientAllowed = sal_False;
218 rInfo.bShearAllowed =sal_False;
219 rInfo.bEdgeRadiusAllowed=sal_False;
220 rInfo.bCanConvToPath =sal_True;
221 rInfo.bCanConvToPoly =sal_True;
222 rInfo.bCanConvToPathLineToArea=sal_False;
223 rInfo.bCanConvToPolyLineToArea=sal_False;
224 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
227 sal_uInt16 SdrCaptionObj::GetObjIdentifier() const
229 return sal_uInt16(OBJ_CAPTION);
232 SdrCaptionObj* SdrCaptionObj::Clone() const
234 return CloneHelper< SdrCaptionObj >();
237 void SdrCaptionObj::TakeObjNameSingul(XubString& rName) const
239 rName=ImpGetResStr(STR_ObjNameSingulCAPTION);
241 String aName( GetName() );
242 if(aName.Len())
244 rName += sal_Unicode(' ');
245 rName += sal_Unicode('\'');
246 rName += aName;
247 rName += sal_Unicode('\'');
251 void SdrCaptionObj::TakeObjNamePlural(XubString& rName) const
253 rName=ImpGetResStr(STR_ObjNamePluralCAPTION);
256 basegfx::B2DPolyPolygon SdrCaptionObj::TakeXorPoly() const
258 basegfx::B2DPolyPolygon aPolyPoly(SdrRectObj::TakeXorPoly());
259 aPolyPoly.append(aTailPoly.getB2DPolygon());
261 return aPolyPoly;
264 sal_uInt32 SdrCaptionObj::GetHdlCount() const
266 sal_uInt32 nAnz1(SdrRectObj::GetHdlCount());
267 // Currently only dragging the tail's end is implemented.
268 return nAnz1 + 1L;
271 SdrHdl* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum) const
273 const sal_uInt32 nRectHdlAnz(SdrRectObj::GetHdlCount());
275 if(nHdlNum < nRectHdlAnz)
277 return SdrRectObj::GetHdl(nHdlNum);
279 else
281 sal_uInt32 nPntNum(nHdlNum);
282 nPntNum -= nRectHdlAnz;
284 if(nPntNum < aTailPoly.GetSize())
286 SdrHdl* pHdl = new SdrHdl(aTailPoly.GetPoint((sal_uInt16)nPntNum), HDL_POLY);
287 pHdl->SetPolyNum(1L);
288 pHdl->SetPointNum(nPntNum);
289 return pHdl;
291 else
293 return 0L;
298 ////////////////////////////////////////////////////////////////////////////////////////////////////
300 bool SdrCaptionObj::hasSpecialDrag() const
302 return true;
305 bool SdrCaptionObj::beginSpecialDrag(SdrDragStat& rDrag) const
307 const SdrHdl* pHdl = rDrag.GetHdl();
308 rDrag.SetEndDragChangesAttributes(true);
309 rDrag.SetEndDragChangesGeoAndAttributes(true);
311 if(pHdl && 0 == pHdl->GetPolyNum())
313 return SdrRectObj::beginSpecialDrag(rDrag);
315 else
317 rDrag.SetOrtho8Possible(true);
319 if(!pHdl)
321 if (bMovProt)
322 return 0;
324 rDrag.SetNoSnap(true);
325 rDrag.SetActionRect(aRect);
327 Point aHit(rDrag.GetStart());
329 if(rDrag.GetPageView() && SdrObjectPrimitiveHit(*this, aHit, 0, *rDrag.GetPageView(), 0, false))
331 return true;
334 else
336 if((1 == pHdl->GetPolyNum()) && (0 == pHdl->GetPointNum()))
337 return true;
341 return false;
344 bool SdrCaptionObj::applySpecialDrag(SdrDragStat& rDrag)
346 const SdrHdl* pHdl = rDrag.GetHdl();
348 if(pHdl && 0 == pHdl->GetPolyNum())
350 const bool bRet(SdrRectObj::applySpecialDrag(rDrag));
351 ImpRecalcTail();
352 ActionChanged();
354 return bRet;
356 else
358 Point aDelt(rDrag.GetNow()-rDrag.GetStart());
360 if(!pHdl)
362 aRect.Move(aDelt.X(),aDelt.Y());
364 else
366 aTailPoly[0] += aDelt;
369 ImpRecalcTail();
370 ActionChanged();
372 return true;
376 String SdrCaptionObj::getSpecialDragComment(const SdrDragStat& rDrag) const
378 const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
380 if(bCreateComment)
382 return String();
384 else
386 const SdrHdl* pHdl = rDrag.GetHdl();
388 if(pHdl && 0 == pHdl->GetPolyNum())
390 return SdrRectObj::getSpecialDragComment(rDrag);
392 else
394 OUString aStr;
396 if(!pHdl)
398 ImpTakeDescriptionStr(STR_DragCaptFram, aStr);
400 else
402 ImpTakeDescriptionStr(STR_DragCaptTail, aStr);
405 return aStr;
410 ////////////////////////////////////////////////////////////////////////////////////////////////////
412 void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams& rPara) const
414 const SfxItemSet& rSet = GetObjectItemSet();
415 rPara.eType =((SdrCaptionTypeItem&) (rSet.Get(SDRATTR_CAPTIONTYPE ))).GetValue();
416 rPara.bFixedAngle=((SdrCaptionFixedAngleItem&)(rSet.Get(SDRATTR_CAPTIONANGLE ))).GetValue();
417 rPara.nAngle =((SdrCaptionAngleItem&) (rSet.Get(SDRATTR_CAPTIONFIXEDANGLE))).GetValue();
418 rPara.nGap =((SdrCaptionGapItem&) (rSet.Get(SDRATTR_CAPTIONGAP ))).GetValue();
419 rPara.eEscDir =((SdrCaptionEscDirItem&) (rSet.Get(SDRATTR_CAPTIONESCDIR ))).GetValue();
420 rPara.bEscRel =((SdrCaptionEscIsRelItem&) (rSet.Get(SDRATTR_CAPTIONESCISREL ))).GetValue();
421 rPara.nEscRel =((SdrCaptionEscRelItem&) (rSet.Get(SDRATTR_CAPTIONESCREL ))).GetValue();
422 rPara.nEscAbs =((SdrCaptionEscAbsItem&) (rSet.Get(SDRATTR_CAPTIONESCABS ))).GetValue();
423 rPara.nLineLen =((SdrCaptionLineLenItem&) (rSet.Get(SDRATTR_CAPTIONLINELEN ))).GetValue();
424 rPara.bFitLineLen=((SdrCaptionFitLineLenItem&)(rSet.Get(SDRATTR_CAPTIONFITLINELEN))).GetValue();
427 void SdrCaptionObj::ImpRecalcTail()
429 ImpCaptParams aPara;
430 ImpGetCaptParams(aPara);
431 ImpCalcTail(aPara,aTailPoly,aRect);
432 SetRectsDirty();
433 SetXPolyDirty();
436 // #i35971#
437 // SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack.
438 // I really wonder why this had not triggered problems before. I am
439 // sure there are some places where SetTailPos() is called at least
440 // twice or SetSnapRect after it again just to work around this.
441 // Changed this method to not do that.
442 // Also found why this has been done: For interactive dragging of the
443 // tail end pos for SDRCAPT_TYPE1. This sure was the simplest method
444 // to achieve this, at the cost of making a whole group of const methods
445 // of this object implicitly change the object's position.
446 void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
448 Polygon aPol(2);
449 Point aTl(rPoly[0]);
451 aPol[0] = aTl;
452 aPol[1] = aTl;
454 EscDir eEscDir;
455 Point aEscPos;
457 rPara.CalcEscPos(aTl, rRect, aEscPos, eEscDir);
458 aPol[1] = aEscPos;
460 if(eEscDir==LKS || eEscDir==RTS)
462 aPol[0].X() = aEscPos.X();
464 else
466 aPol[0].Y() = aEscPos.Y();
469 rPoly = aPol;
472 void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
473 { // Gap/EscDir/EscPos/Angle
474 Polygon aPol(2);
475 Point aTl(rPoly[0]);
476 aPol[0]=aTl;
478 EscDir eEscDir;
479 Point aEscPos;
480 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
481 aPol[1]=aEscPos;
483 if (!rPara.bFixedAngle) {
484 // TODO: Implementation missing.
486 rPoly=aPol;
489 void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
490 { // Gap/EscDir/EscPos/Angle/LineLen
491 Polygon aPol(3);
492 Point aTl(rPoly[0]);
493 aPol[0]=aTl;
495 EscDir eEscDir;
496 Point aEscPos;
497 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
498 aPol[1]=aEscPos;
499 aPol[2]=aEscPos;
501 if (eEscDir==LKS || eEscDir==RTS) {
502 if (rPara.bFitLineLen) {
503 aPol[1].X()=(aTl.X()+aEscPos.X())/2;
504 } else {
505 if (eEscDir==LKS) aPol[1].X()-=rPara.nLineLen;
506 else aPol[1].X()+=rPara.nLineLen;
508 } else {
509 if (rPara.bFitLineLen) {
510 aPol[1].Y()=(aTl.Y()+aEscPos.Y())/2;
511 } else {
512 if (eEscDir==OBN) aPol[1].Y()-=rPara.nLineLen;
513 else aPol[1].Y()+=rPara.nLineLen;
516 if (!rPara.bFixedAngle) {
517 // TODO: Implementation missing.
519 rPoly=aPol;
522 void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
524 ImpCalcTail3(rPara,rPoly,rRect);
527 void SdrCaptionObj::ImpCalcTail(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
529 switch (rPara.eType) {
530 case SDRCAPT_TYPE1: ImpCalcTail1(rPara,rPoly,rRect); break;
531 case SDRCAPT_TYPE2: ImpCalcTail2(rPara,rPoly,rRect); break;
532 case SDRCAPT_TYPE3: ImpCalcTail3(rPara,rPoly,rRect); break;
533 case SDRCAPT_TYPE4: ImpCalcTail4(rPara,rPoly,rRect); break;
537 bool SdrCaptionObj::BegCreate(SdrDragStat& rStat)
539 if (aRect.IsEmpty()) return sal_False; // Create currently only works with the given Rect
541 ImpCaptParams aPara;
542 ImpGetCaptParams(aPara);
543 aRect.SetPos(rStat.GetNow());
544 aTailPoly[0]=rStat.GetStart();
545 ImpCalcTail(aPara,aTailPoly,aRect);
546 rStat.SetActionRect(aRect);
547 return sal_True;
550 bool SdrCaptionObj::MovCreate(SdrDragStat& rStat)
552 ImpCaptParams aPara;
553 ImpGetCaptParams(aPara);
554 aRect.SetPos(rStat.GetNow());
555 ImpCalcTail(aPara,aTailPoly,aRect);
556 rStat.SetActionRect(aRect);
557 SetBoundRectDirty();
558 bSnapRectDirty=sal_True;
559 return sal_True;
562 bool SdrCaptionObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
564 ImpCaptParams aPara;
565 ImpGetCaptParams(aPara);
566 aRect.SetPos(rStat.GetNow());
567 ImpCalcTail(aPara,aTailPoly,aRect);
568 SetRectsDirty();
569 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
572 bool SdrCaptionObj::BckCreate(SdrDragStat& /*rStat*/)
574 return sal_False;
577 void SdrCaptionObj::BrkCreate(SdrDragStat& /*rStat*/)
581 basegfx::B2DPolyPolygon SdrCaptionObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
583 basegfx::B2DPolyPolygon aRetval;
584 const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
585 aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
586 aRetval.append(aTailPoly.getB2DPolygon());
587 return aRetval;
590 Pointer SdrCaptionObj::GetCreatePointer() const
592 return Pointer(POINTER_DRAW_CAPTION);
595 void SdrCaptionObj::NbcMove(const Size& rSiz)
597 SdrRectObj::NbcMove(rSiz);
598 MovePoly(aTailPoly,rSiz);
599 if(mbFixedTail)
600 SetTailPos(GetFixedTailPos());
603 void SdrCaptionObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
605 SdrRectObj::NbcResize(rRef,xFact,yFact);
606 ResizePoly(aTailPoly,rRef,xFact,yFact);
607 ImpRecalcTail();
608 if(mbFixedTail)
609 SetTailPos(GetFixedTailPos());
612 void SdrCaptionObj::NbcSetRelativePos(const Point& rPnt)
614 Point aRelPos0(aTailPoly.GetPoint(0)-aAnchor);
615 Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
616 NbcMove(aSiz); // This also calls SetRectsDirty()
619 Point SdrCaptionObj::GetRelativePos() const
621 return aTailPoly.GetPoint(0)-aAnchor;
624 void SdrCaptionObj::NbcSetAnchorPos(const Point& rPnt)
626 SdrRectObj::NbcSetAnchorPos(rPnt);
627 // TODO: Implementation missing.
630 const Point& SdrCaptionObj::GetAnchorPos() const
632 // TODO: Implementation missing.
633 return SdrRectObj::GetAnchorPos();
636 void SdrCaptionObj::RecalcSnapRect()
638 SdrRectObj::RecalcSnapRect();
639 // #i32599#
640 // TODO: Implementation missing.
643 const Rectangle& SdrCaptionObj::GetSnapRect() const
645 return SdrRectObj::GetSnapRect();
648 void SdrCaptionObj::NbcSetSnapRect(const Rectangle& rRect)
650 // #i32599#
651 // Move back to see the rectangle of the underlying SdrRectObj
652 // as the SnapRect, without the TailPos. That simplifies SnapRect
653 // handling again, if not allows it at all...
654 SdrRectObj::NbcSetSnapRect(rRect);
657 const Rectangle& SdrCaptionObj::GetLogicRect() const
659 return aRect;
662 void SdrCaptionObj::NbcSetLogicRect(const Rectangle& rRect)
664 SdrRectObj::NbcSetLogicRect(rRect);
665 ImpRecalcTail();
668 const Point& SdrCaptionObj::GetTailPos() const
670 return aTailPoly[0];
673 void SdrCaptionObj::SetTailPos(const Point& rPos)
675 if (aTailPoly.GetSize()==0 || aTailPoly[0]!=rPos) {
676 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
677 NbcSetTailPos(rPos);
678 SetChanged();
679 BroadcastObjectChange();
680 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
684 void SdrCaptionObj::NbcSetTailPos(const Point& rPos)
686 aTailPoly[0]=rPos;
687 ImpRecalcTail();
690 sal_uInt32 SdrCaptionObj::GetSnapPointCount() const
692 // TODO: Implementation missing.
693 return 0L;
696 Point SdrCaptionObj::GetSnapPoint(sal_uInt32 /*i*/) const
698 // TODO: Implementation missing.
699 return Point(0,0);
702 void SdrCaptionObj::SetModel(SdrModel* pNewModel)
704 SdrRectObj::SetModel(pNewModel);
705 ImpRecalcTail();
708 void SdrCaptionObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
710 SdrRectObj::Notify(rBC,rHint);
711 ImpRecalcTail();
714 SdrObjGeoData* SdrCaptionObj::NewGeoData() const
716 return new SdrCaptObjGeoData;
719 void SdrCaptionObj::SaveGeoData(SdrObjGeoData& rGeo) const
721 SdrRectObj::SaveGeoData(rGeo);
722 SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo;
723 rCGeo.aTailPoly=aTailPoly;
726 void SdrCaptionObj::RestGeoData(const SdrObjGeoData& rGeo)
728 SdrRectObj::RestGeoData(rGeo);
729 SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo;
730 aTailPoly=rCGeo.aTailPoly;
733 SdrObject* SdrCaptionObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const
735 SdrObject* pRect=SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
736 SdrObject* pTail = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly.getB2DPolygon()), sal_False, bBezier);
737 SdrObject* pRet=(pTail!=NULL) ? pTail : pRect;
738 if (pTail!=NULL && pRect!=NULL) {
739 bool bInsRect = true;
740 bool bInsTail = true;
741 SdrObjList* pOL=pTail->GetSubList();
742 if (pOL!=NULL) { pRet=pRect; bInsTail = false; }
743 if (pOL==NULL) pOL=pRect->GetSubList();
744 if (pOL!=NULL) { pRet=pRect; bInsRect = false; }
745 if (pOL==NULL) {
746 SdrObjGroup* pGrp=new SdrObjGroup;
747 pOL=pGrp->GetSubList();
748 pRet=pGrp;
750 if (bInsRect) pOL->NbcInsertObject(pRect);
751 if (bInsTail) pOL->NbcInsertObject(pTail,0);
753 return pRet;
756 // #i32599#
757 // Add own implementation for TRSetBaseGeometry to handle TailPos over changes.
758 void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
760 // break up matrix
761 basegfx::B2DTuple aScale;
762 basegfx::B2DTuple aTranslate;
763 double fRotate, fShearX;
764 rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
766 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
767 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
768 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
770 aScale.setX(fabs(aScale.getX()));
771 aScale.setY(fabs(aScale.getY()));
772 fRotate = fmod(fRotate + F_PI, F_2PI);
775 // force metric to pool metric
776 SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0);
777 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
779 switch(eMapUnit)
781 case SFX_MAPUNIT_TWIP :
783 // position
784 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
785 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
787 // size
788 aScale.setX(ImplMMToTwips(aScale.getX()));
789 aScale.setY(ImplMMToTwips(aScale.getY()));
791 break;
793 default:
795 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
800 // if anchor is used, make position relative to it
801 if( pModel->IsWriter() )
803 if(GetAnchorPos().X() || GetAnchorPos().Y())
805 aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
809 // build BaseRect
810 Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY()));
811 Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY())));
813 // set BaseRect, but rescue TailPos over this call
814 const Point aTailPoint = GetTailPos();
815 SetSnapRect(aBaseRect);
816 SetTailPos(aTailPoint);
817 ImpRecalcTail();
820 // geometry access
821 basegfx::B2DPolygon SdrCaptionObj::getTailPolygon() const
823 return aTailPoly.getB2DPolygon();
826 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */