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 .
21 #include <svx/svdotext.hxx>
22 #include <svx/svdhdl.hxx>
23 #include <svx/svddrag.hxx>
24 #include <svx/svdview.hxx>
25 #include <svx/svdorect.hxx>
26 #include <svx/strings.hrc>
27 #include <svx/svdoashp.hxx>
28 #include <tools/bigint.hxx>
29 #include <basegfx/polygon/b2dpolygon.hxx>
30 #include <basegfx/range/b2drange.hxx>
31 #include <basegfx/polygon/b2dpolygontools.hxx>
32 #include <vcl/canvastools.hxx>
33 #include <vcl/ptrstyle.hxx>
36 sal_uInt32
SdrTextObj::GetHdlCount() const
41 void SdrTextObj::AddToHdlList(SdrHdlList
& rHdlList
) const
43 for(sal_uInt32 nHdlNum
=0; nHdlNum
<8; ++nHdlNum
)
46 SdrHdlKind eKind
= SdrHdlKind::UpperLeft
;
47 auto aRectangle
= getRectangle();
49 case 0: aPnt
= aRectangle
.TopLeft(); eKind
=SdrHdlKind::UpperLeft
; break;
50 case 1: aPnt
= aRectangle
.TopCenter(); eKind
=SdrHdlKind::Upper
; break;
51 case 2: aPnt
= aRectangle
.TopRight(); eKind
=SdrHdlKind::UpperRight
; break;
52 case 3: aPnt
= aRectangle
.LeftCenter(); eKind
=SdrHdlKind::Left
; break;
53 case 4: aPnt
= aRectangle
.RightCenter(); eKind
=SdrHdlKind::Right
; break;
54 case 5: aPnt
= aRectangle
.BottomLeft(); eKind
=SdrHdlKind::LowerLeft
; break;
55 case 6: aPnt
= aRectangle
.BottomCenter(); eKind
=SdrHdlKind::Lower
; break;
56 case 7: aPnt
= aRectangle
.BottomRight(); eKind
=SdrHdlKind::LowerRight
; break;
58 if (maGeo
.nShearAngle
)
59 ShearPoint(aPnt
, aRectangle
.TopLeft(), maGeo
.mfTanShearAngle
);
60 if (maGeo
.nRotationAngle
)
61 RotatePoint(aPnt
, aRectangle
.TopLeft(), maGeo
.mfSinRotationAngle
, maGeo
.mfCosRotationAngle
);
62 std::unique_ptr
<SdrHdl
> pH(new SdrHdl(aPnt
,eKind
));
63 pH
->SetObj(const_cast<SdrTextObj
*>(this));
64 pH
->SetRotationAngle(maGeo
.nRotationAngle
);
65 rHdlList
.AddHdl(std::move(pH
));
70 bool SdrTextObj::hasSpecialDrag() const
75 tools::Rectangle
SdrTextObj::ImpDragCalcRect(const SdrDragStat
& rDrag
) const
77 tools::Rectangle
aTmpRect(getRectangle());
78 const SdrHdl
* pHdl
=rDrag
.GetHdl();
79 SdrHdlKind eHdl
=pHdl
==nullptr ? SdrHdlKind::Move
: pHdl
->GetKind();
80 bool bEcke
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::LowerLeft
|| eHdl
==SdrHdlKind::LowerRight
);
81 bool bOrtho
=rDrag
.GetView()!=nullptr && rDrag
.GetView()->IsOrtho();
82 bool bBigOrtho
=bEcke
&& bOrtho
&& rDrag
.GetView()->IsBigOrtho();
83 Point
aPos(rDrag
.GetNow());
85 if (maGeo
.nRotationAngle
) RotatePoint(aPos
,aTmpRect
.TopLeft(),-maGeo
.mfSinRotationAngle
,maGeo
.mfCosRotationAngle
);
87 if (maGeo
.nShearAngle
) ShearPoint(aPos
,aTmpRect
.TopLeft(),-maGeo
.mfTanShearAngle
);
89 bool bLft
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::LowerLeft
);
90 bool bRgt
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerRight
);
91 bool bTop
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperLeft
);
92 bool bBtm
=(eHdl
==SdrHdlKind::LowerRight
|| eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerLeft
);
93 if (bLft
) aTmpRect
.SetLeft(aPos
.X() );
94 if (bRgt
) aTmpRect
.SetRight(aPos
.X() );
95 if (bTop
) aTmpRect
.SetTop(aPos
.Y() );
96 if (bBtm
) aTmpRect
.SetBottom(aPos
.Y() );
97 if (bOrtho
) { // Ortho
98 tools::Long nWdt0
=getRectangle().Right() - getRectangle().Left();
99 tools::Long nHgt0
=getRectangle().Bottom() - getRectangle().Top();
100 tools::Long nXMul
=aTmpRect
.Right() -aTmpRect
.Left();
101 tools::Long nYMul
=aTmpRect
.Bottom()-aTmpRect
.Top();
102 tools::Long nXDiv
=nWdt0
;
103 tools::Long nYDiv
=nHgt0
;
104 bool bXNeg
=(nXMul
<0)!=(nXDiv
<0);
105 bool bYNeg
=(nYMul
<0)!=(nYDiv
<0);
106 nXMul
=std::abs(nXMul
);
107 nYMul
=std::abs(nYMul
);
108 nXDiv
=std::abs(nXDiv
);
109 nYDiv
=std::abs(nYDiv
);
110 Fraction
aXFact(nXMul
,nXDiv
); // fractions for canceling
111 Fraction
aYFact(nYMul
,nYDiv
); // and for comparing
112 nXMul
=aXFact
.GetNumerator();
113 nYMul
=aYFact
.GetNumerator();
114 nXDiv
=aXFact
.GetDenominator();
115 nYDiv
=aYFact
.GetDenominator();
116 if (bEcke
) { // corner point handles
117 bool bUseX
=(aXFact
<aYFact
) != bBigOrtho
;
119 tools::Long nNeed
=tools::Long(BigInt(nHgt0
)*BigInt(nXMul
)/BigInt(nXDiv
));
120 if (bYNeg
) nNeed
=-nNeed
;
121 if (bTop
) aTmpRect
.SetTop(aTmpRect
.Bottom()-nNeed
);
122 if (bBtm
) aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
124 tools::Long nNeed
=tools::Long(BigInt(nWdt0
)*BigInt(nYMul
)/BigInt(nYDiv
));
125 if (bXNeg
) nNeed
=-nNeed
;
126 if (bLft
) aTmpRect
.SetLeft(aTmpRect
.Right()-nNeed
);
127 if (bRgt
) aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
129 } else { // apex handles
130 if ((bLft
|| bRgt
) && nXDiv
!=0) {
131 tools::Long nHgt0b
=getRectangle().Bottom() - getRectangle().Top();
132 tools::Long nNeed
=tools::Long(BigInt(nHgt0b
)*BigInt(nXMul
)/BigInt(nXDiv
));
133 aTmpRect
.AdjustTop( -((nNeed
-nHgt0b
)/2) );
134 aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
136 if ((bTop
|| bBtm
) && nYDiv
!=0) {
137 tools::Long nWdt0b
=getRectangle().Right() - getRectangle().Left();
138 tools::Long nNeed
=tools::Long(BigInt(nWdt0b
)*BigInt(nYMul
)/BigInt(nYDiv
));
139 aTmpRect
.AdjustLeft( -((nNeed
-nWdt0b
)/2) );
140 aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
144 if (dynamic_cast<const SdrObjCustomShape
*>(this) == nullptr) // not justifying when in CustomShapes, to be able to detect if a shape has to be mirrored
145 ImpJustifyRect(aTmpRect
);
152 bool SdrTextObj::applySpecialDrag(SdrDragStat
& rDrag
)
154 tools::Rectangle
aNewRect(ImpDragCalcRect(rDrag
));
156 if(aNewRect
.TopLeft() != getRectangle().TopLeft() && (maGeo
.nRotationAngle
|| maGeo
.nShearAngle
))
158 Point
aNewPos(aNewRect
.TopLeft());
160 if (maGeo
.nShearAngle
)
161 ShearPoint(aNewPos
, getRectangle().TopLeft(), maGeo
.mfTanShearAngle
);
163 if (maGeo
.nRotationAngle
)
164 RotatePoint(aNewPos
, getRectangle().TopLeft(), maGeo
.mfSinRotationAngle
, maGeo
.mfCosRotationAngle
);
166 aNewRect
.SetPos(aNewPos
);
169 if (aNewRect
!= getRectangle())
171 NbcSetLogicRect(aNewRect
);
177 OUString
SdrTextObj::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
179 return ImpGetDescriptionStr(STR_DragRectResize
);
185 bool SdrTextObj::BegCreate(SdrDragStat
& rStat
)
187 rStat
.SetOrtho4Possible();
188 tools::Rectangle
aRect1(rStat
.GetStart(), rStat
.GetNow());
190 rStat
.SetActionRect(aRect1
);
191 setRectangle(aRect1
);
195 bool SdrTextObj::MovCreate(SdrDragStat
& rStat
)
197 tools::Rectangle aRect1
;
198 rStat
.TakeCreateRect(aRect1
);
199 ImpJustifyRect(aRect1
);
200 rStat
.SetActionRect(aRect1
);
201 setRectangle(aRect1
); // for ObjName
203 m_bSnapRectDirty
=true;
204 if (auto pRectObj
= dynamic_cast<SdrRectObj
*>(this)) {
205 pRectObj
->SetXPolyDirty();
210 bool SdrTextObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
212 tools::Rectangle
aRectangle(getRectangle());
213 rStat
.TakeCreateRect(aRectangle
);
214 ImpJustifyRect(aRectangle
);
215 setRectangle(aRectangle
);
219 SetBoundAndSnapRectsDirty();
220 if (auto pRectObj
= dynamic_cast<SdrRectObj
*>(this)) {
221 pRectObj
->SetXPolyDirty();
223 return (eCmd
==SdrCreateCmd::ForceEnd
|| rStat
.GetPointCount()>=2);
226 void SdrTextObj::BrkCreate(SdrDragStat
& /*rStat*/)
230 bool SdrTextObj::BckCreate(SdrDragStat
& /*rStat*/)
235 basegfx::B2DPolyPolygon
SdrTextObj::TakeCreatePoly(const SdrDragStat
& rDrag
) const
237 tools::Rectangle aRect1
;
238 rDrag
.TakeCreateRect(aRect1
);
241 basegfx::B2DPolyPolygon aRetval
;
242 const basegfx::B2DRange aRange
= vcl::unotools::b2DRectangleFromRectangle(aRect1
);
243 aRetval
.append(basegfx::utils::createPolygonFromRect(aRange
));
247 PointerStyle
SdrTextObj::GetCreatePointer() const
249 if (IsTextFrame()) return PointerStyle::DrawText
;
250 return PointerStyle::Cross
;
253 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */