1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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>
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()
88 SdrRectObj::SdrRectObj(const Rectangle
& rRect
)
95 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind
)
96 : SdrTextObj(eNewTextKind
),
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");
105 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind
, const Rectangle
& rRect
)
106 : SdrTextObj(eNewTextKind
,rRect
),
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");
115 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind
, const Rectangle
& rNewRect
, SvStream
& rInput
, const String
& rBaseURL
, USHORT eFormat
)
116 : SdrTextObj(eNewTextKind
,rNewRect
,rInput
,rBaseURL
,eFormat
),
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");
125 SdrRectObj::~SdrRectObj()
133 void SdrRectObj::SetXPolyDirty()
142 FASTBOOL
SdrRectObj::PaintNeedsXPoly(long nEckRad
) const
144 FASTBOOL bNeed
=aGeo
.nDrehWink
!=0 || aGeo
.nShearWink
!=0 || nEckRad
!=0;
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;
156 for (sal_uInt16 i
=1; i
<nPointAnz
; i
++) {
157 aNeuPoly
[i
]=aXPoly
[j
];
158 aNeuPoly
.SetFlags(i
,aXPoly
.GetFlags(j
));
160 if (j
>=nPointAnz
) j
=1;
162 aNeuPoly
[0]=rRect1
.BottomCenter();
163 aNeuPoly
[nPointAnz
]=aNeuPoly
[0];
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
);
172 void SdrRectObj::RecalcXPoly()
174 mpXPoly
= new XPolygon(ImpCalcXPoly(aRect
,GetEckenradius()));
177 const XPolygon
& SdrRectObj::GetXPoly() const
181 ((SdrRectObj
*)this)->RecalcXPoly();
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
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());
231 Point
aTmpPt(rRect
.TopLeft());
232 RotatePoint(aTmpPt
,aRef
,aGeo
.nSin
,aGeo
.nCos
);
233 aTmpPt
-=rRect
.TopLeft();
234 rRect
.Move(aTmpPt
.X(),aTmpPt
.Y());
241 void SdrRectObj::TakeObjNameSingul(XubString
& rName
) const
245 SdrTextObj::TakeObjNameSingul(rName
);
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.
255 if (aRect
.GetWidth()==aRect
.GetHeight()) nResId
+=2; // Quadrat
257 if (GetEckenradius()!=0) nResId
+=8; // abgerundet
258 rName
=ImpGetResStr(nResId
);
260 String
aName( GetName() );
263 rName
+= sal_Unicode(' ');
264 rName
+= sal_Unicode('\'');
266 rName
+= sal_Unicode('\'');
271 void SdrRectObj::TakeObjNamePlural(XubString
& rName
) const
273 if (IsTextFrame()) SdrTextObj::TakeObjNamePlural(rName
);
275 USHORT nResId
=STR_ObjNamePluralRECT
;
276 if (aGeo
.nShearWink
!=0) {
277 nResId
+=4; // Parallelogramm oder Raute
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
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();
304 SdrTextObj::RecalcSnapRect();
308 void SdrRectObj::NbcSetSnapRect(const Rectangle
& rRect
)
310 SdrTextObj::NbcSetSnapRect(rRect
);
314 void SdrRectObj::NbcSetLogicRect(const Rectangle
& rRect
)
316 SdrTextObj::NbcSetLogicRect(rRect
);
320 sal_uInt32
SdrRectObj::GetHdlCount() const
325 SdrHdl
* SdrRectObj::GetHdl(sal_uInt32 nHdlNum
) const
329 SdrHdlKind eKind
=HDL_MOVE
;
330 if( IsTextFrame() && !nHdlNum
)
332 pH
=new ImpTextframeHdl(aRect
);
333 pH
->SetObj((SdrObject
*)this);
334 pH
->SetDrehWink(aGeo
.nDrehWink
);
341 long a
=GetEckenradius();
342 long b
=Max(aRect
.GetWidth(),aRect
.GetHeight())/2; // Wird aufgerundet, da GetWidth() eins draufaddiert
345 aPnt
=aRect
.TopLeft();
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
);
369 ////////////////////////////////////////////////////////////////////////////////////////////////////
371 bool SdrRectObj::hasSpecialDrag() const
376 bool SdrRectObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
378 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
382 rDrag
.SetEndDragChangesAttributes(true);
387 return SdrTextObj::beginSpecialDrag(rDrag
);
390 bool SdrRectObj::applySpecialDrag(SdrDragStat
& rDrag
)
392 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
396 Rectangle aBoundRect0
;
397 Point
aPt(rDrag
.GetNow());
400 RotatePoint(aPt
,aRect
.TopLeft(),-aGeo
.nSin
,aGeo
.nCos
);
402 sal_Int32
nRad(aPt
.X() - aRect
.Left());
407 if(nRad
!= GetEckenradius())
409 NbcSetEckenradius(nRad
);
416 return SdrTextObj::applySpecialDrag(rDrag
);
420 String
SdrRectObj::getSpecialDragComment(const SdrDragStat
& rDrag
) const
422 const bool bCreateComment(rDrag
.GetView() && this == rDrag
.GetView()->GetCreateObj());
430 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
434 Point
aPt(rDrag
.GetNow());
436 // -sin fuer Umkehrung
438 RotatePoint(aPt
, aRect
.TopLeft(), -aGeo
.nSin
, aGeo
.nCos
);
440 sal_Int32
nRad(aPt
.X() - aRect
.Left());
447 ImpTakeDescriptionStr(STR_DragRectEckRad
, aStr
);
448 aStr
.AppendAscii(" (");
449 aStr
+= GetMetrStr(nRad
);
450 aStr
+= sal_Unicode(')');
456 return SdrTextObj::getSpecialDragComment(rDrag
);
461 ////////////////////////////////////////////////////////////////////////////////////////////////////
463 basegfx::B2DPolyPolygon
SdrRectObj::TakeCreatePoly(const SdrDragStat
& rDrag
) const
466 rDrag
.TakeCreateRect(aRect1
);
469 basegfx::B2DPolyPolygon aRetval
;
470 aRetval
.append(ImpCalcXPoly(aRect1
,GetEckenradius()).getB2DPolygon());
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
);
486 void SdrRectObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
488 SdrTextObj::NbcResize(rRef
,xFact
,yFact
);
492 void SdrRectObj::NbcRotate(const Point
& rRef
, long nWink
, double sn
, double cs
)
494 SdrTextObj::NbcRotate(rRef
,nWink
,sn
,cs
);
498 void SdrRectObj::NbcShear(const Point
& rRef
, long nWink
, double tn
, FASTBOOL bVShear
)
500 SdrTextObj::NbcShear(rRef
,nWink
,tn
,bVShear
);
504 void SdrRectObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
506 SdrTextObj::NbcMirror(rRef1
,rRef2
);
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();
525 if(!LineIsOutsideGeometry())
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
);
546 SdrGluePoint
SdrRectObj::GetCornerGluePoint(USHORT nPosNum
) const
548 INT32 nWdt
= ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue();
551 if(!LineIsOutsideGeometry())
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
);
572 SdrObject
* SdrRectObj::DoConvertToPolyObj(BOOL bBezier
) const
574 XPolygon
aXP(ImpCalcXPoly(aRect
,GetEckenradius()));
575 { // #40608# Nur Uebergangsweise bis zum neuen TakeContour()
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
);
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
);