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