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 <sdr/properties/rectangleproperties.hxx>
43 #include <svx/sdr/contact/viewcontactofsdrrectobj.hxx>
44 #include <basegfx/polygon/b2dpolygon.hxx>
45 #include <basegfx/polygon/b2dpolygontools.hxx>
47 using namespace com::sun::star
;
49 // BaseProperties section
51 sdr::properties::BaseProperties
* SdrRectObj::CreateObjectSpecificProperties()
53 return new sdr::properties::RectangleProperties(*this);
57 // DrawContact section
59 sdr::contact::ViewContact
* SdrRectObj::CreateObjectSpecificViewContact()
61 return new sdr::contact::ViewContactOfSdrRectObj(*this);
66 TYPEINIT1(SdrRectObj
,SdrTextObj
);
68 SdrRectObj::SdrRectObj()
74 SdrRectObj::SdrRectObj(const Rectangle
& rRect
)
81 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind
)
82 : SdrTextObj(eNewTextKind
),
85 DBG_ASSERT(eTextKind
==OBJ_TEXT
|| eTextKind
==OBJ_TEXTEXT
||
86 eTextKind
==OBJ_OUTLINETEXT
|| eTextKind
==OBJ_TITLETEXT
,
87 "SdrRectObj::SdrRectObj(SdrObjKind) can only be applied to text frames.");
91 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind
, const Rectangle
& rRect
)
92 : SdrTextObj(eNewTextKind
,rRect
),
95 DBG_ASSERT(eTextKind
==OBJ_TEXT
|| eTextKind
==OBJ_TEXTEXT
||
96 eTextKind
==OBJ_OUTLINETEXT
|| eTextKind
==OBJ_TITLETEXT
,
97 "SdrRectObj::SdrRectObj(SdrObjKind,...) can only be applied to text frames.");
101 SdrRectObj::~SdrRectObj()
106 SdrRectObj
& SdrRectObj::operator=(const SdrRectObj
& rCopy
)
108 if ( this == &rCopy
)
111 SdrTextObj::operator=( rCopy
);
116 mpXPoly
= new XPolygon( *rCopy
.mpXPoly
);
123 void SdrRectObj::SetXPolyDirty()
129 XPolygon
SdrRectObj::ImpCalcXPoly(const Rectangle
& rRect1
, long nRad1
) const
131 XPolygon
aXPoly(rRect1
,nRad1
,nRad1
);
132 const sal_uInt16
nPointAnz(aXPoly
.GetPointCount());
133 XPolygon
aNeuPoly(nPointAnz
+1);
134 sal_uInt16 nShift
=nPointAnz
-2;
135 if (nRad1
!=0) nShift
=nPointAnz
-5;
137 for (sal_uInt16 i
=1; i
<nPointAnz
; i
++) {
138 aNeuPoly
[i
]=aXPoly
[j
];
139 aNeuPoly
.SetFlags(i
,aXPoly
.GetFlags(j
));
141 if (j
>=nPointAnz
) j
=1;
143 aNeuPoly
[0]=rRect1
.BottomCenter();
144 aNeuPoly
[nPointAnz
]=aNeuPoly
[0];
147 // these angles always relate to the top left corner of aRect
148 if (aGeo
.nShearAngle
!=0) ShearXPoly(aXPoly
,maRect
.TopLeft(),aGeo
.nTan
);
149 if (aGeo
.nRotationAngle
!=0) RotateXPoly(aXPoly
,maRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
153 void SdrRectObj::RecalcXPoly()
156 mpXPoly
= new XPolygon(ImpCalcXPoly(maRect
,GetEckenradius()));
159 const XPolygon
& SdrRectObj::GetXPoly() const
163 const_cast<SdrRectObj
*>(this)->RecalcXPoly();
169 void SdrRectObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
171 bool bNoTextFrame
=!IsTextFrame();
172 rInfo
.bResizeFreeAllowed
=bNoTextFrame
|| aGeo
.nRotationAngle
%9000==0;
173 rInfo
.bResizePropAllowed
=true;
174 rInfo
.bRotateFreeAllowed
=true;
175 rInfo
.bRotate90Allowed
=true;
176 rInfo
.bMirrorFreeAllowed
=bNoTextFrame
;
177 rInfo
.bMirror45Allowed
=bNoTextFrame
;
178 rInfo
.bMirror90Allowed
=bNoTextFrame
;
180 // allow transparency
181 rInfo
.bTransparenceAllowed
= true;
183 // gradient depends on fillstyle
184 drawing::FillStyle eFillStyle
= static_cast<const XFillStyleItem
&>(GetObjectItem(XATTR_FILLSTYLE
)).GetValue();
185 rInfo
.bGradientAllowed
= (eFillStyle
== drawing::FillStyle_GRADIENT
);
187 rInfo
.bShearAllowed
=bNoTextFrame
;
188 rInfo
.bEdgeRadiusAllowed
=true;
190 bool bCanConv
=!HasText() || ImpCanConvTextToCurve();
191 if (bCanConv
&& !bNoTextFrame
&& !HasText()) {
192 bCanConv
=HasFill() || HasLine();
194 rInfo
.bCanConvToPath
=bCanConv
;
195 rInfo
.bCanConvToPoly
=bCanConv
;
196 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
199 sal_uInt16
SdrRectObj::GetObjIdentifier() const
201 if (IsTextFrame()) return sal_uInt16(eTextKind
);
202 else return sal_uInt16(OBJ_RECT
);
205 void SdrRectObj::TakeUnrotatedSnapRect(Rectangle
& rRect
) const
208 if (aGeo
.nShearAngle
!=0)
210 long nDst
=Round((maRect
.Bottom()-maRect
.Top())*aGeo
.nTan
);
211 if (aGeo
.nShearAngle
>0)
213 Point
aRef(rRect
.TopLeft());
215 Point
aTmpPt(rRect
.TopLeft());
216 RotatePoint(aTmpPt
,aRef
,aGeo
.nSin
,aGeo
.nCos
);
217 aTmpPt
-=rRect
.TopLeft();
218 rRect
.Move(aTmpPt
.X(),aTmpPt
.Y());
227 OUString
SdrRectObj::TakeObjNameSingul() const
231 return SdrTextObj::TakeObjNameSingul();
234 OUStringBuffer sName
;
236 sal_uInt16 nResId
=STR_ObjNameSingulRECT
;
237 if (aGeo
.nShearAngle
!=0) {
238 nResId
+=4; // parallelogram or, maybe, rhombus
240 if (maRect
.GetWidth() == maRect
.GetHeight()) nResId
+=2; // square
242 if (GetEckenradius()!=0) nResId
+=8; // rounded down
243 sName
.append(ImpGetResStr(nResId
));
245 OUString
aName(GetName());
246 if (!aName
.isEmpty())
254 return sName
.makeStringAndClear();
257 OUString
SdrRectObj::TakeObjNamePlural() const
261 return SdrTextObj::TakeObjNamePlural();
264 sal_uInt16 nResId
=STR_ObjNamePluralRECT
;
266 if (aGeo
.nShearAngle
!=0)
268 nResId
+=4; // parallelogram or rhombus
272 if (maRect
.GetWidth() == maRect
.GetHeight())
276 if (GetEckenradius()!=0)
277 nResId
+=8; // rounded down
279 return ImpGetResStr(nResId
);
282 SdrRectObj
* SdrRectObj::Clone() const
284 return CloneHelper
< SdrRectObj
>();
287 basegfx::B2DPolyPolygon
SdrRectObj::TakeXorPoly() const
290 aXPP
.Insert(ImpCalcXPoly(maRect
,GetEckenradius()));
291 return aXPP
.getB2DPolyPolygon();
294 void SdrRectObj::RecalcSnapRect()
296 long nEckRad
=GetEckenradius();
297 if ((aGeo
.nRotationAngle
!=0 || aGeo
.nShearAngle
!=0) && nEckRad
!=0) {
298 maSnapRect
=GetXPoly().GetBoundRect();
300 SdrTextObj::RecalcSnapRect();
304 void SdrRectObj::NbcSetSnapRect(const Rectangle
& rRect
)
306 SdrTextObj::NbcSetSnapRect(rRect
);
310 void SdrRectObj::NbcSetLogicRect(const Rectangle
& rRect
)
312 SdrTextObj::NbcSetLogicRect(rRect
);
316 sal_uInt32
SdrRectObj::GetHdlCount() const
318 return IsTextFrame() ? 10 : 9;
321 SdrHdl
* SdrRectObj::GetHdl(sal_uInt32 nHdlNum
) const
325 SdrHdlKind eKind
= HDL_MOVE
;
336 OSL_ENSURE(!IsTextEditActive(), "Do not use a ImpTextframeHdl for hilighting text in active text edit, this will collide with EditEngine paints (!)");
337 // hack for calc grid sync to ensure the hatched area
338 // for a textbox is displayed at correct position
339 pH
= new ImpTextframeHdl(maRect
+ GetGridOffset() );
340 pH
->SetObj((SdrObject
*)this);
341 pH
->SetRotationAngle(aGeo
.nRotationAngle
);
346 long a
= GetEckenradius();
347 long b
= std::max(maRect
.GetWidth(),maRect
.GetHeight())/2; // rounded up, because GetWidth() adds 1
350 aPnt
=maRect
.TopLeft();
355 case 2: aPnt
=maRect
.TopLeft(); eKind
= HDL_UPLFT
; break;
356 case 3: aPnt
=maRect
.TopCenter(); eKind
= HDL_UPPER
; break;
357 case 4: aPnt
=maRect
.TopRight(); eKind
= HDL_UPRGT
; break;
358 case 5: aPnt
=maRect
.LeftCenter(); eKind
= HDL_LEFT
; break;
359 case 6: aPnt
=maRect
.RightCenter(); eKind
= HDL_RIGHT
; break;
360 case 7: aPnt
=maRect
.BottomLeft(); eKind
= HDL_LWLFT
; break;
361 case 8: aPnt
=maRect
.BottomCenter(); eKind
= HDL_LOWER
; break;
362 case 9: aPnt
=maRect
.BottomRight(); eKind
= HDL_LWRGT
; break;
369 ShearPoint(aPnt
,maRect
.TopLeft(),aGeo
.nTan
);
372 if(aGeo
.nRotationAngle
)
374 RotatePoint(aPnt
,maRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
377 pH
= new SdrHdl(aPnt
,eKind
);
378 pH
->SetObj((SdrObject
*)this);
379 pH
->SetRotationAngle(aGeo
.nRotationAngle
);
387 bool SdrRectObj::hasSpecialDrag() const
392 bool SdrRectObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
394 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
398 rDrag
.SetEndDragChangesAttributes(true);
403 return SdrTextObj::beginSpecialDrag(rDrag
);
406 bool SdrRectObj::applySpecialDrag(SdrDragStat
& rDrag
)
408 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
412 Point
aPt(rDrag
.GetNow());
414 if(aGeo
.nRotationAngle
)
415 RotatePoint(aPt
,maRect
.TopLeft(),-aGeo
.nSin
,aGeo
.nCos
);
417 sal_Int32
nRad(aPt
.X() - maRect
.Left());
422 if(nRad
!= GetEckenradius())
424 NbcSetEckenradius(nRad
);
431 return SdrTextObj::applySpecialDrag(rDrag
);
435 OUString
SdrRectObj::getSpecialDragComment(const SdrDragStat
& rDrag
) const
437 const bool bCreateComment(rDrag
.GetView() && this == rDrag
.GetView()->GetCreateObj());
445 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
449 Point
aPt(rDrag
.GetNow());
452 if(aGeo
.nRotationAngle
)
453 RotatePoint(aPt
, maRect
.TopLeft(), -aGeo
.nSin
, aGeo
.nCos
);
455 sal_Int32
nRad(aPt
.X() - maRect
.Left());
461 ImpTakeDescriptionStr(STR_DragRectEckRad
, aStr
);
462 OUStringBuffer
aBuf(aStr
);
463 aBuf
.appendAscii(" (");
464 aBuf
.append(GetMetrStr(nRad
));
467 return aBuf
.makeStringAndClear();
471 return SdrTextObj::getSpecialDragComment(rDrag
);
478 basegfx::B2DPolyPolygon
SdrRectObj::TakeCreatePoly(const SdrDragStat
& rDrag
) const
481 rDrag
.TakeCreateRect(aRect1
);
484 basegfx::B2DPolyPolygon aRetval
;
485 aRetval
.append(ImpCalcXPoly(aRect1
,GetEckenradius()).getB2DPolygon());
489 Pointer
SdrRectObj::GetCreatePointer() const
491 if (IsTextFrame()) return Pointer(PointerStyle::DrawText
);
492 return Pointer(PointerStyle::DrawRect
);
495 void SdrRectObj::NbcMove(const Size
& rSiz
)
497 SdrTextObj::NbcMove(rSiz
);
501 void SdrRectObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
503 SdrTextObj::NbcResize(rRef
,xFact
,yFact
);
507 void SdrRectObj::NbcRotate(const Point
& rRef
, long nAngle
, double sn
, double cs
)
509 SdrTextObj::NbcRotate(rRef
,nAngle
,sn
,cs
);
513 void SdrRectObj::NbcShear(const Point
& rRef
, long nAngle
, double tn
, bool bVShear
)
515 SdrTextObj::NbcShear(rRef
,nAngle
,tn
,bVShear
);
519 void SdrRectObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
521 SdrTextObj::NbcMirror(rRef1
,rRef2
);
525 bool SdrRectObj::DoMacro(const SdrObjMacroHitRec
& rRec
)
527 return SdrTextObj::DoMacro(rRec
);
530 OUString
SdrRectObj::GetMacroPopupComment(const SdrObjMacroHitRec
& rRec
) const
532 return SdrTextObj::GetMacroPopupComment(rRec
);
535 SdrGluePoint
SdrRectObj::GetVertexGluePoint(sal_uInt16 nPosNum
) const
537 sal_Int32 nWdt
= ImpGetLineWdt(); // #i25616#
540 if(!LineIsOutsideGeometry())
548 case 0: aPt
=maRect
.TopCenter(); aPt
.Y()-=nWdt
; break;
549 case 1: aPt
=maRect
.RightCenter(); aPt
.X()+=nWdt
; break;
550 case 2: aPt
=maRect
.BottomCenter(); aPt
.Y()+=nWdt
; break;
551 case 3: aPt
=maRect
.LeftCenter(); aPt
.X()-=nWdt
; break;
553 if (aGeo
.nShearAngle
!=0) ShearPoint(aPt
,maRect
.TopLeft(),aGeo
.nTan
);
554 if (aGeo
.nRotationAngle
!=0) RotatePoint(aPt
,maRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
555 aPt
-=GetSnapRect().Center();
556 SdrGluePoint
aGP(aPt
);
557 aGP
.SetPercent(false);
561 SdrGluePoint
SdrRectObj::GetCornerGluePoint(sal_uInt16 nPosNum
) const
563 sal_Int32 nWdt
= ImpGetLineWdt(); // #i25616#
566 if(!LineIsOutsideGeometry())
574 case 0: aPt
=maRect
.TopLeft(); aPt
.X()-=nWdt
; aPt
.Y()-=nWdt
; break;
575 case 1: aPt
=maRect
.TopRight(); aPt
.X()+=nWdt
; aPt
.Y()-=nWdt
; break;
576 case 2: aPt
=maRect
.BottomRight(); aPt
.X()+=nWdt
; aPt
.Y()+=nWdt
; break;
577 case 3: aPt
=maRect
.BottomLeft(); aPt
.X()-=nWdt
; aPt
.Y()+=nWdt
; break;
579 if (aGeo
.nShearAngle
!=0) ShearPoint(aPt
,maRect
.TopLeft(),aGeo
.nTan
);
580 if (aGeo
.nRotationAngle
!=0) RotatePoint(aPt
,maRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
581 aPt
-=GetSnapRect().Center();
582 SdrGluePoint
aGP(aPt
);
583 aGP
.SetPercent(false);
587 SdrObject
* SdrRectObj::DoConvertToPolyObj(bool bBezier
, bool bAddText
) const
589 XPolygon
aXP(ImpCalcXPoly(maRect
,GetEckenradius()));
590 { // TODO: this is only for the moment, until we have the new TakeContour()
592 aXP
[aXP
.GetPointCount()-1]=aXP
[0];
595 basegfx::B2DPolyPolygon
aPolyPolygon(aXP
.getB2DPolygon());
596 aPolyPolygon
.removeDoublePoints();
597 SdrObject
* pRet
= 0L;
599 // small correction: Do not create something when no fill and no line. To
600 // be sure to not damage something with non-text frames, do this only
601 // when used with bAddText==false from other converters
602 if((bAddText
&& !IsTextFrame()) || HasFill() || HasLine())
604 pRet
= ImpConvertMakeObj(aPolyPolygon
, true, bBezier
);
609 pRet
= ImpConvertAddText(pRet
, bBezier
);
615 void SdrRectObj::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
617 SdrTextObj::Notify(rBC
,rHint
);
618 SetXPolyDirty(); // because of the corner radius
621 void SdrRectObj::RestGeoData(const SdrObjGeoData
& rGeo
)
623 SdrTextObj::RestGeoData(rGeo
);
627 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */