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