xref: /AOO41X/main/svx/source/svdraw/svdocapt.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include <tools/bigint.hxx>
27 #include <svx/xlnwtit.hxx>
28 #include <svl/style.hxx>
29 #include <svx/svdocapt.hxx>
30 #include <svx/xpool.hxx>
31 #include <svx/xpoly.hxx>
32 #include <svx/svdattrx.hxx>
33 #include <svx/svdpool.hxx>
34 #include <svx/svdetc.hxx>
35 #include <svx/svdtrans.hxx>
36 #include <svx/svdhdl.hxx>
37 #include <svx/svddrag.hxx>
38 #include <svx/svdmodel.hxx>
39 #include <svx/svdview.hxx>   // fuer RectSnap
40 #include "svx/svdglob.hxx"   // StringCache
41 #include "svx/svdstr.hrc"    // Objektname
42 #include <svx/svdogrp.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/xflhtit.hxx>
45 #include <svx/xflclit.hxx>
46 #include <svx/xfltrit.hxx>
47 #include <editeng/eeitem.hxx>
48 #include <svx/sdr/properties/captionproperties.hxx>
49 #include <vcl/salbtype.hxx>     // FRound
50 #include <svx/sdr/contact/viewcontactofsdrcaptionobj.hxx>
51 #include <basegfx/tuple/b2dtuple.hxx>
52 #include <basegfx/matrix/b2dhommatrix.hxx>
53 #include <basegfx/polygon/b2dpolygon.hxx>
54 #include <basegfx/range/b2drange.hxx>
55 #include <basegfx/polygon/b2dpolygontools.hxx>
56 #include <svx/sdrhittesthelper.hxx>
57 
58 // #i32599#
ImplTwipsToMM(double fVal)59 inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); }
ImplMMToTwips(double fVal)60 inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); }
61 
62 ////////////////////////////////////////////////////////////////////////////////////////////////////
63 
64 enum EscDir {LKS,RTS,OBN,UNT};
65 
66 class ImpCaptParams
67 {
68 public:
69     SdrCaptionType              eType;
70     long                        nAngle;
71     long                        nGap;
72     long                        nEscRel;
73     long                        nEscAbs;
74     long                        nLineLen;
75     SdrCaptionEscDir            eEscDir;
76     FASTBOOL                    bFitLineLen;
77     FASTBOOL                    bEscRel;
78     FASTBOOL                    bFixedAngle;
79 
80 public:
ImpCaptParams()81     ImpCaptParams()
82     {
83         eType      =SDRCAPT_TYPE3;
84         bFixedAngle=sal_False;
85         nAngle     =4500;
86         nGap       =0;
87         eEscDir    =SDRCAPT_ESCHORIZONTAL;
88         bEscRel    =sal_True;
89         nEscRel    =5000;
90         nEscAbs    =0;
91         nLineLen   =0;
92         bFitLineLen=sal_True;
93     }
94     void CalcEscPos(const Point& rTail, const Rectangle& rRect, Point& rPt, EscDir& rDir) const;
95 };
96 
CalcEscPos(const Point & rTailPt,const Rectangle & rRect,Point & rPt,EscDir & rDir) const97 void ImpCaptParams::CalcEscPos(const Point& rTailPt, const Rectangle& rRect, Point& rPt, EscDir& rDir) const
98 {
99     Point aTl(rTailPt); // lokal kopieren wg. Performance
100     long nX,nY;
101     if (bEscRel) {
102         nX=rRect.Right()-rRect.Left();
103         nX=BigMulDiv(nX,nEscRel,10000);
104         nY=rRect.Bottom()-rRect.Top();
105         nY=BigMulDiv(nY,nEscRel,10000);
106     } else {
107         nX=nEscAbs;
108         nY=nEscAbs;
109     }
110     nX+=rRect.Left();
111     nY+=rRect.Top();
112     Point  aBestPt;
113     EscDir eBestDir=LKS;
114     FASTBOOL bTryH=eEscDir==SDRCAPT_ESCBESTFIT;
115     if (!bTryH) {
116         if (eType!=SDRCAPT_TYPE1) {
117             bTryH=eEscDir==SDRCAPT_ESCHORIZONTAL;
118         } else {
119             bTryH=eEscDir==SDRCAPT_ESCVERTICAL;
120         }
121     }
122     FASTBOOL bTryV=eEscDir==SDRCAPT_ESCBESTFIT;
123     if (!bTryV) {
124         if (eType!=SDRCAPT_TYPE1) {
125             bTryV=eEscDir==SDRCAPT_ESCVERTICAL;
126         } else {
127             bTryV=eEscDir==SDRCAPT_ESCHORIZONTAL;
128         }
129     }
130 
131     if (bTryH) {
132         Point aLft(rRect.Left()-nGap,nY);
133         Point aRgt(rRect.Right()+nGap,nY);
134         FASTBOOL bLft=(aTl.X()-aLft.X()<aRgt.X()-aTl.X());
135         if (bLft) {
136             eBestDir=LKS;
137             aBestPt=aLft;
138         } else {
139             eBestDir=RTS;
140             aBestPt=aRgt;
141         }
142     }
143     if (bTryV) {
144         Point aTop(nX,rRect.Top()-nGap);
145         Point aBtm(nX,rRect.Bottom()+nGap);
146         FASTBOOL bTop=(aTl.Y()-aTop.Y()<aBtm.Y()-aTl.Y());
147         Point aBest2;
148         EscDir eBest2;
149         if (bTop) {
150             eBest2=OBN;
151             aBest2=aTop;
152         } else {
153             eBest2=UNT;
154             aBest2=aBtm;
155         }
156         FASTBOOL bTakeIt=eEscDir!=SDRCAPT_ESCBESTFIT;
157         if (!bTakeIt) {
158             BigInt aHorX(aBestPt.X()-aTl.X()); aHorX*=aHorX;
159             BigInt aHorY(aBestPt.Y()-aTl.Y()); aHorY*=aHorY;
160             BigInt aVerX(aBest2.X()-aTl.X());  aVerX*=aVerX;
161             BigInt aVerY(aBest2.Y()-aTl.Y());  aVerY*=aVerY;
162             if (eType!=SDRCAPT_TYPE1) {
163                 bTakeIt=aVerX+aVerY<aHorX+aHorY;
164             } else {
165                 bTakeIt=aVerX+aVerY>=aHorX+aHorY;
166             }
167         }
168         if (bTakeIt) {
169             aBestPt=aBest2;
170             eBestDir=eBest2;
171         }
172     }
173     rPt=aBestPt;
174     rDir=eBestDir;
175 }
176 
177 //////////////////////////////////////////////////////////////////////////////
178 // BaseProperties section
179 
CreateObjectSpecificProperties()180 sdr::properties::BaseProperties* SdrCaptionObj::CreateObjectSpecificProperties()
181 {
182     return new sdr::properties::CaptionProperties(*this);
183 }
184 
185 //////////////////////////////////////////////////////////////////////////////
186 // DrawContact section
187 
CreateObjectSpecificViewContact()188 sdr::contact::ViewContact* SdrCaptionObj::CreateObjectSpecificViewContact()
189 {
190     return new sdr::contact::ViewContactOfSdrCaptionObj(*this);
191 }
192 
193 //////////////////////////////////////////////////////////////////////////////
194 
195 TYPEINIT1(SdrCaptionObj,SdrRectObj);
196 
SdrCaptionObj()197 SdrCaptionObj::SdrCaptionObj():
198     SdrRectObj(OBJ_TEXT),
199     aTailPoly(3),  // Default Groesse: 3 Punkte = 2 Linien
200     mbSpecialTextBoxShadow(sal_False),
201     mbFixedTail(sal_False)
202 {
203 }
204 
SdrCaptionObj(const Rectangle & rRect)205 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect):
206     SdrRectObj(OBJ_TEXT,rRect),
207     aTailPoly(3),  // Default Groesse: 3 Punkte = 2 Linien
208     mbSpecialTextBoxShadow(sal_False),
209     mbFixedTail(sal_False)
210 {
211 }
212 
SdrCaptionObj(const Rectangle & rRect,const Point & rTail)213 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect, const Point& rTail):
214     SdrRectObj(OBJ_TEXT,rRect),
215     aTailPoly(3),  // Default Groesse: 3 Punkte = 2 Linien
216     mbSpecialTextBoxShadow(sal_False),
217     mbFixedTail(sal_False)
218 {
219     aTailPoly[0]=maFixedTailPos=rTail;
220 }
221 
~SdrCaptionObj()222 SdrCaptionObj::~SdrCaptionObj()
223 {
224 }
225 
TakeObjInfo(SdrObjTransformInfoRec & rInfo) const226 void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
227 {
228     rInfo.bRotateFreeAllowed=sal_False;
229     rInfo.bRotate90Allowed  =sal_False;
230     rInfo.bMirrorFreeAllowed=sal_False;
231     rInfo.bMirror45Allowed  =sal_False;
232     rInfo.bMirror90Allowed  =sal_False;
233     rInfo.bTransparenceAllowed = sal_False;
234     rInfo.bGradientAllowed = sal_False;
235     rInfo.bShearAllowed     =sal_False;
236     rInfo.bEdgeRadiusAllowed=sal_False;
237     rInfo.bCanConvToPath    =sal_True;
238     rInfo.bCanConvToPoly    =sal_True;
239     rInfo.bCanConvToPathLineToArea=sal_False;
240     rInfo.bCanConvToPolyLineToArea=sal_False;
241     rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
242 }
243 
GetObjIdentifier() const244 sal_uInt16 SdrCaptionObj::GetObjIdentifier() const
245 {
246     return sal_uInt16(OBJ_CAPTION);
247 }
248 
operator =(const SdrObject & rObj)249 void SdrCaptionObj::operator=(const SdrObject& rObj)
250 {
251     SdrRectObj::operator=(rObj);
252     aTailPoly=((SdrCaptionObj&)rObj).aTailPoly;
253 }
254 
TakeObjNameSingul(XubString & rName) const255 void SdrCaptionObj::TakeObjNameSingul(XubString& rName) const
256 {
257     rName=ImpGetResStr(STR_ObjNameSingulCAPTION);
258 
259     String aName( GetName() );
260     if(aName.Len())
261     {
262         rName += sal_Unicode(' ');
263         rName += sal_Unicode('\'');
264         rName += aName;
265         rName += sal_Unicode('\'');
266     }
267 }
268 
TakeObjNamePlural(XubString & rName) const269 void SdrCaptionObj::TakeObjNamePlural(XubString& rName) const
270 {
271     rName=ImpGetResStr(STR_ObjNamePluralCAPTION);
272 }
273 
TakeXorPoly() const274 basegfx::B2DPolyPolygon SdrCaptionObj::TakeXorPoly() const
275 {
276     basegfx::B2DPolyPolygon aPolyPoly(SdrRectObj::TakeXorPoly());
277     aPolyPoly.append(aTailPoly.getB2DPolygon());
278 
279     return aPolyPoly;
280 }
281 
GetHdlCount() const282 sal_uInt32 SdrCaptionObj::GetHdlCount() const
283 {
284     sal_uInt32 nAnz1(SdrRectObj::GetHdlCount());
285     // sal_uInt32 nAnz2(aTailPoly.GetSize());
286     // Derzeit ist nur das Draggen des Schwanzendes implementiert
287     return nAnz1 + 1L;
288 }
289 
GetHdl(sal_uInt32 nHdlNum) const290 SdrHdl* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum) const
291 {
292     const sal_uInt32 nRectHdlAnz(SdrRectObj::GetHdlCount());
293 
294     if(nHdlNum < nRectHdlAnz)
295     {
296         return SdrRectObj::GetHdl(nHdlNum);
297     }
298     else
299     {
300         sal_uInt32 nPntNum(nHdlNum);
301         nPntNum -= nRectHdlAnz;
302 
303         if(nPntNum < aTailPoly.GetSize())
304         {
305             SdrHdl* pHdl = new SdrHdl(aTailPoly.GetPoint((sal_uInt16)nPntNum), HDL_POLY);
306             pHdl->SetPolyNum(1L);
307             pHdl->SetPointNum(nPntNum);
308             return pHdl;
309         }
310         else
311         {
312             return 0L;
313         }
314     }
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////////////////////////
318 
hasSpecialDrag() const319 bool SdrCaptionObj::hasSpecialDrag() const
320 {
321     return true;
322 }
323 
beginSpecialDrag(SdrDragStat & rDrag) const324 bool SdrCaptionObj::beginSpecialDrag(SdrDragStat& rDrag) const
325 {
326     const SdrHdl* pHdl = rDrag.GetHdl();
327     rDrag.SetEndDragChangesAttributes(true);
328     rDrag.SetEndDragChangesGeoAndAttributes(true);
329 
330     if(pHdl && 0 == pHdl->GetPolyNum())
331     {
332         return SdrRectObj::beginSpecialDrag(rDrag);
333     }
334     else
335     {
336         rDrag.SetOrtho8Possible(true);
337 
338         if(!pHdl)
339         {
340             if (bMovProt)
341                 return 0;
342 
343             rDrag.SetNoSnap(true);
344             rDrag.SetActionRect(aRect);
345 
346             Point aHit(rDrag.GetStart());
347 
348             if(rDrag.GetPageView() && SdrObjectPrimitiveHit(*this, aHit, 0, *rDrag.GetPageView(), 0, false))
349             {
350                 return true;
351             }
352         }
353         else
354         {
355             if((1 == pHdl->GetPolyNum()) && (0 == pHdl->GetPointNum()))
356                 return true;
357         }
358     }
359 
360     return false;
361 }
362 
applySpecialDrag(SdrDragStat & rDrag)363 bool SdrCaptionObj::applySpecialDrag(SdrDragStat& rDrag)
364 {
365     const SdrHdl* pHdl = rDrag.GetHdl();
366 
367     if(pHdl && 0 == pHdl->GetPolyNum())
368     {
369         const bool bRet(SdrRectObj::applySpecialDrag(rDrag));
370         ImpRecalcTail();
371         ActionChanged();
372 
373         return bRet;
374     }
375     else
376     {
377         Point aDelt(rDrag.GetNow()-rDrag.GetStart());
378 
379         if(!pHdl)
380         {
381             aRect.Move(aDelt.X(),aDelt.Y());
382         }
383         else
384         {
385             aTailPoly[0] += aDelt;
386         }
387 
388         ImpRecalcTail();
389         ActionChanged();
390 
391         return true;
392     }
393 }
394 
getSpecialDragComment(const SdrDragStat & rDrag) const395 String SdrCaptionObj::getSpecialDragComment(const SdrDragStat& rDrag) const
396 {
397     const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
398 
399     if(bCreateComment)
400     {
401         return String();
402     }
403     else
404     {
405         const SdrHdl* pHdl = rDrag.GetHdl();
406 
407         if(pHdl && 0 == pHdl->GetPolyNum())
408         {
409             return SdrRectObj::getSpecialDragComment(rDrag);
410         }
411         else
412         {
413             XubString aStr;
414 
415             if(!pHdl)
416             {
417                 ImpTakeDescriptionStr(STR_DragCaptFram, aStr);
418             }
419             else
420             {
421                 ImpTakeDescriptionStr(STR_DragCaptTail, aStr);
422             }
423 
424             return aStr;
425         }
426     }
427 }
428 
429 ////////////////////////////////////////////////////////////////////////////////////////////////////
430 
ImpGetCaptParams(ImpCaptParams & rPara) const431 void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams& rPara) const
432 {
433     const SfxItemSet& rSet = GetObjectItemSet();
434     rPara.eType      =((SdrCaptionTypeItem&)      (rSet.Get(SDRATTR_CAPTIONTYPE      ))).GetValue();
435     rPara.bFixedAngle=((SdrCaptionFixedAngleItem&)(rSet.Get(SDRATTR_CAPTIONANGLE     ))).GetValue();
436     rPara.nAngle     =((SdrCaptionAngleItem&)     (rSet.Get(SDRATTR_CAPTIONFIXEDANGLE))).GetValue();
437     rPara.nGap       =((SdrCaptionGapItem&)       (rSet.Get(SDRATTR_CAPTIONGAP       ))).GetValue();
438     rPara.eEscDir    =((SdrCaptionEscDirItem&)    (rSet.Get(SDRATTR_CAPTIONESCDIR    ))).GetValue();
439     rPara.bEscRel    =((SdrCaptionEscIsRelItem&)  (rSet.Get(SDRATTR_CAPTIONESCISREL  ))).GetValue();
440     rPara.nEscRel    =((SdrCaptionEscRelItem&)    (rSet.Get(SDRATTR_CAPTIONESCREL    ))).GetValue();
441     rPara.nEscAbs    =((SdrCaptionEscAbsItem&)    (rSet.Get(SDRATTR_CAPTIONESCABS    ))).GetValue();
442     rPara.nLineLen   =((SdrCaptionLineLenItem&)   (rSet.Get(SDRATTR_CAPTIONLINELEN   ))).GetValue();
443     rPara.bFitLineLen=((SdrCaptionFitLineLenItem&)(rSet.Get(SDRATTR_CAPTIONFITLINELEN))).GetValue();
444 }
445 
ImpRecalcTail()446 void SdrCaptionObj::ImpRecalcTail()
447 {
448     ImpCaptParams aPara;
449     ImpGetCaptParams(aPara);
450     ImpCalcTail(aPara,aTailPoly,aRect);
451     SetRectsDirty();
452     SetXPolyDirty();
453 }
454 
455 // #i35971#
456 // SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack.
457 // I really wonder why this had not triggered problems before. I am
458 // sure there are some places where SetTailPos() is called at least
459 // twice or SetSnapRect after it again just to work around this.
460 // Changed this method to not do that.
461 // Also found why this has been done: For interactive dragging of the
462 // tail end pos for SDRCAPT_TYPE1. This sure was the simplest method
463 // to achieve this, for the cost to make a whole group of const methods
464 // of this object implicitly chainging the object's position.
ImpCalcTail1(const ImpCaptParams & rPara,Polygon & rPoly,Rectangle & rRect) const465 void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
466 {
467     Polygon aPol(2);
468     Point aTl(rPoly[0]);
469 
470     aPol[0] = aTl;
471     aPol[1] = aTl;
472 
473     EscDir eEscDir;
474     Point aEscPos;
475 
476     rPara.CalcEscPos(aTl, rRect, aEscPos, eEscDir);
477     aPol[1] = aEscPos;
478 
479     if(eEscDir==LKS || eEscDir==RTS)
480     {
481         aPol[0].X() = aEscPos.X();
482     }
483     else
484     {
485         aPol[0].Y() = aEscPos.Y();
486     }
487 
488     rPoly = aPol;
489 }
490 
ImpCalcTail2(const ImpCaptParams & rPara,Polygon & rPoly,Rectangle & rRect) const491 void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
492 { // Gap/EscDir/EscPos/Angle
493     Polygon aPol(2);
494     Point aTl(rPoly[0]);
495     aPol[0]=aTl;
496 
497     EscDir eEscDir;
498     Point aEscPos;
499     rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
500     aPol[1]=aEscPos;
501 
502     if (!rPara.bFixedAngle) {
503         // fehlende Implementation
504     }
505     rPoly=aPol;
506 }
507 
ImpCalcTail3(const ImpCaptParams & rPara,Polygon & rPoly,Rectangle & rRect) const508 void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
509 { // Gap/EscDir/EscPos/Angle/LineLen
510     Polygon aPol(3);
511     Point aTl(rPoly[0]);
512     aPol[0]=aTl;
513 
514     EscDir eEscDir;
515     Point aEscPos;
516     rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir);
517     aPol[1]=aEscPos;
518     aPol[2]=aEscPos;
519 
520     if (eEscDir==LKS || eEscDir==RTS) {
521         if (rPara.bFitLineLen) {
522             aPol[1].X()=(aTl.X()+aEscPos.X())/2;
523         } else {
524             if (eEscDir==LKS) aPol[1].X()-=rPara.nLineLen;
525             else aPol[1].X()+=rPara.nLineLen;
526         }
527     } else {
528         if (rPara.bFitLineLen) {
529             aPol[1].Y()=(aTl.Y()+aEscPos.Y())/2;
530         } else {
531             if (eEscDir==OBN) aPol[1].Y()-=rPara.nLineLen;
532             else aPol[1].Y()+=rPara.nLineLen;
533         }
534     }
535     if (!rPara.bFixedAngle) {
536         // fehlende Implementation
537     }
538     rPoly=aPol;
539 }
540 
ImpCalcTail4(const ImpCaptParams & rPara,Polygon & rPoly,Rectangle & rRect) const541 void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
542 {
543     ImpCalcTail3(rPara,rPoly,rRect);
544 }
545 
ImpCalcTail(const ImpCaptParams & rPara,Polygon & rPoly,Rectangle & rRect) const546 void SdrCaptionObj::ImpCalcTail(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const
547 {
548     switch (rPara.eType) {
549         case SDRCAPT_TYPE1: ImpCalcTail1(rPara,rPoly,rRect); break;
550         case SDRCAPT_TYPE2: ImpCalcTail2(rPara,rPoly,rRect); break;
551         case SDRCAPT_TYPE3: ImpCalcTail3(rPara,rPoly,rRect); break;
552         case SDRCAPT_TYPE4: ImpCalcTail4(rPara,rPoly,rRect); break;
553     }
554 }
555 
BegCreate(SdrDragStat & rStat)556 FASTBOOL SdrCaptionObj::BegCreate(SdrDragStat& rStat)
557 {
558     if (aRect.IsEmpty()) return sal_False; // Create z.Zt. nur mit vorgegebenen Rect
559 
560     ImpCaptParams aPara;
561     ImpGetCaptParams(aPara);
562     aRect.SetPos(rStat.GetNow());
563     aTailPoly[0]=rStat.GetStart();
564     ImpCalcTail(aPara,aTailPoly,aRect);
565     rStat.SetActionRect(aRect);
566     return sal_True;
567 }
568 
MovCreate(SdrDragStat & rStat)569 FASTBOOL SdrCaptionObj::MovCreate(SdrDragStat& rStat)
570 {
571     ImpCaptParams aPara;
572     ImpGetCaptParams(aPara);
573     aRect.SetPos(rStat.GetNow());
574     ImpCalcTail(aPara,aTailPoly,aRect);
575     rStat.SetActionRect(aRect);
576     SetBoundRectDirty();
577     bSnapRectDirty=sal_True;
578     return sal_True;
579 }
580 
EndCreate(SdrDragStat & rStat,SdrCreateCmd eCmd)581 FASTBOOL SdrCaptionObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
582 {
583     ImpCaptParams aPara;
584     ImpGetCaptParams(aPara);
585     aRect.SetPos(rStat.GetNow());
586     ImpCalcTail(aPara,aTailPoly,aRect);
587     SetRectsDirty();
588     return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
589 }
590 
BckCreate(SdrDragStat &)591 FASTBOOL SdrCaptionObj::BckCreate(SdrDragStat& /*rStat*/)
592 {
593     return sal_False;
594 }
595 
BrkCreate(SdrDragStat &)596 void SdrCaptionObj::BrkCreate(SdrDragStat& /*rStat*/)
597 {
598 }
599 
TakeCreatePoly(const SdrDragStat &) const600 basegfx::B2DPolyPolygon SdrCaptionObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
601 {
602     basegfx::B2DPolyPolygon aRetval;
603     const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
604     aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
605     aRetval.append(aTailPoly.getB2DPolygon());
606     return aRetval;
607 }
608 
GetCreatePointer() const609 Pointer SdrCaptionObj::GetCreatePointer() const
610 {
611     return Pointer(POINTER_DRAW_CAPTION);
612 }
613 
NbcMove(const Size & rSiz)614 void SdrCaptionObj::NbcMove(const Size& rSiz)
615 {
616     SdrRectObj::NbcMove(rSiz);
617     MovePoly(aTailPoly,rSiz);
618     if(mbFixedTail)
619         SetTailPos(GetFixedTailPos());
620 }
621 
NbcResize(const Point & rRef,const Fraction & xFact,const Fraction & yFact)622 void SdrCaptionObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
623 {
624     SdrRectObj::NbcResize(rRef,xFact,yFact);
625     ResizePoly(aTailPoly,rRef,xFact,yFact);
626     ImpRecalcTail();
627     if(mbFixedTail)
628         SetTailPos(GetFixedTailPos());
629 }
630 
NbcSetRelativePos(const Point & rPnt)631 void SdrCaptionObj::NbcSetRelativePos(const Point& rPnt)
632 {
633     Point aRelPos0(aTailPoly.GetPoint(0)-aAnchor);
634     Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
635     NbcMove(aSiz); // Der ruft auch das SetRectsDirty()
636 }
637 
GetRelativePos() const638 Point SdrCaptionObj::GetRelativePos() const
639 {
640     return aTailPoly.GetPoint(0)-aAnchor;
641 }
642 
NbcSetAnchorPos(const Point & rPnt)643 void SdrCaptionObj::NbcSetAnchorPos(const Point& rPnt)
644 {
645     SdrRectObj::NbcSetAnchorPos(rPnt);
646     // !!!!! fehlende Impl.
647 }
648 
GetAnchorPos() const649 const Point& SdrCaptionObj::GetAnchorPos() const
650 {
651     // !!!!! fehlende Impl.
652     return SdrRectObj::GetAnchorPos();
653 }
654 
RecalcSnapRect()655 void SdrCaptionObj::RecalcSnapRect()
656 {
657     SdrRectObj::RecalcSnapRect();
658     // #i32599#
659     // maSnapRect.Union(aTailPoly.GetBoundRect());
660     // !!!!! fehlende Impl.
661 }
662 
GetSnapRect() const663 const Rectangle& SdrCaptionObj::GetSnapRect() const
664 {
665     return SdrRectObj::GetSnapRect();
666 }
667 
NbcSetSnapRect(const Rectangle & rRect)668 void SdrCaptionObj::NbcSetSnapRect(const Rectangle& rRect)
669 {
670     // #i32599#
671     // Move back to see the rectangle of the underlying SdrRectObj
672     // as the SnapRect, without the TailPos. That simplifies SnapRect
673     // handling again, if not allows it at all...
674     SdrRectObj::NbcSetSnapRect(rRect);
675 }
676 
GetLogicRect() const677 const Rectangle& SdrCaptionObj::GetLogicRect() const
678 {
679     return aRect;
680 }
681 
NbcSetLogicRect(const Rectangle & rRect)682 void SdrCaptionObj::NbcSetLogicRect(const Rectangle& rRect)
683 {
684     SdrRectObj::NbcSetLogicRect(rRect);
685     ImpRecalcTail();
686 }
687 
GetTailPos() const688 const Point& SdrCaptionObj::GetTailPos() const
689 {
690     return aTailPoly[0];
691 }
692 
SetTailPos(const Point & rPos)693 void SdrCaptionObj::SetTailPos(const Point& rPos)
694 {
695     if (aTailPoly.GetSize()==0 || aTailPoly[0]!=rPos) {
696         Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
697         // #110094#-14 SendRepaintBroadcast();
698         NbcSetTailPos(rPos);
699         SetChanged();
700         BroadcastObjectChange();
701         SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
702     }
703 }
704 
NbcSetTailPos(const Point & rPos)705 void SdrCaptionObj::NbcSetTailPos(const Point& rPos)
706 {
707     aTailPoly[0]=rPos;
708     ImpRecalcTail();
709 }
710 
GetSnapPointCount() const711 sal_uInt32 SdrCaptionObj::GetSnapPointCount() const
712 {
713     // !!!!! fehlende Impl.
714     return 0L;
715 }
716 
GetSnapPoint(sal_uInt32) const717 Point SdrCaptionObj::GetSnapPoint(sal_uInt32 /*i*/) const
718 {
719     // !!!!! fehlende Impl.
720     return Point(0,0);
721 }
722 
SetModel(SdrModel * pNewModel)723 void SdrCaptionObj::SetModel(SdrModel* pNewModel)
724 {
725     SdrRectObj::SetModel(pNewModel);
726     ImpRecalcTail();
727 }
728 
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)729 void SdrCaptionObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
730 {
731     SdrRectObj::Notify(rBC,rHint);
732     ImpRecalcTail();
733 }
734 
NewGeoData() const735 SdrObjGeoData* SdrCaptionObj::NewGeoData() const
736 {
737     return new SdrCaptObjGeoData;
738 }
739 
SaveGeoData(SdrObjGeoData & rGeo) const740 void SdrCaptionObj::SaveGeoData(SdrObjGeoData& rGeo) const
741 {
742     SdrRectObj::SaveGeoData(rGeo);
743     SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo;
744     rCGeo.aTailPoly=aTailPoly;
745 }
746 
RestGeoData(const SdrObjGeoData & rGeo)747 void SdrCaptionObj::RestGeoData(const SdrObjGeoData& rGeo)
748 {
749     SdrRectObj::RestGeoData(rGeo);
750     SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo;
751     aTailPoly=rCGeo.aTailPoly;
752 }
753 
DoConvertToPolyObj(sal_Bool bBezier,bool bAddText) const754 SdrObject* SdrCaptionObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const
755 { // #42334# - Convert implementiert
756     SdrObject* pRect=SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
757     SdrObject* pTail = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly.getB2DPolygon()), sal_False, bBezier);
758     SdrObject* pRet=(pTail!=NULL) ? pTail : pRect;
759     if (pTail!=NULL && pRect!=NULL) {
760         FASTBOOL bInsRect=sal_True;
761         FASTBOOL bInsTail=sal_True;
762         SdrObjList* pOL=pTail->GetSubList();
763         if (pOL!=NULL) { pRet=pRect; bInsTail=sal_False; }
764         if (pOL==NULL) pOL=pRect->GetSubList();
765         if (pOL!=NULL) { pRet=pRect; bInsRect=sal_False; }
766         if (pOL==NULL) {
767             SdrObjGroup* pGrp=new SdrObjGroup;
768             pOL=pGrp->GetSubList();
769             pRet=pGrp;
770         }
771         if (bInsRect) pOL->NbcInsertObject(pRect);
772         if (bInsTail) pOL->NbcInsertObject(pTail,0);
773     }
774     return pRet;
775 }
776 
777 // #i32599#
778 // Add own implementation for TRSetBaseGeometry to handle TailPos over changes.
TRSetBaseGeometry(const basegfx::B2DHomMatrix & rMatrix,const basegfx::B2DPolyPolygon &)779 void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
780 {
781     // break up matrix
782     basegfx::B2DTuple aScale;
783     basegfx::B2DTuple aTranslate;
784     double fRotate, fShearX;
785     rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
786 
787     // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
788     // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
789     if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
790     {
791         aScale.setX(fabs(aScale.getX()));
792         aScale.setY(fabs(aScale.getY()));
793         fRotate = fmod(fRotate + F_PI, F_2PI);
794     }
795 
796     // force metric to pool metric
797     SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0);
798     if(eMapUnit != SFX_MAPUNIT_100TH_MM)
799     {
800         switch(eMapUnit)
801         {
802             case SFX_MAPUNIT_TWIP :
803             {
804                 // position
805                 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
806                 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
807 
808                 // size
809                 aScale.setX(ImplMMToTwips(aScale.getX()));
810                 aScale.setY(ImplMMToTwips(aScale.getY()));
811 
812                 break;
813             }
814             default:
815             {
816                 DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
817             }
818         }
819     }
820 
821     // if anchor is used, make position relative to it
822     if( pModel->IsWriter() )
823     {
824         if(GetAnchorPos().X() || GetAnchorPos().Y())
825         {
826             aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
827         }
828     }
829 
830     // build BaseRect
831     Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY()));
832     Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY())));
833 
834     // set BaseRect, but rescue TailPos over this call
835     const Point aTailPoint = GetTailPos();
836     SetSnapRect(aBaseRect);
837     SetTailPos(aTailPoint);
838     ImpRecalcTail();
839 }
840 
841 // geometry access
getTailPolygon() const842 basegfx::B2DPolygon SdrCaptionObj::getTailPolygon() const
843 {
844     return aTailPoly.getB2DPolygon();
845 }
846 
847 // eof
848