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