Update ooo320-m1
[ooovba.git] / svx / source / svdraw / svdorect.cxx
blobf6c0fbc6ead03e975e95f3baa100a62b64fd0725
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svdorect.cxx,v $
10 * $Revision: 1.31.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <svx/svdorect.hxx>
35 #include <math.h>
36 #include <stdlib.h>
37 #include <svx/xpool.hxx>
38 #include <svx/xpoly.hxx>
39 #include <svx/svdattr.hxx>
40 #include <svx/svdpool.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/svdocapt.hxx> // fuer Import von SdrFileVersion 2
47 #include <svx/svdpagv.hxx> // fuer
48 #include <svx/svdview.hxx> // das
49 #include <svx/svdundo.hxx> // Macro-Beispiel
50 #include <svx/svdopath.hxx>
51 #include "svdglob.hxx" // Stringcache
52 #include "svdstr.hrc" // Objektname
53 #include <svx/xflclit.hxx>
54 #include <svx/xlnclit.hxx>
55 #include <svx/xlnwtit.hxx>
56 #include "svdoimp.hxx"
57 #include <svx/sdr/properties/rectangleproperties.hxx>
58 #include <svx/sdr/contact/viewcontactofsdrrectobj.hxx>
59 #include <basegfx/polygon/b2dpolygon.hxx>
60 #include <basegfx/polygon/b2dpolygontools.hxx>
62 //////////////////////////////////////////////////////////////////////////////
63 // BaseProperties section
65 sdr::properties::BaseProperties* SdrRectObj::CreateObjectSpecificProperties()
67 return new sdr::properties::RectangleProperties(*this);
70 //////////////////////////////////////////////////////////////////////////////
71 // DrawContact section
73 sdr::contact::ViewContact* SdrRectObj::CreateObjectSpecificViewContact()
75 return new sdr::contact::ViewContactOfSdrRectObj(*this);
78 //////////////////////////////////////////////////////////////////////////////
80 TYPEINIT1(SdrRectObj,SdrTextObj);
82 SdrRectObj::SdrRectObj()
83 : mpXPoly(0L)
85 bClosedObj=TRUE;
88 SdrRectObj::SdrRectObj(const Rectangle& rRect)
89 : SdrTextObj(rRect),
90 mpXPoly(NULL)
92 bClosedObj=TRUE;
95 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind)
96 : SdrTextObj(eNewTextKind),
97 mpXPoly(NULL)
99 DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT ||
100 eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT,
101 "SdrRectObj::SdrRectObj(SdrObjKind) ist nur fuer Textrahmen gedacht");
102 bClosedObj=TRUE;
105 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rRect)
106 : SdrTextObj(eNewTextKind,rRect),
107 mpXPoly(NULL)
109 DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT ||
110 eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT,
111 "SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht");
112 bClosedObj=TRUE;
115 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect, SvStream& rInput, const String& rBaseURL, USHORT eFormat)
116 : SdrTextObj(eNewTextKind,rNewRect,rInput,rBaseURL,eFormat),
117 mpXPoly(NULL)
119 DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT ||
120 eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT,
121 "SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht");
122 bClosedObj=TRUE;
125 SdrRectObj::~SdrRectObj()
127 if(mpXPoly)
129 delete mpXPoly;
133 void SdrRectObj::SetXPolyDirty()
135 if(mpXPoly)
137 delete mpXPoly;
138 mpXPoly = 0L;
142 FASTBOOL SdrRectObj::PaintNeedsXPoly(long nEckRad) const
144 FASTBOOL bNeed=aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || nEckRad!=0;
145 return bNeed;
148 XPolygon SdrRectObj::ImpCalcXPoly(const Rectangle& rRect1, long nRad1) const
150 XPolygon aXPoly(rRect1,nRad1,nRad1);
151 const sal_uInt16 nPointAnz(aXPoly.GetPointCount());
152 XPolygon aNeuPoly(nPointAnz+1);
153 sal_uInt16 nShift=nPointAnz-2;
154 if (nRad1!=0) nShift=nPointAnz-5;
155 sal_uInt16 j=nShift;
156 for (sal_uInt16 i=1; i<nPointAnz; i++) {
157 aNeuPoly[i]=aXPoly[j];
158 aNeuPoly.SetFlags(i,aXPoly.GetFlags(j));
159 j++;
160 if (j>=nPointAnz) j=1;
162 aNeuPoly[0]=rRect1.BottomCenter();
163 aNeuPoly[nPointAnz]=aNeuPoly[0];
164 aXPoly=aNeuPoly;
166 // Die Winkelangaben beziehen sich immer auf die linke obere Ecke von !aRect!
167 if (aGeo.nShearWink!=0) ShearXPoly(aXPoly,aRect.TopLeft(),aGeo.nTan);
168 if (aGeo.nDrehWink!=0) RotateXPoly(aXPoly,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
169 return aXPoly;
172 void SdrRectObj::RecalcXPoly()
174 mpXPoly = new XPolygon(ImpCalcXPoly(aRect,GetEckenradius()));
177 const XPolygon& SdrRectObj::GetXPoly() const
179 if(!mpXPoly)
181 ((SdrRectObj*)this)->RecalcXPoly();
184 return *mpXPoly;
187 void SdrRectObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
189 FASTBOOL bNoTextFrame=!IsTextFrame();
190 rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0;
191 rInfo.bResizePropAllowed=TRUE;
192 rInfo.bRotateFreeAllowed=TRUE;
193 rInfo.bRotate90Allowed =TRUE;
194 rInfo.bMirrorFreeAllowed=bNoTextFrame;
195 rInfo.bMirror45Allowed =bNoTextFrame;
196 rInfo.bMirror90Allowed =bNoTextFrame;
198 // allow transparence
199 rInfo.bTransparenceAllowed = TRUE;
201 // gradient depends on fillstyle
202 XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue();
203 rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT);
205 rInfo.bShearAllowed =bNoTextFrame;
206 rInfo.bEdgeRadiusAllowed=TRUE;
208 FASTBOOL bCanConv=!HasText() || ImpCanConvTextToCurve();
209 if (bCanConv && !bNoTextFrame && !HasText()) {
210 bCanConv=HasFill() || HasLine();
212 rInfo.bCanConvToPath =bCanConv;
213 rInfo.bCanConvToPoly =bCanConv;
214 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
217 UINT16 SdrRectObj::GetObjIdentifier() const
219 if (IsTextFrame()) return UINT16(eTextKind);
220 else return UINT16(OBJ_RECT);
223 void SdrRectObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
225 rRect=aRect;
226 if (aGeo.nShearWink!=0) {
227 long nDst=Round((aRect.Bottom()-aRect.Top())*aGeo.nTan);
228 if (aGeo.nShearWink>0) {
229 Point aRef(rRect.TopLeft());
230 rRect.Left()-=nDst;
231 Point aTmpPt(rRect.TopLeft());
232 RotatePoint(aTmpPt,aRef,aGeo.nSin,aGeo.nCos);
233 aTmpPt-=rRect.TopLeft();
234 rRect.Move(aTmpPt.X(),aTmpPt.Y());
235 } else {
236 rRect.Right()-=nDst;
241 void SdrRectObj::TakeObjNameSingul(XubString& rName) const
243 if (IsTextFrame())
245 SdrTextObj::TakeObjNameSingul(rName);
247 else
249 USHORT nResId=STR_ObjNameSingulRECT;
250 if (aGeo.nShearWink!=0) {
251 nResId+=4; // Parallelogramm oder Raute
252 // Raute ist nicht, weil Shear die vertikalen Kanten verlaengert!
253 // Wenn Zeit ist, werde ich das mal berechnen.
254 } else {
255 if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat
257 if (GetEckenradius()!=0) nResId+=8; // abgerundet
258 rName=ImpGetResStr(nResId);
260 String aName( GetName() );
261 if(aName.Len())
263 rName += sal_Unicode(' ');
264 rName += sal_Unicode('\'');
265 rName += aName;
266 rName += sal_Unicode('\'');
271 void SdrRectObj::TakeObjNamePlural(XubString& rName) const
273 if (IsTextFrame()) SdrTextObj::TakeObjNamePlural(rName);
274 else {
275 USHORT nResId=STR_ObjNamePluralRECT;
276 if (aGeo.nShearWink!=0) {
277 nResId+=4; // Parallelogramm oder Raute
278 } else {
279 if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat
281 if (GetEckenradius()!=0) nResId+=8; // abgerundet
282 rName=ImpGetResStr(nResId);
286 void SdrRectObj::operator=(const SdrObject& rObj)
288 SdrTextObj::operator=(rObj);
291 basegfx::B2DPolyPolygon SdrRectObj::TakeXorPoly() const
293 XPolyPolygon aXPP;
294 aXPP.Insert(ImpCalcXPoly(aRect,GetEckenradius()));
295 return aXPP.getB2DPolyPolygon();
298 void SdrRectObj::RecalcSnapRect()
300 long nEckRad=GetEckenradius();
301 if ((aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) && nEckRad!=0) {
302 maSnapRect=GetXPoly().GetBoundRect();
303 } else {
304 SdrTextObj::RecalcSnapRect();
308 void SdrRectObj::NbcSetSnapRect(const Rectangle& rRect)
310 SdrTextObj::NbcSetSnapRect(rRect);
311 SetXPolyDirty();
314 void SdrRectObj::NbcSetLogicRect(const Rectangle& rRect)
316 SdrTextObj::NbcSetLogicRect(rRect);
317 SetXPolyDirty();
320 sal_uInt32 SdrRectObj::GetHdlCount() const
322 return 9L;
325 SdrHdl* SdrRectObj::GetHdl(sal_uInt32 nHdlNum) const
327 SdrHdl* pH=NULL;
328 Point aPnt;
329 SdrHdlKind eKind=HDL_MOVE;
330 if( IsTextFrame() && !nHdlNum )
332 pH=new ImpTextframeHdl(aRect);
333 pH->SetObj((SdrObject*)this);
334 pH->SetDrehWink(aGeo.nDrehWink);
335 return pH;
337 else
339 switch (nHdlNum) {
340 case 0: {
341 long a=GetEckenradius();
342 long b=Max(aRect.GetWidth(),aRect.GetHeight())/2; // Wird aufgerundet, da GetWidth() eins draufaddiert
343 if (a>b) a=b;
344 if (a<0) a=0;
345 aPnt=aRect.TopLeft();
346 aPnt.X()+=a;
347 eKind=HDL_CIRC;
348 } break; // Eckenradius
349 case 1: aPnt=aRect.TopLeft(); eKind=HDL_UPLFT; break; // Oben links
350 case 2: aPnt=aRect.TopCenter(); eKind=HDL_UPPER; break; // Oben
351 case 3: aPnt=aRect.TopRight(); eKind=HDL_UPRGT; break; // Oben rechts
352 case 4: aPnt=aRect.LeftCenter(); eKind=HDL_LEFT ; break; // Links
353 case 5: aPnt=aRect.RightCenter(); eKind=HDL_RIGHT; break; // Rechts
354 case 6: aPnt=aRect.BottomLeft(); eKind=HDL_LWLFT; break; // Unten links
355 case 7: aPnt=aRect.BottomCenter(); eKind=HDL_LOWER; break; // Unten
356 case 8: aPnt=aRect.BottomRight(); eKind=HDL_LWRGT; break; // Unten rechts
359 if (aGeo.nShearWink!=0) ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan);
360 if (aGeo.nDrehWink!=0) RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
361 if (eKind!=HDL_MOVE) {
362 pH=new SdrHdl(aPnt,eKind);
363 pH->SetObj((SdrObject*)this);
364 pH->SetDrehWink(aGeo.nDrehWink);
366 return pH;
369 ////////////////////////////////////////////////////////////////////////////////////////////////////
371 bool SdrRectObj::hasSpecialDrag() const
373 return true;
376 bool SdrRectObj::beginSpecialDrag(SdrDragStat& rDrag) const
378 const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
380 if(bRad)
382 rDrag.SetEndDragChangesAttributes(true);
384 return true;
387 return SdrTextObj::beginSpecialDrag(rDrag);
390 bool SdrRectObj::applySpecialDrag(SdrDragStat& rDrag)
392 const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
394 if (bRad)
396 Rectangle aBoundRect0;
397 Point aPt(rDrag.GetNow());
399 if(aGeo.nDrehWink)
400 RotatePoint(aPt,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos);
402 sal_Int32 nRad(aPt.X() - aRect.Left());
404 if (nRad < 0)
405 nRad = 0;
407 if(nRad != GetEckenradius())
409 NbcSetEckenradius(nRad);
412 return true;
414 else
416 return SdrTextObj::applySpecialDrag(rDrag);
420 String SdrRectObj::getSpecialDragComment(const SdrDragStat& rDrag) const
422 const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
424 if(bCreateComment)
426 return String();
428 else
430 const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
432 if(bRad)
434 Point aPt(rDrag.GetNow());
436 // -sin fuer Umkehrung
437 if(aGeo.nDrehWink)
438 RotatePoint(aPt, aRect.TopLeft(), -aGeo.nSin, aGeo.nCos);
440 sal_Int32 nRad(aPt.X() - aRect.Left());
442 if(nRad < 0)
443 nRad = 0;
445 XubString aStr;
447 ImpTakeDescriptionStr(STR_DragRectEckRad, aStr);
448 aStr.AppendAscii(" (");
449 aStr += GetMetrStr(nRad);
450 aStr += sal_Unicode(')');
452 return aStr;
454 else
456 return SdrTextObj::getSpecialDragComment(rDrag);
461 ////////////////////////////////////////////////////////////////////////////////////////////////////
463 basegfx::B2DPolyPolygon SdrRectObj::TakeCreatePoly(const SdrDragStat& rDrag) const
465 Rectangle aRect1;
466 rDrag.TakeCreateRect(aRect1);
467 aRect1.Justify();
469 basegfx::B2DPolyPolygon aRetval;
470 aRetval.append(ImpCalcXPoly(aRect1,GetEckenradius()).getB2DPolygon());
471 return aRetval;
474 Pointer SdrRectObj::GetCreatePointer() const
476 if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT);
477 return Pointer(POINTER_DRAW_RECT);
480 void SdrRectObj::NbcMove(const Size& rSiz)
482 SdrTextObj::NbcMove(rSiz);
483 SetXPolyDirty();
486 void SdrRectObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
488 SdrTextObj::NbcResize(rRef,xFact,yFact);
489 SetXPolyDirty();
492 void SdrRectObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
494 SdrTextObj::NbcRotate(rRef,nWink,sn,cs);
495 SetXPolyDirty();
498 void SdrRectObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
500 SdrTextObj::NbcShear(rRef,nWink,tn,bVShear);
501 SetXPolyDirty();
504 void SdrRectObj::NbcMirror(const Point& rRef1, const Point& rRef2)
506 SdrTextObj::NbcMirror(rRef1,rRef2);
507 SetXPolyDirty();
510 FASTBOOL SdrRectObj::DoMacro(const SdrObjMacroHitRec& rRec)
512 return SdrTextObj::DoMacro(rRec);
515 XubString SdrRectObj::GetMacroPopupComment(const SdrObjMacroHitRec& rRec) const
517 return SdrTextObj::GetMacroPopupComment(rRec);
520 SdrGluePoint SdrRectObj::GetVertexGluePoint(USHORT nPosNum) const
522 INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue();
524 // #i25616#
525 if(!LineIsOutsideGeometry())
527 nWdt++;
528 nWdt /= 2;
531 Point aPt;
532 switch (nPosNum) {
533 case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break;
534 case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break;
535 case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break;
536 case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break;
538 if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan);
539 if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
540 aPt-=GetSnapRect().Center();
541 SdrGluePoint aGP(aPt);
542 aGP.SetPercent(FALSE);
543 return aGP;
546 SdrGluePoint SdrRectObj::GetCornerGluePoint(USHORT nPosNum) const
548 INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue();
550 // #i25616#
551 if(!LineIsOutsideGeometry())
553 nWdt++;
554 nWdt /= 2;
557 Point aPt;
558 switch (nPosNum) {
559 case 0: aPt=aRect.TopLeft(); aPt.X()-=nWdt; aPt.Y()-=nWdt; break;
560 case 1: aPt=aRect.TopRight(); aPt.X()+=nWdt; aPt.Y()-=nWdt; break;
561 case 2: aPt=aRect.BottomRight(); aPt.X()+=nWdt; aPt.Y()+=nWdt; break;
562 case 3: aPt=aRect.BottomLeft(); aPt.X()-=nWdt; aPt.Y()+=nWdt; break;
564 if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan);
565 if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
566 aPt-=GetSnapRect().Center();
567 SdrGluePoint aGP(aPt);
568 aGP.SetPercent(FALSE);
569 return aGP;
572 SdrObject* SdrRectObj::DoConvertToPolyObj(BOOL bBezier) const
574 XPolygon aXP(ImpCalcXPoly(aRect,GetEckenradius()));
575 { // #40608# Nur Uebergangsweise bis zum neuen TakeContour()
576 aXP.Remove(0,1);
577 aXP[aXP.GetPointCount()-1]=aXP[0];
580 basegfx::B2DPolyPolygon aPolyPolygon(aXP.getB2DPolygon());
581 aPolyPolygon.removeDoublePoints();
582 SdrObject* pRet = 0L;
584 if(!IsTextFrame() || HasFill() || HasLine())
586 pRet = ImpConvertMakeObj(aPolyPolygon, sal_True, bBezier);
589 pRet = ImpConvertAddText(pRet, bBezier);
591 return pRet;
594 void SdrRectObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
596 SdrTextObj::Notify(rBC,rHint);
597 SetXPolyDirty(); // wg. Eckenradius
600 void SdrRectObj::RestGeoData(const SdrObjGeoData& rGeo)
602 SdrTextObj::RestGeoData(rGeo);
603 SetXPolyDirty();
606 // eof