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