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/matrix/b2dhommatrixtools.hxx>
22 : #include <basegfx/point/b2dpoint.hxx>
23 : #include <basegfx/polygon/b2dpolygon.hxx>
24 : #include <basegfx/polygon/b2dpolygontools.hxx>
25 : #include <editeng/eeitem.hxx>
26 : #include <math.h>
27 : #include <svl/style.hxx>
28 :
29 : #include "svdglob.hxx"
30 : #include "svx/svdstr.hrc"
31 :
32 : #include <sdr/contact/viewcontactofsdrcircobj.hxx>
33 : #include <sdr/properties/circleproperties.hxx>
34 : #include <svx/svdattr.hxx>
35 : #include <svx/svddrag.hxx>
36 : #include <svx/svdetc.hxx>
37 : #include <svx/svdmodel.hxx>
38 : #include <svx/svdocirc.hxx>
39 : #include <svx/svdopath.hxx>
40 : #include <svx/svdpage.hxx>
41 : #include <svx/svdpool.hxx>
42 : #include <svx/svdtrans.hxx>
43 : #include <svx/svdview.hxx>
44 : #include <svx/sxciaitm.hxx>
45 : #include <sxcikitm.hxx>
46 : #include <svx/xlnedit.hxx>
47 : #include <svx/xlnedwit.hxx>
48 : #include <svx/xlnstit.hxx>
49 : #include <svx/xlnstwit.hxx>
50 : #include <svx/xlnwtit.hxx>
51 : #include <svx/xpool.hxx>
52 :
53 : using namespace com::sun::star;
54 :
55 0 : Point GetAnglePnt(const Rectangle& rR, long nAngle)
56 : {
57 0 : Point aCenter(rR.Center());
58 0 : long nWdt=rR.Right()-rR.Left();
59 0 : long nHgt=rR.Bottom()-rR.Top();
60 0 : long nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2;
61 : double a;
62 0 : a=nAngle*nPi180;
63 0 : Point aRetval(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad));
64 0 : if (nWdt==0) aRetval.X()=0;
65 0 : if (nHgt==0) aRetval.Y()=0;
66 0 : if (nWdt!=nHgt) {
67 0 : if (nWdt>nHgt) {
68 0 : if (nWdt!=0) {
69 : // stop possible overruns for very large objects
70 0 : if (std::abs(nHgt)>32767 || std::abs(aRetval.Y())>32767) {
71 0 : aRetval.Y()=BigMulDiv(aRetval.Y(),nHgt,nWdt);
72 : } else {
73 0 : aRetval.Y()=aRetval.Y()*nHgt/nWdt;
74 : }
75 : }
76 : } else {
77 0 : if (nHgt!=0) {
78 : // stop possible overruns for very large objects
79 0 : if (std::abs(nWdt)>32767 || std::abs(aRetval.X())>32767) {
80 0 : aRetval.X()=BigMulDiv(aRetval.X(),nWdt,nHgt);
81 : } else {
82 0 : aRetval.X()=aRetval.X()*nWdt/nHgt;
83 : }
84 : }
85 : }
86 : }
87 0 : aRetval+=aCenter;
88 0 : return aRetval;
89 : }
90 :
91 :
92 : // BaseProperties section
93 :
94 115 : sdr::properties::BaseProperties* SdrCircObj::CreateObjectSpecificProperties()
95 : {
96 115 : return new sdr::properties::CircleProperties(*this);
97 : }
98 :
99 :
100 : // DrawContact section
101 :
102 116 : sdr::contact::ViewContact* SdrCircObj::CreateObjectSpecificViewContact()
103 : {
104 116 : return new sdr::contact::ViewContactOfSdrCircObj(*this);
105 : }
106 :
107 :
108 :
109 10304 : TYPEINIT1(SdrCircObj,SdrRectObj);
110 :
111 1 : SdrCircObj::SdrCircObj(SdrObjKind eNewKind)
112 : {
113 1 : nStartAngle=0;
114 1 : nEndAngle=36000;
115 1 : meCircleKind=eNewKind;
116 1 : bClosedObj=eNewKind!=OBJ_CARC;
117 1 : }
118 :
119 115 : SdrCircObj::SdrCircObj(SdrObjKind eNewKind, const Rectangle& rRect):
120 115 : SdrRectObj(rRect)
121 : {
122 115 : nStartAngle=0;
123 115 : nEndAngle=36000;
124 115 : meCircleKind=eNewKind;
125 115 : bClosedObj=eNewKind!=OBJ_CARC;
126 115 : }
127 :
128 0 : SdrCircObj::SdrCircObj(SdrObjKind eNewKind, const Rectangle& rRect, long nNewStartWink, long nNewEndWink):
129 0 : SdrRectObj(rRect)
130 : {
131 0 : long nAngleDif=nNewEndWink-nNewStartWink;
132 0 : nStartAngle=NormAngle360(nNewStartWink);
133 0 : nEndAngle=NormAngle360(nNewEndWink);
134 0 : if (nAngleDif==36000) nEndAngle+=nAngleDif; // full circle
135 0 : meCircleKind=eNewKind;
136 0 : bClosedObj=eNewKind!=OBJ_CARC;
137 0 : }
138 :
139 232 : SdrCircObj::~SdrCircObj()
140 : {
141 232 : }
142 :
143 0 : void SdrCircObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
144 : {
145 0 : bool bCanConv=!HasText() || ImpCanConvTextToCurve();
146 0 : rInfo.bEdgeRadiusAllowed = false;
147 0 : rInfo.bCanConvToPath=bCanConv;
148 0 : rInfo.bCanConvToPoly=bCanConv;
149 0 : rInfo.bCanConvToContour = !IsFontwork() && (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
150 0 : }
151 :
152 2026 : sal_uInt16 SdrCircObj::GetObjIdentifier() const
153 : {
154 2026 : return sal_uInt16(meCircleKind);
155 : }
156 :
157 149 : bool SdrCircObj::PaintNeedsXPolyCirc() const
158 : {
159 : // XPoly is necessary for all rotated ellipse objects, circle and
160 : // ellipse segments.
161 : // If not WIN, then (for now) also for circle/ellipse segments and circle/
162 : // ellipse arcs (for precision)
163 149 : bool bNeed=aGeo.nRotationAngle!=0 || aGeo.nShearAngle!=0 || meCircleKind==OBJ_CCUT;
164 : // If not WIN, then for everything except full circle (for now!)
165 149 : if (meCircleKind!=OBJ_CIRC) bNeed = true;
166 :
167 149 : const SfxItemSet& rSet = GetObjectItemSet();
168 149 : if(!bNeed)
169 : {
170 : // XPoly is necessary for everything that isn't LineSolid or LineNone
171 98 : drawing::LineStyle eLine = static_cast<const XLineStyleItem&>(rSet.Get(XATTR_LINESTYLE)).GetValue();
172 98 : bNeed = eLine != drawing::LineStyle_NONE && eLine != drawing::LineStyle_SOLID;
173 :
174 : // XPoly is necessary for thick lines
175 98 : if(!bNeed && eLine != drawing::LineStyle_NONE)
176 85 : bNeed = static_cast<const XLineWidthItem&>(rSet.Get(XATTR_LINEWIDTH)).GetValue() != 0;
177 :
178 : // XPoly is necessary for circle arcs with line ends
179 98 : if(!bNeed && meCircleKind == OBJ_CARC)
180 : {
181 : // start of the line is here if StartPolygon, StartWidth!=0
182 0 : bNeed=static_cast<const XLineStartItem&>(rSet.Get(XATTR_LINESTART)).GetLineStartValue().count() != 0L &&
183 0 : static_cast<const XLineStartWidthItem&>(rSet.Get(XATTR_LINESTARTWIDTH)).GetValue() != 0;
184 :
185 0 : if(!bNeed)
186 : {
187 : // end of the line is here if EndPolygon, EndWidth!=0
188 0 : bNeed = static_cast<const XLineEndItem&>(rSet.Get(XATTR_LINEEND)).GetLineEndValue().count() != 0L &&
189 0 : static_cast<const XLineEndWidthItem&>(rSet.Get(XATTR_LINEENDWIDTH)).GetValue() != 0;
190 : }
191 : }
192 : }
193 :
194 : // XPoly is necessary if Fill !=None and !=Solid
195 149 : if(!bNeed && meCircleKind != OBJ_CARC)
196 : {
197 87 : drawing::FillStyle eFill=static_cast<const XFillStyleItem&>(rSet.Get(XATTR_FILLSTYLE)).GetValue();
198 87 : bNeed = eFill != drawing::FillStyle_NONE && eFill != drawing::FillStyle_SOLID;
199 : }
200 :
201 149 : if(!bNeed && meCircleKind != OBJ_CIRC && nStartAngle == nEndAngle)
202 0 : bNeed = true; // otherwise we're drawing a full circle
203 :
204 149 : return bNeed;
205 : }
206 :
207 68 : basegfx::B2DPolygon SdrCircObj::ImpCalcXPolyCirc(const SdrObjKind eCicrleKind, const Rectangle& rRect1, long nStart, long nEnd) const
208 : {
209 68 : const basegfx::B2DRange aRange(rRect1.Left(), rRect1.Top(), rRect1.Right(), rRect1.Bottom());
210 68 : basegfx::B2DPolygon aCircPolygon;
211 :
212 68 : if(OBJ_CIRC == eCicrleKind)
213 : {
214 : // create full circle. Do not use createPolygonFromEllipse; it's necessary
215 : // to get the start point to the bottom of the circle to keep compatible to
216 : // old geometry creation
217 17 : aCircPolygon = basegfx::tools::createPolygonFromUnitCircle(1);
218 :
219 : // needs own scaling and translation from unit circle to target size (same as
220 : // would be in createPolygonFromEllipse)
221 17 : const basegfx::B2DPoint aCenter(aRange.getCenter());
222 : const basegfx::B2DHomMatrix aMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
223 34 : aRange.getWidth() / 2.0, aRange.getHeight() / 2.0,
224 68 : aCenter.getX(), aCenter.getY()));
225 34 : aCircPolygon.transform(aMatrix);
226 : }
227 : else
228 : {
229 : // mirror start, end for geometry creation since model coordinate system is mirrored in Y
230 : // #i111715# increase numerical correctness by first dividing and not using F_PI1800
231 51 : const double fStart((((36000 - nEnd) % 36000) / 18000.0) * F_PI);
232 51 : const double fEnd((((36000 - nStart) % 36000) / 18000.0) * F_PI);
233 :
234 : // create circle segment. This is not closed by default
235 153 : aCircPolygon = basegfx::tools::createPolygonFromEllipseSegment(
236 102 : aRange.getCenter(), aRange.getWidth() / 2.0, aRange.getHeight() / 2.0,
237 51 : fStart, fEnd);
238 :
239 : // check closing states
240 51 : const bool bCloseSegment(OBJ_CARC != eCicrleKind);
241 51 : const bool bCloseUsingCenter(OBJ_SECT == eCicrleKind);
242 :
243 51 : if(bCloseSegment)
244 : {
245 39 : if(bCloseUsingCenter)
246 : {
247 : // add center point at start (for historical reasons)
248 12 : basegfx::B2DPolygon aSector;
249 12 : aSector.append(aRange.getCenter());
250 12 : aSector.append(aCircPolygon);
251 12 : aCircPolygon = aSector;
252 : }
253 :
254 : // close
255 39 : aCircPolygon.setClosed(true);
256 : }
257 : }
258 :
259 : // #i76950#
260 68 : if(aGeo.nShearAngle || aGeo.nRotationAngle)
261 : {
262 : // translate top left to (0,0)
263 0 : const basegfx::B2DPoint aTopLeft(aRange.getMinimum());
264 : basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
265 0 : -aTopLeft.getX(), -aTopLeft.getY()));
266 :
267 : // shear, rotate and back to top left (if needed)
268 : aMatrix = basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
269 0 : aGeo.nShearAngle ? tan((36000 - aGeo.nShearAngle) * F_PI18000) : 0.0,
270 0 : aGeo.nRotationAngle ? (36000 - aGeo.nRotationAngle) * F_PI18000 : 0.0,
271 0 : aTopLeft) * aMatrix;
272 :
273 : // apply transformation
274 0 : aCircPolygon.transform(aMatrix);
275 : }
276 :
277 68 : return aCircPolygon;
278 : }
279 :
280 65 : void SdrCircObj::RecalcXPoly()
281 : {
282 65 : const basegfx::B2DPolygon aPolyCirc(ImpCalcXPolyCirc(meCircleKind, maRect, nStartAngle, nEndAngle));
283 65 : mpXPoly = new XPolygon(aPolyCirc);
284 65 : }
285 :
286 2 : OUString SdrCircObj::TakeObjNameSingul() const
287 : {
288 2 : sal_uInt16 nID=STR_ObjNameSingulCIRC;
289 2 : if (maRect.GetWidth() == maRect.GetHeight() && aGeo.nShearAngle==0)
290 : {
291 1 : switch (meCircleKind) {
292 1 : case OBJ_CIRC: nID=STR_ObjNameSingulCIRC; break;
293 0 : case OBJ_SECT: nID=STR_ObjNameSingulSECT; break;
294 0 : case OBJ_CARC: nID=STR_ObjNameSingulCARC; break;
295 0 : case OBJ_CCUT: nID=STR_ObjNameSingulCCUT; break;
296 0 : default: break;
297 : }
298 : } else {
299 1 : switch (meCircleKind) {
300 1 : case OBJ_CIRC: nID=STR_ObjNameSingulCIRCE; break;
301 0 : case OBJ_SECT: nID=STR_ObjNameSingulSECTE; break;
302 0 : case OBJ_CARC: nID=STR_ObjNameSingulCARCE; break;
303 0 : case OBJ_CCUT: nID=STR_ObjNameSingulCCUTE; break;
304 0 : default: break;
305 : }
306 : }
307 2 : OUStringBuffer sName(ImpGetResStr(nID));
308 :
309 4 : OUString aName(GetName());
310 2 : if (!aName.isEmpty())
311 : {
312 0 : sName.append(' ');
313 0 : sName.append('\'');
314 0 : sName.append(aName);
315 0 : sName.append('\'');
316 : }
317 4 : return sName.makeStringAndClear();
318 : }
319 :
320 20 : OUString SdrCircObj::TakeObjNamePlural() const
321 : {
322 20 : sal_uInt16 nID=STR_ObjNamePluralCIRC;
323 20 : if (maRect.GetWidth() == maRect.GetHeight() && aGeo.nShearAngle==0)
324 : {
325 14 : switch (meCircleKind) {
326 2 : case OBJ_CIRC: nID=STR_ObjNamePluralCIRC; break;
327 0 : case OBJ_SECT: nID=STR_ObjNamePluralSECT; break;
328 12 : case OBJ_CARC: nID=STR_ObjNamePluralCARC; break;
329 0 : case OBJ_CCUT: nID=STR_ObjNamePluralCCUT; break;
330 0 : default: break;
331 : }
332 : } else {
333 6 : switch (meCircleKind) {
334 6 : case OBJ_CIRC: nID=STR_ObjNamePluralCIRCE; break;
335 0 : case OBJ_SECT: nID=STR_ObjNamePluralSECTE; break;
336 0 : case OBJ_CARC: nID=STR_ObjNamePluralCARCE; break;
337 0 : case OBJ_CCUT: nID=STR_ObjNamePluralCCUTE; break;
338 0 : default: break;
339 : }
340 : }
341 20 : return ImpGetResStr(nID);
342 : }
343 :
344 1 : SdrCircObj* SdrCircObj::Clone() const
345 : {
346 1 : return CloneHelper< SdrCircObj >();
347 : }
348 :
349 0 : basegfx::B2DPolyPolygon SdrCircObj::TakeXorPoly() const
350 : {
351 0 : const basegfx::B2DPolygon aCircPolygon(ImpCalcXPolyCirc(meCircleKind, maRect, nStartAngle, nEndAngle));
352 0 : return basegfx::B2DPolyPolygon(aCircPolygon);
353 : }
354 :
355 : struct ImpCircUser : public SdrDragStatUserData
356 : {
357 : Rectangle aR;
358 : Point aCenter;
359 : Point aRadius;
360 : Point aP1;
361 : Point aP2;
362 : long nMaxRad;
363 : long nHgt;
364 : long nWdt;
365 : long nStart;
366 : long nEnd;
367 : long nAngle;
368 : bool bRight; // not yet implemented
369 :
370 : public:
371 0 : ImpCircUser()
372 : : nMaxRad(0),
373 : nHgt(0),
374 : nWdt(0),
375 : nStart(0),
376 : nEnd(0),
377 : nAngle(0),
378 0 : bRight(false)
379 0 : {}
380 : void SetCreateParams(SdrDragStat& rStat);
381 : };
382 :
383 12 : sal_uInt32 SdrCircObj::GetHdlCount() const
384 : {
385 12 : if(OBJ_CIRC != meCircleKind)
386 : {
387 0 : return 10L;
388 : }
389 : else
390 : {
391 12 : return 8L;
392 : }
393 : }
394 :
395 96 : SdrHdl* SdrCircObj::GetHdl(sal_uInt32 nHdlNum) const
396 : {
397 96 : if (meCircleKind==OBJ_CIRC)
398 : {
399 96 : nHdlNum += 2L;
400 : }
401 :
402 96 : SdrHdl* pH = NULL;
403 96 : Point aPnt;
404 96 : SdrHdlKind eLocalKind(HDL_MOVE);
405 96 : sal_uInt32 nPNum(0);
406 :
407 96 : switch (nHdlNum)
408 : {
409 : case 0:
410 0 : aPnt = GetAnglePnt(maRect,nStartAngle);
411 0 : eLocalKind = HDL_CIRC;
412 0 : nPNum = 1;
413 0 : break;
414 : case 1:
415 0 : aPnt = GetAnglePnt(maRect,nEndAngle);
416 0 : eLocalKind = HDL_CIRC;
417 0 : nPNum = 2L;
418 0 : break;
419 : case 2:
420 12 : aPnt = maRect.TopLeft();
421 12 : eLocalKind = HDL_UPLFT;
422 12 : break;
423 : case 3:
424 12 : aPnt = maRect.TopCenter();
425 12 : eLocalKind = HDL_UPPER;
426 12 : break;
427 : case 4:
428 12 : aPnt = maRect.TopRight();
429 12 : eLocalKind = HDL_UPRGT;
430 12 : break;
431 : case 5:
432 12 : aPnt = maRect.LeftCenter();
433 12 : eLocalKind = HDL_LEFT;
434 12 : break;
435 : case 6:
436 12 : aPnt = maRect.RightCenter();
437 12 : eLocalKind = HDL_RIGHT;
438 12 : break;
439 : case 7:
440 12 : aPnt = maRect.BottomLeft();
441 12 : eLocalKind = HDL_LWLFT;
442 12 : break;
443 : case 8:
444 12 : aPnt = maRect.BottomCenter();
445 12 : eLocalKind = HDL_LOWER;
446 12 : break;
447 : case 9:
448 12 : aPnt = maRect.BottomRight();
449 12 : eLocalKind = HDL_LWRGT;
450 12 : break;
451 : }
452 :
453 96 : if (aGeo.nShearAngle)
454 : {
455 0 : ShearPoint(aPnt,maRect.TopLeft(),aGeo.nTan);
456 : }
457 :
458 96 : if (aGeo.nRotationAngle)
459 : {
460 0 : RotatePoint(aPnt,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
461 : }
462 :
463 96 : if (eLocalKind != HDL_MOVE)
464 : {
465 96 : pH = new SdrHdl(aPnt,eLocalKind);
466 96 : pH->SetPointNum(nPNum);
467 96 : pH->SetObj(const_cast<SdrCircObj*>(this));
468 96 : pH->SetRotationAngle(aGeo.nRotationAngle);
469 : }
470 :
471 96 : return pH;
472 : }
473 :
474 :
475 :
476 15 : bool SdrCircObj::hasSpecialDrag() const
477 : {
478 15 : return true;
479 : }
480 :
481 0 : bool SdrCircObj::beginSpecialDrag(SdrDragStat& rDrag) const
482 : {
483 0 : const bool bAngle(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
484 :
485 0 : if(bAngle)
486 : {
487 0 : if(1 == rDrag.GetHdl()->GetPointNum() || 2 == rDrag.GetHdl()->GetPointNum())
488 : {
489 0 : rDrag.SetNoSnap(true);
490 : }
491 :
492 0 : return true;
493 : }
494 :
495 0 : return SdrTextObj::beginSpecialDrag(rDrag);
496 : }
497 :
498 0 : bool SdrCircObj::applySpecialDrag(SdrDragStat& rDrag)
499 : {
500 0 : const bool bAngle(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
501 :
502 0 : if(bAngle)
503 : {
504 0 : Point aPt(rDrag.GetNow());
505 :
506 0 : if (aGeo.nRotationAngle!=0)
507 0 : RotatePoint(aPt,maRect.TopLeft(),-aGeo.nSin,aGeo.nCos);
508 :
509 0 : if (aGeo.nShearAngle!=0)
510 0 : ShearPoint(aPt,maRect.TopLeft(),-aGeo.nTan);
511 :
512 0 : aPt -= maRect.Center();
513 :
514 0 : long nWdt = maRect.Right() - maRect.Left();
515 0 : long nHgt = maRect.Bottom() - maRect.Top();
516 :
517 0 : if(nWdt>=nHgt)
518 : {
519 0 : aPt.Y()=BigMulDiv(aPt.Y(),nWdt,nHgt);
520 : }
521 : else
522 : {
523 0 : aPt.X()=BigMulDiv(aPt.X(),nHgt,nWdt);
524 : }
525 :
526 0 : long nAngle=NormAngle360(GetAngle(aPt));
527 :
528 0 : if (rDrag.GetView() && rDrag.GetView()->IsAngleSnapEnabled())
529 : {
530 0 : long nSA=rDrag.GetView()->GetSnapAngle();
531 :
532 0 : if (nSA!=0)
533 : {
534 0 : nAngle+=nSA/2;
535 0 : nAngle/=nSA;
536 0 : nAngle*=nSA;
537 0 : nAngle=NormAngle360(nAngle);
538 : }
539 : }
540 :
541 0 : if(1 == rDrag.GetHdl()->GetPointNum())
542 : {
543 0 : nStartAngle = nAngle;
544 : }
545 0 : else if(2 == rDrag.GetHdl()->GetPointNum())
546 : {
547 0 : nEndAngle = nAngle;
548 : }
549 :
550 0 : SetRectsDirty();
551 0 : SetXPolyDirty();
552 0 : ImpSetCircInfoToAttr();
553 0 : SetChanged();
554 :
555 0 : return true;
556 : }
557 : else
558 : {
559 0 : return SdrTextObj::applySpecialDrag(rDrag);
560 : }
561 : }
562 :
563 0 : OUString SdrCircObj::getSpecialDragComment(const SdrDragStat& rDrag) const
564 : {
565 0 : const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
566 :
567 0 : if(bCreateComment)
568 : {
569 0 : OUString aStr;
570 0 : ImpTakeDescriptionStr(STR_ViewCreateObj, aStr);
571 0 : OUStringBuffer aBuf(aStr);
572 0 : const sal_uInt32 nPointCount(rDrag.GetPointAnz());
573 :
574 0 : if(OBJ_CIRC != meCircleKind && nPointCount > 2)
575 : {
576 0 : const ImpCircUser* pU = static_cast<const ImpCircUser*>(rDrag.GetUser());
577 : sal_Int32 nAngle;
578 :
579 0 : aBuf.appendAscii(" (");
580 :
581 0 : if(3 == nPointCount)
582 : {
583 0 : nAngle = pU->nStart;
584 : }
585 : else
586 : {
587 0 : nAngle = pU->nEnd;
588 : }
589 :
590 0 : aBuf.append(GetAngleStr(nAngle,false));
591 0 : aBuf.append(')');
592 : }
593 :
594 0 : return aBuf.makeStringAndClear();
595 : }
596 : else
597 : {
598 0 : const bool bAngle(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
599 :
600 0 : if(bAngle)
601 : {
602 0 : const sal_Int32 nAngle(1 == rDrag.GetHdl()->GetPointNum() ? nStartAngle : nEndAngle);
603 :
604 0 : OUString aStr;
605 0 : ImpTakeDescriptionStr(STR_DragCircAngle, aStr);
606 0 : OUStringBuffer aBuf(aStr);
607 0 : aBuf.appendAscii(" (");
608 0 : aBuf.append(GetAngleStr(nAngle,false));
609 0 : aBuf.append(')');
610 :
611 0 : return aBuf.makeStringAndClear();
612 : }
613 : else
614 : {
615 0 : return SdrTextObj::getSpecialDragComment(rDrag);
616 : }
617 : }
618 : }
619 :
620 :
621 :
622 0 : void ImpCircUser::SetCreateParams(SdrDragStat& rStat)
623 : {
624 0 : rStat.TakeCreateRect(aR);
625 0 : aR.Justify();
626 0 : aCenter=aR.Center();
627 0 : nWdt=aR.Right()-aR.Left();
628 0 : nHgt=aR.Bottom()-aR.Top();
629 0 : nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2;
630 0 : nStart=0;
631 0 : nEnd=36000;
632 0 : if (rStat.GetPointAnz()>2) {
633 0 : Point aP(rStat.GetPoint(2)-aCenter);
634 0 : if (nWdt==0) aP.X()=0;
635 0 : if (nHgt==0) aP.Y()=0;
636 0 : if (nWdt>=nHgt) {
637 0 : if (nHgt!=0) aP.Y()=aP.Y()*nWdt/nHgt;
638 : } else {
639 0 : if (nWdt!=0) aP.X()=aP.X()*nHgt/nWdt;
640 : }
641 0 : nStart=NormAngle360(GetAngle(aP));
642 0 : if (rStat.GetView()!=NULL && rStat.GetView()->IsAngleSnapEnabled()) {
643 0 : long nSA=rStat.GetView()->GetSnapAngle();
644 0 : if (nSA!=0) { // angle snapping
645 0 : nStart+=nSA/2;
646 0 : nStart/=nSA;
647 0 : nStart*=nSA;
648 0 : nStart=NormAngle360(nStart);
649 : }
650 : }
651 0 : aP1 = GetAnglePnt(aR,nStart);
652 0 : nEnd=nStart;
653 0 : aP2=aP1;
654 0 : } else aP1=aCenter;
655 0 : if (rStat.GetPointAnz()>3) {
656 0 : Point aP(rStat.GetPoint(3)-aCenter);
657 0 : if (nWdt>=nHgt) {
658 0 : aP.Y()=BigMulDiv(aP.Y(),nWdt,nHgt);
659 : } else {
660 0 : aP.X()=BigMulDiv(aP.X(),nHgt,nWdt);
661 : }
662 0 : nEnd=NormAngle360(GetAngle(aP));
663 0 : if (rStat.GetView()!=NULL && rStat.GetView()->IsAngleSnapEnabled()) {
664 0 : long nSA=rStat.GetView()->GetSnapAngle();
665 0 : if (nSA!=0) { // angle snapping
666 0 : nEnd+=nSA/2;
667 0 : nEnd/=nSA;
668 0 : nEnd*=nSA;
669 0 : nEnd=NormAngle360(nEnd);
670 : }
671 : }
672 0 : aP2 = GetAnglePnt(aR,nEnd);
673 0 : } else aP2=aCenter;
674 0 : }
675 :
676 0 : void SdrCircObj::ImpSetCreateParams(SdrDragStat& rStat) const
677 : {
678 0 : ImpCircUser* pU=static_cast<ImpCircUser*>(rStat.GetUser());
679 0 : if (pU==NULL) {
680 0 : pU=new ImpCircUser;
681 0 : rStat.SetUser(pU);
682 : }
683 0 : pU->SetCreateParams(rStat);
684 0 : }
685 :
686 0 : bool SdrCircObj::BegCreate(SdrDragStat& rStat)
687 : {
688 0 : rStat.SetOrtho4Possible();
689 0 : Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
690 0 : aRect1.Justify();
691 0 : rStat.SetActionRect(aRect1);
692 0 : maRect = aRect1;
693 0 : ImpSetCreateParams(rStat);
694 0 : return true;
695 : }
696 :
697 0 : bool SdrCircObj::MovCreate(SdrDragStat& rStat)
698 : {
699 0 : ImpSetCreateParams(rStat);
700 0 : ImpCircUser* pU=static_cast<ImpCircUser*>(rStat.GetUser());
701 0 : rStat.SetActionRect(pU->aR);
702 0 : maRect = pU->aR; // for ObjName
703 0 : ImpJustifyRect(maRect);
704 0 : nStartAngle=pU->nStart;
705 0 : nEndAngle=pU->nEnd;
706 0 : SetBoundRectDirty();
707 0 : bSnapRectDirty=true;
708 0 : SetXPolyDirty();
709 :
710 : // #i103058# push current angle settings to ItemSet to
711 : // allow FullDrag visualisation
712 0 : if(rStat.GetPointAnz() >= 4)
713 : {
714 0 : ImpSetCircInfoToAttr();
715 : }
716 :
717 0 : return true;
718 : }
719 :
720 0 : bool SdrCircObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
721 : {
722 0 : ImpSetCreateParams(rStat);
723 0 : ImpCircUser* pU=static_cast<ImpCircUser*>(rStat.GetUser());
724 0 : bool bRet = false;
725 0 : if (eCmd==SDRCREATE_FORCEEND && rStat.GetPointAnz()<4) meCircleKind=OBJ_CIRC;
726 0 : if (meCircleKind==OBJ_CIRC) {
727 0 : bRet=rStat.GetPointAnz()>=2;
728 0 : if (bRet) {
729 0 : maRect = pU->aR;
730 0 : ImpJustifyRect(maRect);
731 : }
732 : } else {
733 0 : rStat.SetNoSnap(rStat.GetPointAnz()>=2);
734 0 : rStat.SetOrtho4Possible(rStat.GetPointAnz()<2);
735 0 : bRet=rStat.GetPointAnz()>=4;
736 0 : if (bRet) {
737 0 : maRect = pU->aR;
738 0 : ImpJustifyRect(maRect);
739 0 : nStartAngle=pU->nStart;
740 0 : nEndAngle=pU->nEnd;
741 : }
742 : }
743 0 : bClosedObj=meCircleKind!=OBJ_CARC;
744 0 : SetRectsDirty();
745 0 : SetXPolyDirty();
746 0 : ImpSetCircInfoToAttr();
747 0 : if (bRet) {
748 0 : delete pU;
749 0 : rStat.SetUser(NULL);
750 : }
751 0 : return bRet;
752 : }
753 :
754 0 : void SdrCircObj::BrkCreate(SdrDragStat& rStat)
755 : {
756 0 : ImpCircUser* pU=static_cast<ImpCircUser*>(rStat.GetUser());
757 0 : delete pU;
758 0 : rStat.SetUser(NULL);
759 0 : }
760 :
761 0 : bool SdrCircObj::BckCreate(SdrDragStat& rStat)
762 : {
763 0 : rStat.SetNoSnap(rStat.GetPointAnz()>=3);
764 0 : rStat.SetOrtho4Possible(rStat.GetPointAnz()<3);
765 0 : return meCircleKind!=OBJ_CIRC;
766 : }
767 :
768 0 : basegfx::B2DPolyPolygon SdrCircObj::TakeCreatePoly(const SdrDragStat& rDrag) const
769 : {
770 0 : const ImpCircUser* pU = static_cast<const ImpCircUser*>(rDrag.GetUser());
771 :
772 0 : if(rDrag.GetPointAnz() < 4L)
773 : {
774 : // force to OBJ_CIRC to get full visualisation
775 0 : basegfx::B2DPolyPolygon aRetval(ImpCalcXPolyCirc(OBJ_CIRC, pU->aR, pU->nStart, pU->nEnd));
776 :
777 0 : if(3L == rDrag.GetPointAnz())
778 : {
779 : // add edge to first point on ellipse
780 0 : basegfx::B2DPolygon aNew;
781 :
782 0 : aNew.append(basegfx::B2DPoint(pU->aCenter.X(), pU->aCenter.Y()));
783 0 : aNew.append(basegfx::B2DPoint(pU->aP1.X(), pU->aP1.Y()));
784 0 : aRetval.append(aNew);
785 : }
786 :
787 0 : return aRetval;
788 : }
789 : else
790 : {
791 0 : return basegfx::B2DPolyPolygon(ImpCalcXPolyCirc(meCircleKind, pU->aR, pU->nStart, pU->nEnd));
792 : }
793 : }
794 :
795 0 : Pointer SdrCircObj::GetCreatePointer() const
796 : {
797 0 : switch (meCircleKind) {
798 0 : case OBJ_CIRC: return Pointer(PointerStyle::DrawEllipse);
799 0 : case OBJ_SECT: return Pointer(PointerStyle::DrawPie);
800 0 : case OBJ_CARC: return Pointer(PointerStyle::DrawArc);
801 0 : case OBJ_CCUT: return Pointer(PointerStyle::DrawCircleCut);
802 0 : default: break;
803 : } // switch
804 0 : return Pointer(PointerStyle::Cross);
805 : }
806 :
807 142 : void SdrCircObj::NbcMove(const Size& aSiz)
808 : {
809 142 : MoveRect(maRect,aSiz);
810 142 : MoveRect(aOutRect,aSiz);
811 142 : MoveRect(maSnapRect,aSiz);
812 142 : SetXPolyDirty();
813 142 : SetRectsDirty(true);
814 142 : }
815 :
816 10 : void SdrCircObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
817 : {
818 10 : long nAngle0=aGeo.nRotationAngle;
819 10 : bool bNoShearRota=(aGeo.nRotationAngle==0 && aGeo.nShearAngle==0);
820 10 : SdrTextObj::NbcResize(rRef,xFact,yFact);
821 10 : bNoShearRota|=(aGeo.nRotationAngle==0 && aGeo.nShearAngle==0);
822 10 : if (meCircleKind!=OBJ_CIRC) {
823 10 : bool bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
824 10 : bool bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
825 10 : if (bXMirr || bYMirr) {
826 : // At bXMirr!=bYMirr we should actually swap both line ends.
827 : // That, however, is pretty bad (because of forced "hard" formatting).
828 : // Alternatively, we could implement a bMirrored flag (maybe even
829 : // a more general one, e. g. for mirrored text, ...).
830 0 : long nS0=nStartAngle;
831 0 : long nE0=nEndAngle;
832 0 : if (bNoShearRota) {
833 : // the RectObj already mirrors at VMirror because of a 180deg rotation
834 0 : if (! (bXMirr && bYMirr)) {
835 0 : long nTmp=nS0;
836 0 : nS0=18000-nE0;
837 0 : nE0=18000-nTmp;
838 : }
839 : } else { // mirror contorted ellipses
840 0 : if (bXMirr!=bYMirr) {
841 0 : nS0+=nAngle0;
842 0 : nE0+=nAngle0;
843 0 : if (bXMirr) {
844 0 : long nTmp=nS0;
845 0 : nS0=18000-nE0;
846 0 : nE0=18000-nTmp;
847 : }
848 0 : if (bYMirr) {
849 0 : long nTmp=nS0;
850 0 : nS0=-nE0;
851 0 : nE0=-nTmp;
852 : }
853 0 : nS0-=aGeo.nRotationAngle;
854 0 : nE0-=aGeo.nRotationAngle;
855 : }
856 : }
857 0 : long nAngleDif=nE0-nS0;
858 0 : nStartAngle=NormAngle360(nS0);
859 0 : nEndAngle =NormAngle360(nE0);
860 0 : if (nAngleDif==36000) nEndAngle+=nAngleDif; // full circle
861 : }
862 : }
863 10 : SetXPolyDirty();
864 10 : ImpSetCircInfoToAttr();
865 10 : }
866 :
867 0 : void SdrCircObj::NbcShear(const Point& rRef, long nAngle, double tn, bool bVShear)
868 : {
869 0 : SdrTextObj::NbcShear(rRef,nAngle,tn,bVShear);
870 0 : SetXPolyDirty();
871 0 : ImpSetCircInfoToAttr();
872 0 : }
873 :
874 0 : void SdrCircObj::NbcMirror(const Point& rRef1, const Point& rRef2)
875 : {
876 0 : bool bFreeMirr=meCircleKind!=OBJ_CIRC;
877 0 : Point aTmpPt1;
878 0 : Point aTmpPt2;
879 0 : if (bFreeMirr) { // some preparations for using an arbitrary axis of reflection
880 0 : Point aCenter(maRect.Center());
881 0 : long nWdt=maRect.GetWidth()-1;
882 0 : long nHgt=maRect.GetHeight()-1;
883 0 : long nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2;
884 : double a;
885 : // starting point
886 0 : a=nStartAngle*nPi180;
887 0 : aTmpPt1=Point(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad));
888 0 : if (nWdt==0) aTmpPt1.X()=0;
889 0 : if (nHgt==0) aTmpPt1.Y()=0;
890 0 : aTmpPt1+=aCenter;
891 : // finishing point
892 0 : a=nEndAngle*nPi180;
893 0 : aTmpPt2=Point(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad));
894 0 : if (nWdt==0) aTmpPt2.X()=0;
895 0 : if (nHgt==0) aTmpPt2.Y()=0;
896 0 : aTmpPt2+=aCenter;
897 0 : if (aGeo.nRotationAngle!=0) {
898 0 : RotatePoint(aTmpPt1,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
899 0 : RotatePoint(aTmpPt2,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
900 : }
901 0 : if (aGeo.nShearAngle!=0) {
902 0 : ShearPoint(aTmpPt1,maRect.TopLeft(),aGeo.nTan);
903 0 : ShearPoint(aTmpPt2,maRect.TopLeft(),aGeo.nTan);
904 : }
905 : }
906 0 : SdrTextObj::NbcMirror(rRef1,rRef2);
907 0 : if (meCircleKind!=OBJ_CIRC) { // adapt starting and finishing angle
908 0 : MirrorPoint(aTmpPt1,rRef1,rRef2);
909 0 : MirrorPoint(aTmpPt2,rRef1,rRef2);
910 : // unrotate:
911 0 : if (aGeo.nRotationAngle!=0) {
912 0 : RotatePoint(aTmpPt1,maRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin for reversion
913 0 : RotatePoint(aTmpPt2,maRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin for reversion
914 : }
915 : // unshear:
916 0 : if (aGeo.nShearAngle!=0) {
917 0 : ShearPoint(aTmpPt1,maRect.TopLeft(),-aGeo.nTan); // -tan for reversion
918 0 : ShearPoint(aTmpPt2,maRect.TopLeft(),-aGeo.nTan); // -tan for reversion
919 : }
920 0 : Point aCenter(maRect.Center());
921 0 : aTmpPt1-=aCenter;
922 0 : aTmpPt2-=aCenter;
923 : // because it's mirrored, the angles are swapped, too
924 0 : nStartAngle=GetAngle(aTmpPt2);
925 0 : nEndAngle =GetAngle(aTmpPt1);
926 0 : long nAngleDif=nEndAngle-nStartAngle;
927 0 : nStartAngle=NormAngle360(nStartAngle);
928 0 : nEndAngle =NormAngle360(nEndAngle);
929 0 : if (nAngleDif==36000) nEndAngle+=nAngleDif; // full circle
930 : }
931 0 : SetXPolyDirty();
932 0 : ImpSetCircInfoToAttr();
933 0 : }
934 :
935 0 : SdrObjGeoData* SdrCircObj::NewGeoData() const
936 : {
937 0 : return new SdrCircObjGeoData;
938 : }
939 :
940 0 : void SdrCircObj::SaveGeoData(SdrObjGeoData& rGeo) const
941 : {
942 0 : SdrRectObj::SaveGeoData(rGeo);
943 0 : SdrCircObjGeoData& rCGeo=static_cast<SdrCircObjGeoData&>(rGeo);
944 0 : rCGeo.nStartAngle=nStartAngle;
945 0 : rCGeo.nEndAngle =nEndAngle;
946 0 : }
947 :
948 0 : void SdrCircObj::RestGeoData(const SdrObjGeoData& rGeo)
949 : {
950 0 : SdrRectObj::RestGeoData(rGeo);
951 0 : const SdrCircObjGeoData& rCGeo=static_cast<const SdrCircObjGeoData&>(rGeo);
952 0 : nStartAngle=rCGeo.nStartAngle;
953 0 : nEndAngle =rCGeo.nEndAngle;
954 0 : SetXPolyDirty();
955 0 : ImpSetCircInfoToAttr();
956 0 : }
957 :
958 0 : void Union(Rectangle& rR, const Point& rP)
959 : {
960 0 : if (rP.X()<rR.Left ()) rR.Left ()=rP.X();
961 0 : if (rP.X()>rR.Right ()) rR.Right ()=rP.X();
962 0 : if (rP.Y()<rR.Top ()) rR.Top ()=rP.Y();
963 0 : if (rP.Y()>rR.Bottom()) rR.Bottom()=rP.Y();
964 0 : }
965 :
966 83 : void SdrCircObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
967 : {
968 83 : rRect = maRect;
969 83 : if (meCircleKind!=OBJ_CIRC) {
970 0 : const Point aPntStart(GetAnglePnt(maRect,nStartAngle));
971 0 : const Point aPntEnd(GetAnglePnt(maRect,nEndAngle));
972 0 : long a=nStartAngle;
973 0 : long e=nEndAngle;
974 0 : rRect.Left ()=maRect.Right();
975 0 : rRect.Right ()=maRect.Left();
976 0 : rRect.Top ()=maRect.Bottom();
977 0 : rRect.Bottom()=maRect.Top();
978 0 : Union(rRect,aPntStart);
979 0 : Union(rRect,aPntEnd);
980 0 : if ((a<=18000 && e>=18000) || (a>e && (a<=18000 || e>=18000))) {
981 0 : Union(rRect,maRect.LeftCenter());
982 : }
983 0 : if ((a<=27000 && e>=27000) || (a>e && (a<=27000 || e>=27000))) {
984 0 : Union(rRect,maRect.BottomCenter());
985 : }
986 0 : if (a>e) {
987 0 : Union(rRect,maRect.RightCenter());
988 : }
989 0 : if ((a<=9000 && e>=9000) || (a>e && (a<=9000 || e>=9000))) {
990 0 : Union(rRect,maRect.TopCenter());
991 : }
992 0 : if (meCircleKind==OBJ_SECT) {
993 0 : Union(rRect,maRect.Center());
994 : }
995 0 : if (aGeo.nRotationAngle!=0) {
996 0 : Point aDst(rRect.TopLeft());
997 0 : aDst-=maRect.TopLeft();
998 0 : Point aDst0(aDst);
999 0 : RotatePoint(aDst,Point(),aGeo.nSin,aGeo.nCos);
1000 0 : aDst-=aDst0;
1001 0 : rRect.Move(aDst.X(),aDst.Y());
1002 : }
1003 : }
1004 83 : if (aGeo.nShearAngle!=0) {
1005 0 : long nDst=Round((rRect.Bottom()-rRect.Top())*aGeo.nTan);
1006 0 : if (aGeo.nShearAngle>0) {
1007 0 : Point aRef(rRect.TopLeft());
1008 0 : rRect.Left()-=nDst;
1009 0 : Point aTmpPt(rRect.TopLeft());
1010 0 : RotatePoint(aTmpPt,aRef,aGeo.nSin,aGeo.nCos);
1011 0 : aTmpPt-=rRect.TopLeft();
1012 0 : rRect.Move(aTmpPt.X(),aTmpPt.Y());
1013 : } else {
1014 0 : rRect.Right()-=nDst;
1015 : }
1016 : }
1017 83 : }
1018 :
1019 149 : void SdrCircObj::RecalcSnapRect()
1020 : {
1021 149 : if (PaintNeedsXPolyCirc()) {
1022 66 : maSnapRect=GetXPoly().GetBoundRect();
1023 : } else {
1024 83 : TakeUnrotatedSnapRect(maSnapRect);
1025 : }
1026 149 : }
1027 :
1028 58 : void SdrCircObj::NbcSetSnapRect(const Rectangle& rRect)
1029 : {
1030 58 : if (aGeo.nRotationAngle!=0 || aGeo.nShearAngle!=0 || meCircleKind!=OBJ_CIRC) {
1031 10 : Rectangle aSR0(GetSnapRect());
1032 10 : long nWdt0=aSR0.Right()-aSR0.Left();
1033 10 : long nHgt0=aSR0.Bottom()-aSR0.Top();
1034 10 : long nWdt1=rRect.Right()-rRect.Left();
1035 10 : long nHgt1=rRect.Bottom()-rRect.Top();
1036 10 : NbcResize(maSnapRect.TopLeft(),Fraction(nWdt1,nWdt0),Fraction(nHgt1,nHgt0));
1037 10 : NbcMove(Size(rRect.Left()-aSR0.Left(),rRect.Top()-aSR0.Top()));
1038 : } else {
1039 48 : maRect=rRect;
1040 48 : ImpJustifyRect(maRect);
1041 : }
1042 58 : SetRectsDirty();
1043 58 : SetXPolyDirty();
1044 58 : ImpSetCircInfoToAttr();
1045 58 : }
1046 :
1047 0 : sal_uInt32 SdrCircObj::GetSnapPointCount() const
1048 : {
1049 0 : if (meCircleKind==OBJ_CIRC) {
1050 0 : return 1L;
1051 : } else {
1052 0 : return 3L;
1053 : }
1054 : }
1055 :
1056 0 : Point SdrCircObj::GetSnapPoint(sal_uInt32 i) const
1057 : {
1058 0 : switch (i) {
1059 0 : case 1 : return GetAnglePnt(maRect,nStartAngle);
1060 0 : case 2 : return GetAnglePnt(maRect,nEndAngle);
1061 0 : default: return maRect.Center();
1062 : }
1063 : }
1064 :
1065 182 : void SdrCircObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
1066 : {
1067 182 : SetXPolyDirty();
1068 182 : SdrRectObj::Notify(rBC,rHint);
1069 182 : ImpSetAttrToCircInfo();
1070 182 : }
1071 :
1072 :
1073 :
1074 844 : void SdrCircObj::ImpSetAttrToCircInfo()
1075 : {
1076 844 : const SfxItemSet& rSet = GetObjectItemSet();
1077 844 : SdrCircKind eNewKindA = static_cast<const SdrCircKindItem&>(rSet.Get(SDRATTR_CIRCKIND)).GetValue();
1078 844 : SdrObjKind eNewKind = meCircleKind;
1079 :
1080 844 : if(eNewKindA == SDRCIRC_FULL)
1081 569 : eNewKind = OBJ_CIRC;
1082 275 : else if(eNewKindA == SDRCIRC_SECT)
1083 94 : eNewKind = OBJ_SECT;
1084 181 : else if(eNewKindA == SDRCIRC_ARC)
1085 72 : eNewKind = OBJ_CARC;
1086 109 : else if(eNewKindA == SDRCIRC_CUT)
1087 109 : eNewKind = OBJ_CCUT;
1088 :
1089 844 : sal_Int32 nNewStart = static_cast<const SdrAngleItem&>(rSet.Get(SDRATTR_CIRCSTARTANGLE)).GetValue();
1090 844 : sal_Int32 nNewEnd = static_cast<const SdrAngleItem&>(rSet.Get(SDRATTR_CIRCENDANGLE)).GetValue();
1091 :
1092 844 : bool bKindChg = meCircleKind != eNewKind;
1093 844 : bool bAngleChg = nNewStart != nStartAngle || nNewEnd != nEndAngle;
1094 :
1095 844 : if(bKindChg || bAngleChg)
1096 : {
1097 123 : meCircleKind = eNewKind;
1098 123 : nStartAngle = nNewStart;
1099 123 : nEndAngle = nNewEnd;
1100 :
1101 123 : if(bKindChg || (meCircleKind != OBJ_CIRC && bAngleChg))
1102 : {
1103 123 : SetXPolyDirty();
1104 123 : SetRectsDirty();
1105 : }
1106 : }
1107 844 : }
1108 :
1109 68 : void SdrCircObj::ImpSetCircInfoToAttr()
1110 : {
1111 68 : SdrCircKind eNewKindA = SDRCIRC_FULL;
1112 68 : const SfxItemSet& rSet = GetObjectItemSet();
1113 :
1114 68 : if(meCircleKind == OBJ_SECT)
1115 0 : eNewKindA = SDRCIRC_SECT;
1116 68 : else if(meCircleKind == OBJ_CARC)
1117 0 : eNewKindA = SDRCIRC_ARC;
1118 68 : else if(meCircleKind == OBJ_CCUT)
1119 20 : eNewKindA = SDRCIRC_CUT;
1120 :
1121 68 : SdrCircKind eOldKindA = static_cast<const SdrCircKindItem&>(rSet.Get(SDRATTR_CIRCKIND)).GetValue();
1122 68 : sal_Int32 nOldStartAngle = static_cast<const SdrAngleItem&>(rSet.Get(SDRATTR_CIRCSTARTANGLE)).GetValue();
1123 68 : sal_Int32 nOldEndAngle = static_cast<const SdrAngleItem&>(rSet.Get(SDRATTR_CIRCENDANGLE)).GetValue();
1124 :
1125 68 : if(eNewKindA != eOldKindA || nStartAngle != nOldStartAngle || nEndAngle != nOldEndAngle)
1126 : {
1127 : // since SetItem() implicitly calls ImpSetAttrToCircInfo()
1128 : // setting the item directly is necessary here.
1129 0 : if(eNewKindA != eOldKindA)
1130 : {
1131 0 : GetProperties().SetObjectItemDirect(SdrCircKindItem(eNewKindA));
1132 : }
1133 :
1134 0 : if(nStartAngle != nOldStartAngle)
1135 : {
1136 0 : GetProperties().SetObjectItemDirect(makeSdrCircStartAngleItem(nStartAngle));
1137 : }
1138 :
1139 0 : if(nEndAngle != nOldEndAngle)
1140 : {
1141 0 : GetProperties().SetObjectItemDirect(makeSdrCircEndAngleItem(nEndAngle));
1142 : }
1143 :
1144 0 : SetXPolyDirty();
1145 0 : ImpSetAttrToCircInfo();
1146 : }
1147 68 : }
1148 :
1149 3 : SdrObject* SdrCircObj::DoConvertToPolyObj(bool bBezier, bool bAddText) const
1150 : {
1151 3 : const bool bFill(meCircleKind != OBJ_CARC);
1152 3 : const basegfx::B2DPolygon aCircPolygon(ImpCalcXPolyCirc(meCircleKind, maRect, nStartAngle, nEndAngle));
1153 3 : SdrObject* pRet = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aCircPolygon), bFill, bBezier);
1154 :
1155 3 : if(bAddText)
1156 : {
1157 3 : pRet = ImpConvertAddText(pRet, bBezier);
1158 : }
1159 :
1160 3 : return pRet;
1161 435 : }
1162 :
1163 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|