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> // for Import of SdrFileVersion 2
33 #include <svx/svdpagv.hxx> // for
34 #include <svx/svdview.hxx> // the
35 #include <svx/svdundo.hxx> // macro example
36 #include <svx/svdopath.hxx>
37 #include "svx/svdglob.hxx" // Stringcache
38 #include "svx/svdstr.hrc" // the object's name
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>
47 //////////////////////////////////////////////////////////////////////////////
48 // BaseProperties section
50 sdr::properties::BaseProperties
* SdrRectObj::CreateObjectSpecificProperties()
52 return new sdr::properties::RectangleProperties(*this);
55 //////////////////////////////////////////////////////////////////////////////
56 // DrawContact section
58 sdr::contact::ViewContact
* SdrRectObj::CreateObjectSpecificViewContact()
60 return new sdr::contact::ViewContactOfSdrRectObj(*this);
63 //////////////////////////////////////////////////////////////////////////////
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
=sal_True
;
173 rInfo
.bRotateFreeAllowed
=sal_True
;
174 rInfo
.bRotate90Allowed
=sal_True
;
175 rInfo
.bMirrorFreeAllowed
=bNoTextFrame
;
176 rInfo
.bMirror45Allowed
=bNoTextFrame
;
177 rInfo
.bMirror90Allowed
=bNoTextFrame
;
179 // allow transparency
180 rInfo
.bTransparenceAllowed
= sal_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
=sal_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 void SdrRectObj::TakeObjNameSingul(XubString
& rName
) const
226 SdrTextObj::TakeObjNameSingul(rName
);
230 sal_uInt16 nResId
=STR_ObjNameSingulRECT
;
231 if (aGeo
.nShearWink
!=0) {
232 nResId
+=4; // parallelogram or, maybe, rhombus
234 if (aRect
.GetWidth()==aRect
.GetHeight()) nResId
+=2; // square
236 if (GetEckenradius()!=0) nResId
+=8; // rounded down
237 rName
=ImpGetResStr(nResId
);
239 String
aName( GetName() );
242 rName
+= sal_Unicode(' ');
243 rName
+= sal_Unicode('\'');
245 rName
+= sal_Unicode('\'');
250 void SdrRectObj::TakeObjNamePlural(XubString
& rName
) const
252 if (IsTextFrame()) SdrTextObj::TakeObjNamePlural(rName
);
254 sal_uInt16 nResId
=STR_ObjNamePluralRECT
;
255 if (aGeo
.nShearWink
!=0) {
256 nResId
+=4; // parallelogram or rhombus
258 if (aRect
.GetWidth()==aRect
.GetHeight()) nResId
+=2; // square
260 if (GetEckenradius()!=0) nResId
+=8; // rounded down
261 rName
=ImpGetResStr(nResId
);
265 SdrRectObj
* SdrRectObj::Clone() const
267 return CloneHelper
< SdrRectObj
>();
270 basegfx::B2DPolyPolygon
SdrRectObj::TakeXorPoly() const
273 aXPP
.Insert(ImpCalcXPoly(aRect
,GetEckenradius()));
274 return aXPP
.getB2DPolyPolygon();
277 void SdrRectObj::RecalcSnapRect()
279 long nEckRad
=GetEckenradius();
280 if ((aGeo
.nDrehWink
!=0 || aGeo
.nShearWink
!=0) && nEckRad
!=0) {
281 maSnapRect
=GetXPoly().GetBoundRect();
283 SdrTextObj::RecalcSnapRect();
287 void SdrRectObj::NbcSetSnapRect(const Rectangle
& rRect
)
289 SdrTextObj::NbcSetSnapRect(rRect
);
293 void SdrRectObj::NbcSetLogicRect(const Rectangle
& rRect
)
295 SdrTextObj::NbcSetLogicRect(rRect
);
299 sal_uInt32
SdrRectObj::GetHdlCount() const
301 return IsTextFrame() ? 10 : 9;
304 SdrHdl
* SdrRectObj::GetHdl(sal_uInt32 nHdlNum
) const
308 SdrHdlKind eKind
= HDL_MOVE
;
319 OSL_ENSURE(!IsTextEditActive(), "Do not use a ImpTextframeHdl for hilighting text in active text edit, this will collide with EditEngine paints (!)");
320 // hack for calc grid sync to ensure the hatched area
321 // for a textbox is displayed at correct position
322 pH
= new ImpTextframeHdl(aRect
+ GetGridOffset() );
323 pH
->SetObj((SdrObject
*)this);
324 pH
->SetDrehWink(aGeo
.nDrehWink
);
329 long a
= GetEckenradius();
330 long b
= std::max(aRect
.GetWidth(),aRect
.GetHeight())/2; // rounded up, because GetWidth() adds 1
333 aPnt
=aRect
.TopLeft();
338 case 2: aPnt
=aRect
.TopLeft(); eKind
= HDL_UPLFT
; break;
339 case 3: aPnt
=aRect
.TopCenter(); eKind
= HDL_UPPER
; break;
340 case 4: aPnt
=aRect
.TopRight(); eKind
= HDL_UPRGT
; break;
341 case 5: aPnt
=aRect
.LeftCenter(); eKind
= HDL_LEFT
; break;
342 case 6: aPnt
=aRect
.RightCenter(); eKind
= HDL_RIGHT
; break;
343 case 7: aPnt
=aRect
.BottomLeft(); eKind
= HDL_LWLFT
; break;
344 case 8: aPnt
=aRect
.BottomCenter(); eKind
= HDL_LOWER
; break;
345 case 9: aPnt
=aRect
.BottomRight(); eKind
= HDL_LWRGT
; break;
352 ShearPoint(aPnt
,aRect
.TopLeft(),aGeo
.nTan
);
357 RotatePoint(aPnt
,aRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
360 pH
= new SdrHdl(aPnt
,eKind
);
361 pH
->SetObj((SdrObject
*)this);
362 pH
->SetDrehWink(aGeo
.nDrehWink
);
368 ////////////////////////////////////////////////////////////////////////////////////////////////////
370 bool SdrRectObj::hasSpecialDrag() const
375 bool SdrRectObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
377 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
381 rDrag
.SetEndDragChangesAttributes(true);
386 return SdrTextObj::beginSpecialDrag(rDrag
);
389 bool SdrRectObj::applySpecialDrag(SdrDragStat
& rDrag
)
391 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
395 Point
aPt(rDrag
.GetNow());
398 RotatePoint(aPt
,aRect
.TopLeft(),-aGeo
.nSin
,aGeo
.nCos
);
400 sal_Int32
nRad(aPt
.X() - aRect
.Left());
405 if(nRad
!= GetEckenradius())
407 NbcSetEckenradius(nRad
);
414 return SdrTextObj::applySpecialDrag(rDrag
);
418 String
SdrRectObj::getSpecialDragComment(const SdrDragStat
& rDrag
) const
420 const bool bCreateComment(rDrag
.GetView() && this == rDrag
.GetView()->GetCreateObj());
428 const bool bRad(rDrag
.GetHdl() && HDL_CIRC
== rDrag
.GetHdl()->GetKind());
432 Point
aPt(rDrag
.GetNow());
436 RotatePoint(aPt
, aRect
.TopLeft(), -aGeo
.nSin
, aGeo
.nCos
);
438 sal_Int32
nRad(aPt
.X() - aRect
.Left());
444 ImpTakeDescriptionStr(STR_DragRectEckRad
, aStr
);
445 OUStringBuffer
aBuf(aStr
);
446 aBuf
.appendAscii(" (");
447 aBuf
.append(GetMetrStr(nRad
));
448 aBuf
.append(sal_Unicode(')'));
450 return aBuf
.makeStringAndClear();
454 return SdrTextObj::getSpecialDragComment(rDrag
);
459 ////////////////////////////////////////////////////////////////////////////////////////////////////
461 basegfx::B2DPolyPolygon
SdrRectObj::TakeCreatePoly(const SdrDragStat
& rDrag
) const
464 rDrag
.TakeCreateRect(aRect1
);
467 basegfx::B2DPolyPolygon aRetval
;
468 aRetval
.append(ImpCalcXPoly(aRect1
,GetEckenradius()).getB2DPolygon());
472 Pointer
SdrRectObj::GetCreatePointer() const
474 if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT
);
475 return Pointer(POINTER_DRAW_RECT
);
478 void SdrRectObj::NbcMove(const Size
& rSiz
)
480 SdrTextObj::NbcMove(rSiz
);
484 void SdrRectObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
486 SdrTextObj::NbcResize(rRef
,xFact
,yFact
);
490 void SdrRectObj::NbcRotate(const Point
& rRef
, long nWink
, double sn
, double cs
)
492 SdrTextObj::NbcRotate(rRef
,nWink
,sn
,cs
);
496 void SdrRectObj::NbcShear(const Point
& rRef
, long nWink
, double tn
, bool bVShear
)
498 SdrTextObj::NbcShear(rRef
,nWink
,tn
,bVShear
);
502 void SdrRectObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
504 SdrTextObj::NbcMirror(rRef1
,rRef2
);
508 bool SdrRectObj::DoMacro(const SdrObjMacroHitRec
& rRec
)
510 return SdrTextObj::DoMacro(rRec
);
513 OUString
SdrRectObj::GetMacroPopupComment(const SdrObjMacroHitRec
& rRec
) const
515 return SdrTextObj::GetMacroPopupComment(rRec
);
518 SdrGluePoint
SdrRectObj::GetVertexGluePoint(sal_uInt16 nPosNum
) const
520 sal_Int32 nWdt
= ImpGetLineWdt(); // #i25616#
523 if(!LineIsOutsideGeometry())
531 case 0: aPt
=aRect
.TopCenter(); aPt
.Y()-=nWdt
; break;
532 case 1: aPt
=aRect
.RightCenter(); aPt
.X()+=nWdt
; break;
533 case 2: aPt
=aRect
.BottomCenter(); aPt
.Y()+=nWdt
; break;
534 case 3: aPt
=aRect
.LeftCenter(); aPt
.X()-=nWdt
; break;
536 if (aGeo
.nShearWink
!=0) ShearPoint(aPt
,aRect
.TopLeft(),aGeo
.nTan
);
537 if (aGeo
.nDrehWink
!=0) RotatePoint(aPt
,aRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
538 aPt
-=GetSnapRect().Center();
539 SdrGluePoint
aGP(aPt
);
540 aGP
.SetPercent(sal_False
);
544 SdrGluePoint
SdrRectObj::GetCornerGluePoint(sal_uInt16 nPosNum
) const
546 sal_Int32 nWdt
= ImpGetLineWdt(); // #i25616#
549 if(!LineIsOutsideGeometry())
557 case 0: aPt
=aRect
.TopLeft(); aPt
.X()-=nWdt
; aPt
.Y()-=nWdt
; break;
558 case 1: aPt
=aRect
.TopRight(); aPt
.X()+=nWdt
; aPt
.Y()-=nWdt
; break;
559 case 2: aPt
=aRect
.BottomRight(); aPt
.X()+=nWdt
; aPt
.Y()+=nWdt
; break;
560 case 3: aPt
=aRect
.BottomLeft(); aPt
.X()-=nWdt
; aPt
.Y()+=nWdt
; break;
562 if (aGeo
.nShearWink
!=0) ShearPoint(aPt
,aRect
.TopLeft(),aGeo
.nTan
);
563 if (aGeo
.nDrehWink
!=0) RotatePoint(aPt
,aRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
564 aPt
-=GetSnapRect().Center();
565 SdrGluePoint
aGP(aPt
);
566 aGP
.SetPercent(sal_False
);
570 SdrObject
* SdrRectObj::DoConvertToPolyObj(sal_Bool bBezier
, bool bAddText
) const
572 XPolygon
aXP(ImpCalcXPoly(aRect
,GetEckenradius()));
573 { // TODO: this is only for the moment, until we have the new TakeContour()
575 aXP
[aXP
.GetPointCount()-1]=aXP
[0];
578 basegfx::B2DPolyPolygon
aPolyPolygon(aXP
.getB2DPolygon());
579 aPolyPolygon
.removeDoublePoints();
580 SdrObject
* pRet
= 0L;
582 // small correction: Do not create something when no fill and no line. To
583 // be sure to not damage something with non-text frames, do this only
584 // when used with bAddText==false from other converters
585 if((bAddText
&& !IsTextFrame()) || HasFill() || HasLine())
587 pRet
= ImpConvertMakeObj(aPolyPolygon
, sal_True
, bBezier
);
592 pRet
= ImpConvertAddText(pRet
, bBezier
);
598 void SdrRectObj::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
600 SdrTextObj::Notify(rBC
,rHint
);
601 SetXPolyDirty(); // because of the corner radius
604 void SdrRectObj::RestGeoData(const SdrObjGeoData
& rGeo
)
606 SdrTextObj::RestGeoData(rGeo
);
610 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */