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