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