1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svdorect.hxx>
23 #include <svx/xpool.hxx>
24 #include <svx/xpoly.hxx>
25 #include <svx/svdattr.hxx>
26 #include <svx/svdpool.hxx>
27 #include <svx/svdtrans.hxx>
28 #include <svx/svdetc.hxx>
29 #include <svx/svddrag.hxx>
30 #include <svx/svdmodel.hxx>
31 #include <svx/svdpage.hxx>
32 #include <svx/svdocapt.hxx>
33 #include <svx/svdpagv.hxx>
34 #include <svx/svdview.hxx>
35 #include <svx/svdundo.hxx>
36 #include <svx/svdopath.hxx>
37 #include "svdglob.hxx"
38 #include "svx/svdstr.hrc"
39 #include <svx/xflclit.hxx>
40 #include <svx/xlnclit.hxx>
41 #include <svx/xlnwtit.hxx>
42 #include <svx/sdr/properties/rectangleproperties.hxx>
43 #include <svx/sdr/contact/viewcontactofsdrrectobj.hxx>
44 #include <basegfx/polygon/b2dpolygon.hxx>
45 #include <basegfx/polygon/b2dpolygontools.hxx>
48 // BaseProperties section
50 sdr::properties::BaseProperties
* SdrRectObj::CreateObjectSpecificProperties()
52 return new sdr::properties::RectangleProperties(*this);
56 // DrawContact section
58 sdr::contact::ViewContact
* SdrRectObj::CreateObjectSpecificViewContact()
60 return new sdr::contact::ViewContactOfSdrRectObj(*this);
65 TYPEINIT1(SdrRectObj
,SdrTextObj
);
67 SdrRectObj::SdrRectObj()
73 SdrRectObj::SdrRectObj(const Rectangle
& rRect
)
80 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind
)
81 : SdrTextObj(eNewTextKind
),
84 DBG_ASSERT(eTextKind
==OBJ_TEXT
|| eTextKind
==OBJ_TEXTEXT
||
85 eTextKind
==OBJ_OUTLINETEXT
|| eTextKind
==OBJ_TITLETEXT
,
86 "SdrRectObj::SdrRectObj(SdrObjKind) can only be applied to text frames.");
90 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind
, const Rectangle
& rRect
)
91 : SdrTextObj(eNewTextKind
,rRect
),
94 DBG_ASSERT(eTextKind
==OBJ_TEXT
|| eTextKind
==OBJ_TEXTEXT
||
95 eTextKind
==OBJ_OUTLINETEXT
|| eTextKind
==OBJ_TITLETEXT
,
96 "SdrRectObj::SdrRectObj(SdrObjKind,...) can only be applied to text frames.");
100 SdrRectObj::~SdrRectObj()
105 SdrRectObj
& SdrRectObj::operator=(const SdrRectObj
& rCopy
)
107 if ( this == &rCopy
)
110 SdrTextObj::operator=( rCopy
);
115 mpXPoly
= new XPolygon( *rCopy
.mpXPoly
);
122 void SdrRectObj::SetXPolyDirty()
128 XPolygon
SdrRectObj::ImpCalcXPoly(const Rectangle
& rRect1
, long nRad1
) const
130 XPolygon
aXPoly(rRect1
,nRad1
,nRad1
);
131 const sal_uInt16
nPointAnz(aXPoly
.GetPointCount());
132 XPolygon
aNeuPoly(nPointAnz
+1);
133 sal_uInt16 nShift
=nPointAnz
-2;
134 if (nRad1
!=0) nShift
=nPointAnz
-5;
136 for (sal_uInt16 i
=1; i
<nPointAnz
; i
++) {
137 aNeuPoly
[i
]=aXPoly
[j
];
138 aNeuPoly
.SetFlags(i
,aXPoly
.GetFlags(j
));
140 if (j
>=nPointAnz
) j
=1;
142 aNeuPoly
[0]=rRect1
.BottomCenter();
143 aNeuPoly
[nPointAnz
]=aNeuPoly
[0];
146 // these angles always relate to the top left corner of aRect
147 if (aGeo
.nShearWink
!=0) ShearXPoly(aXPoly
,aRect
.TopLeft(),aGeo
.nTan
);
148 if (aGeo
.nDrehWink
!=0) RotateXPoly(aXPoly
,aRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
152 void SdrRectObj::RecalcXPoly()
155 mpXPoly
= new XPolygon(ImpCalcXPoly(aRect
,GetEckenradius()));
158 const XPolygon
& SdrRectObj::GetXPoly() const
162 ((SdrRectObj
*)this)->RecalcXPoly();
168 void SdrRectObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
170 bool bNoTextFrame
=!IsTextFrame();
171 rInfo
.bResizeFreeAllowed
=bNoTextFrame
|| aGeo
.nDrehWink
%9000==0;
172 rInfo
.bResizePropAllowed
=true;
173 rInfo
.bRotateFreeAllowed
=true;
174 rInfo
.bRotate90Allowed
=true;
175 rInfo
.bMirrorFreeAllowed
=bNoTextFrame
;
176 rInfo
.bMirror45Allowed
=bNoTextFrame
;
177 rInfo
.bMirror90Allowed
=bNoTextFrame
;
179 // allow transparency
180 rInfo
.bTransparenceAllowed
= true;
182 // gradient depends on fillstyle
183 XFillStyle eFillStyle
= ((XFillStyleItem
&)(GetObjectItem(XATTR_FILLSTYLE
))).GetValue();
184 rInfo
.bGradientAllowed
= (eFillStyle
== XFILL_GRADIENT
);
186 rInfo
.bShearAllowed
=bNoTextFrame
;
187 rInfo
.bEdgeRadiusAllowed
=true;
189 bool bCanConv
=!HasText() || ImpCanConvTextToCurve();
190 if (bCanConv
&& !bNoTextFrame
&& !HasText()) {
191 bCanConv
=HasFill() || HasLine();
193 rInfo
.bCanConvToPath
=bCanConv
;
194 rInfo
.bCanConvToPoly
=bCanConv
;
195 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
198 sal_uInt16
SdrRectObj::GetObjIdentifier() const
200 if (IsTextFrame()) return sal_uInt16(eTextKind
);
201 else return sal_uInt16(OBJ_RECT
);
204 void SdrRectObj::TakeUnrotatedSnapRect(Rectangle
& rRect
) const
207 if (aGeo
.nShearWink
!=0) {
208 long nDst
=Round((aRect
.Bottom()-aRect
.Top())*aGeo
.nTan
);
209 if (aGeo
.nShearWink
>0) {
210 Point
aRef(rRect
.TopLeft());
212 Point
aTmpPt(rRect
.TopLeft());
213 RotatePoint(aTmpPt
,aRef
,aGeo
.nSin
,aGeo
.nCos
);
214 aTmpPt
-=rRect
.TopLeft();
215 rRect
.Move(aTmpPt
.X(),aTmpPt
.Y());
222 OUString
SdrRectObj::TakeObjNameSingul() const
226 return SdrTextObj::TakeObjNameSingul();
229 OUStringBuffer sName
;
231 sal_uInt16 nResId
=STR_ObjNameSingulRECT
;
232 if (aGeo
.nShearWink
!=0) {
233 nResId
+=4; // parallelogram or, maybe, rhombus
235 if (aRect
.GetWidth()==aRect
.GetHeight()) nResId
+=2; // square
237 if (GetEckenradius()!=0) nResId
+=8; // rounded down
238 sName
.append(ImpGetResStr(nResId
));
240 OUString
aName(GetName());
241 if (!aName
.isEmpty())
249 return sName
.makeStringAndClear();
252 OUString
SdrRectObj::TakeObjNamePlural() const
256 return SdrTextObj::TakeObjNamePlural();
259 sal_uInt16 nResId
=STR_ObjNamePluralRECT
;
261 if (aGeo
.nShearWink
!=0)
263 nResId
+=4; // parallelogram or rhombus
267 if (aRect
.GetWidth()==aRect
.GetHeight())
271 if (GetEckenradius()!=0)
272 nResId
+=8; // rounded down
274 return ImpGetResStr(nResId
);
277 SdrRectObj
* SdrRectObj::Clone() const
279 return CloneHelper
< SdrRectObj
>();
282 basegfx::B2DPolyPolygon
SdrRectObj::TakeXorPoly() const
285 aXPP
.Insert(ImpCalcXPoly(aRect
,GetEckenradius()));
286 return aXPP
.getB2DPolyPolygon();
289 void SdrRectObj::RecalcSnapRect()
291 long nEckRad
=GetEckenradius();
292 if ((aGeo
.nDrehWink
!=0 || aGeo
.nShearWink
!=0) && nEckRad
!=0) {
293 maSnapRect
=GetXPoly().GetBoundRect();
295 SdrTextObj::RecalcSnapRect();
299 void SdrRectObj::NbcSetSnapRect(const Rectangle
& rRect
)
301 SdrTextObj::NbcSetSnapRect(rRect
);
305 void SdrRectObj::NbcSetLogicRect(const Rectangle
& rRect
)
307 SdrTextObj::NbcSetLogicRect(rRect
);
311 sal_uInt32
SdrRectObj::GetHdlCount() const
313 return IsTextFrame() ? 10 : 9;
316 SdrHdl
* SdrRectObj::GetHdl(sal_uInt32 nHdlNum
) const
320 SdrHdlKind eKind
= HDL_MOVE
;
331 OSL_ENSURE(!IsTextEditActive(), "Do not use a ImpTextframeHdl for hilighting text in active text edit, this will collide with EditEngine paints (!)");
332 // hack for calc grid sync to ensure the hatched area
333 // for a textbox is displayed at correct position
334 pH
= new ImpTextframeHdl(aRect
+ GetGridOffset() );
335 pH
->SetObj((SdrObject
*)this);
336 pH
->SetDrehWink(aGeo
.nDrehWink
);
341 long a
= GetEckenradius();
342 long b
= std::max(aRect
.GetWidth(),aRect
.GetHeight())/2; // rounded up, because GetWidth() adds 1
345 aPnt
=aRect
.TopLeft();
350 case 2: aPnt
=aRect
.TopLeft(); eKind
= HDL_UPLFT
; break;
351 case 3: aPnt
=aRect
.TopCenter(); eKind
= HDL_UPPER
; break;
352 case 4: aPnt
=aRect
.TopRight(); eKind
= HDL_UPRGT
; break;
353 case 5: aPnt
=aRect
.LeftCenter(); eKind
= HDL_LEFT
; break;
354 case 6: aPnt
=aRect
.RightCenter(); eKind
= HDL_RIGHT
; break;
355 case 7: aPnt
=aRect
.BottomLeft(); eKind
= HDL_LWLFT
; break;
356 case 8: aPnt
=aRect
.BottomCenter(); eKind
= HDL_LOWER
; break;
357 case 9: aPnt
=aRect
.BottomRight(); eKind
= HDL_LWRGT
; break;
364 ShearPoint(aPnt
,aRect
.TopLeft(),aGeo
.nTan
);
369 RotatePoint(aPnt
,aRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
372 pH
= new SdrHdl(aPnt
,eKind
);
373 pH
->SetObj((SdrObject
*)this);
374 pH
->SetDrehWink(aGeo
.nDrehWink
);
382 bool SdrRectObj::hasSpecialDrag() const
387 bool SdrRectObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
389 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
393 rDrag
.SetEndDragChangesAttributes(true);
398 return SdrTextObj::beginSpecialDrag(rDrag
);
401 bool SdrRectObj::applySpecialDrag(SdrDragStat
& rDrag
)
403 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
407 Point
aPt(rDrag
.GetNow());
410 RotatePoint(aPt
,aRect
.TopLeft(),-aGeo
.nSin
,aGeo
.nCos
);
412 sal_Int32
nRad(aPt
.X() - aRect
.Left());
417 if(nRad
!= GetEckenradius())
419 NbcSetEckenradius(nRad
);
426 return SdrTextObj::applySpecialDrag(rDrag
);
430 OUString
SdrRectObj::getSpecialDragComment(const SdrDragStat
& rDrag
) const
432 const bool bCreateComment(rDrag
.GetView() && this == rDrag
.GetView()->GetCreateObj());
440 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
444 Point
aPt(rDrag
.GetNow());
448 RotatePoint(aPt
, aRect
.TopLeft(), -aGeo
.nSin
, aGeo
.nCos
);
450 sal_Int32
nRad(aPt
.X() - aRect
.Left());
456 ImpTakeDescriptionStr(STR_DragRectEckRad
, aStr
);
457 OUStringBuffer
aBuf(aStr
);
458 aBuf
.appendAscii(" (");
459 aBuf
.append(GetMetrStr(nRad
));
462 return aBuf
.makeStringAndClear();
466 return SdrTextObj::getSpecialDragComment(rDrag
);
473 basegfx::B2DPolyPolygon
SdrRectObj::TakeCreatePoly(const SdrDragStat
& rDrag
) const
476 rDrag
.TakeCreateRect(aRect1
);
479 basegfx::B2DPolyPolygon aRetval
;
480 aRetval
.append(ImpCalcXPoly(aRect1
,GetEckenradius()).getB2DPolygon());
484 Pointer
SdrRectObj::GetCreatePointer() const
486 if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT
);
487 return Pointer(POINTER_DRAW_RECT
);
490 void SdrRectObj::NbcMove(const Size
& rSiz
)
492 SdrTextObj::NbcMove(rSiz
);
496 void SdrRectObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
498 SdrTextObj::NbcResize(rRef
,xFact
,yFact
);
502 void SdrRectObj::NbcRotate(const Point
& rRef
, long nWink
, double sn
, double cs
)
504 SdrTextObj::NbcRotate(rRef
,nWink
,sn
,cs
);
508 void SdrRectObj::NbcShear(const Point
& rRef
, long nWink
, double tn
, bool bVShear
)
510 SdrTextObj::NbcShear(rRef
,nWink
,tn
,bVShear
);
514 void SdrRectObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
516 SdrTextObj::NbcMirror(rRef1
,rRef2
);
520 bool SdrRectObj::DoMacro(const SdrObjMacroHitRec
& rRec
)
522 return SdrTextObj::DoMacro(rRec
);
525 OUString
SdrRectObj::GetMacroPopupComment(const SdrObjMacroHitRec
& rRec
) const
527 return SdrTextObj::GetMacroPopupComment(rRec
);
530 SdrGluePoint
SdrRectObj::GetVertexGluePoint(sal_uInt16 nPosNum
) const
532 sal_Int32 nWdt
= ImpGetLineWdt(); // #i25616#
535 if(!LineIsOutsideGeometry())
543 case 0: aPt
=aRect
.TopCenter(); aPt
.Y()-=nWdt
; break;
544 case 1: aPt
=aRect
.RightCenter(); aPt
.X()+=nWdt
; break;
545 case 2: aPt
=aRect
.BottomCenter(); aPt
.Y()+=nWdt
; break;
546 case 3: aPt
=aRect
.LeftCenter(); aPt
.X()-=nWdt
; break;
548 if (aGeo
.nShearWink
!=0) ShearPoint(aPt
,aRect
.TopLeft(),aGeo
.nTan
);
549 if (aGeo
.nDrehWink
!=0) RotatePoint(aPt
,aRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
550 aPt
-=GetSnapRect().Center();
551 SdrGluePoint
aGP(aPt
);
552 aGP
.SetPercent(false);
556 SdrGluePoint
SdrRectObj::GetCornerGluePoint(sal_uInt16 nPosNum
) const
558 sal_Int32 nWdt
= ImpGetLineWdt(); // #i25616#
561 if(!LineIsOutsideGeometry())
569 case 0: aPt
=aRect
.TopLeft(); aPt
.X()-=nWdt
; aPt
.Y()-=nWdt
; break;
570 case 1: aPt
=aRect
.TopRight(); aPt
.X()+=nWdt
; aPt
.Y()-=nWdt
; break;
571 case 2: aPt
=aRect
.BottomRight(); aPt
.X()+=nWdt
; aPt
.Y()+=nWdt
; break;
572 case 3: aPt
=aRect
.BottomLeft(); aPt
.X()-=nWdt
; aPt
.Y()+=nWdt
; break;
574 if (aGeo
.nShearWink
!=0) ShearPoint(aPt
,aRect
.TopLeft(),aGeo
.nTan
);
575 if (aGeo
.nDrehWink
!=0) RotatePoint(aPt
,aRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
576 aPt
-=GetSnapRect().Center();
577 SdrGluePoint
aGP(aPt
);
578 aGP
.SetPercent(false);
582 SdrObject
* SdrRectObj::DoConvertToPolyObj(bool bBezier
, bool bAddText
) const
584 XPolygon
aXP(ImpCalcXPoly(aRect
,GetEckenradius()));
585 { // TODO: this is only for the moment, until we have the new TakeContour()
587 aXP
[aXP
.GetPointCount()-1]=aXP
[0];
590 basegfx::B2DPolyPolygon
aPolyPolygon(aXP
.getB2DPolygon());
591 aPolyPolygon
.removeDoublePoints();
592 SdrObject
* pRet
= 0L;
594 // small correction: Do not create something when no fill and no line. To
595 // be sure to not damage something with non-text frames, do this only
596 // when used with bAddText==false from other converters
597 if((bAddText
&& !IsTextFrame()) || HasFill() || HasLine())
599 pRet
= ImpConvertMakeObj(aPolyPolygon
, true, bBezier
);
604 pRet
= ImpConvertAddText(pRet
, bBezier
);
610 void SdrRectObj::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
612 SdrTextObj::Notify(rBC
,rHint
);
613 SetXPolyDirty(); // because of the corner radius
616 void SdrRectObj::RestGeoData(const SdrObjGeoData
& rGeo
)
618 SdrTextObj::RestGeoData(rGeo
);
622 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */