xref: /trunk/main/svx/source/svdraw/svdocapt.cxx (revision f6e50924)
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