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