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