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