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