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 const tools::Rectangle rRectangle
= getRectangle();
49 case 0: aPnt
= rRectangle
.TopLeft(); eKind
=SdrHdlKind::UpperLeft
; break;
50 case 1: aPnt
= rRectangle
.TopCenter(); eKind
=SdrHdlKind::Upper
; break;
51 case 2: aPnt
= rRectangle
.TopRight(); eKind
=SdrHdlKind::UpperRight
; break;
52 case 3: aPnt
= rRectangle
.LeftCenter(); eKind
=SdrHdlKind::Left
; break;
53 case 4: aPnt
= rRectangle
.RightCenter(); eKind
=SdrHdlKind::Right
; break;
54 case 5: aPnt
= rRectangle
.BottomLeft(); eKind
=SdrHdlKind::LowerLeft
; break;
55 case 6: aPnt
= rRectangle
.BottomCenter(); eKind
=SdrHdlKind::Lower
; break;
56 case 7: aPnt
= rRectangle
.BottomRight(); eKind
=SdrHdlKind::LowerRight
; break;
58 if (maGeo
.m_nShearAngle
)
59 ShearPoint(aPnt
, rRectangle
.TopLeft(), maGeo
.mfTanShearAngle
);
60 if (maGeo
.m_nRotationAngle
)
61 RotatePoint(aPnt
, rRectangle
.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
.m_nRotationAngle
);
65 rHdlList
.AddHdl(std::move(pH
));
69 bool SdrTextObj::hasSpecialDrag() const
74 tools::Rectangle
SdrTextObj::ImpDragCalcRect(const SdrDragStat
& rDrag
) const
76 tools::Rectangle
aTmpRect(getRectangle());
77 const SdrHdl
* pHdl
=rDrag
.GetHdl();
78 SdrHdlKind eHdl
=pHdl
==nullptr ? SdrHdlKind::Move
: pHdl
->GetKind();
79 bool bEcke
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::LowerLeft
|| eHdl
==SdrHdlKind::LowerRight
);
80 bool bOrtho
=rDrag
.GetView()!=nullptr && rDrag
.GetView()->IsOrtho();
81 bool bBigOrtho
=bEcke
&& bOrtho
&& rDrag
.GetView()->IsBigOrtho();
82 Point
aPos(rDrag
.GetNow());
84 if (maGeo
.m_nRotationAngle
) RotatePoint(aPos
,aTmpRect
.TopLeft(),-maGeo
.mfSinRotationAngle
,maGeo
.mfCosRotationAngle
);
86 if (maGeo
.m_nShearAngle
) ShearPoint(aPos
,aTmpRect
.TopLeft(),-maGeo
.mfTanShearAngle
);
88 bool bLft
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::LowerLeft
);
89 bool bRgt
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerRight
);
90 bool bTop
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperLeft
);
91 bool bBtm
=(eHdl
==SdrHdlKind::LowerRight
|| eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerLeft
);
92 if (bLft
) aTmpRect
.SetLeft(aPos
.X() );
93 if (bRgt
) aTmpRect
.SetRight(aPos
.X() );
94 if (bTop
) aTmpRect
.SetTop(aPos
.Y() );
95 if (bBtm
) aTmpRect
.SetBottom(aPos
.Y() );
96 if (bOrtho
) { // Ortho
97 tools::Long nWdt0
=getRectangle().Right() - getRectangle().Left();
98 tools::Long nHgt0
=getRectangle().Bottom() - getRectangle().Top();
99 tools::Long nXMul
=aTmpRect
.Right() -aTmpRect
.Left();
100 tools::Long nYMul
=aTmpRect
.Bottom()-aTmpRect
.Top();
101 tools::Long nXDiv
=nWdt0
;
102 tools::Long nYDiv
=nHgt0
;
103 bool bXNeg
=(nXMul
<0)!=(nXDiv
<0);
104 bool bYNeg
=(nYMul
<0)!=(nYDiv
<0);
105 nXMul
=std::abs(nXMul
);
106 nYMul
=std::abs(nYMul
);
107 nXDiv
=std::abs(nXDiv
);
108 nYDiv
=std::abs(nYDiv
);
109 Fraction
aXFact(nXMul
,nXDiv
); // fractions for canceling
110 Fraction
aYFact(nYMul
,nYDiv
); // and for comparing
111 nXMul
=aXFact
.GetNumerator();
112 nYMul
=aYFact
.GetNumerator();
113 nXDiv
=aXFact
.GetDenominator();
114 nYDiv
=aYFact
.GetDenominator();
115 if (bEcke
) { // corner point handles
116 bool bUseX
=(aXFact
<aYFact
) != bBigOrtho
;
118 tools::Long nNeed
=tools::Long(BigInt(nHgt0
)*BigInt(nXMul
)/BigInt(nXDiv
));
119 if (bYNeg
) nNeed
=-nNeed
;
120 if (bTop
) aTmpRect
.SetTop(aTmpRect
.Bottom()-nNeed
);
121 if (bBtm
) aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
123 tools::Long nNeed
=tools::Long(BigInt(nWdt0
)*BigInt(nYMul
)/BigInt(nYDiv
));
124 if (bXNeg
) nNeed
=-nNeed
;
125 if (bLft
) aTmpRect
.SetLeft(aTmpRect
.Right()-nNeed
);
126 if (bRgt
) aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
128 } else { // apex handles
129 if ((bLft
|| bRgt
) && nXDiv
!=0) {
130 tools::Long nHgt0b
=getRectangle().Bottom() - getRectangle().Top();
131 tools::Long nNeed
=tools::Long(BigInt(nHgt0b
)*BigInt(nXMul
)/BigInt(nXDiv
));
132 aTmpRect
.AdjustTop( -((nNeed
-nHgt0b
)/2) );
133 aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
135 if ((bTop
|| bBtm
) && nYDiv
!=0) {
136 tools::Long nWdt0b
=getRectangle().Right() - getRectangle().Left();
137 tools::Long nNeed
=tools::Long(BigInt(nWdt0b
)*BigInt(nYMul
)/BigInt(nYDiv
));
138 aTmpRect
.AdjustLeft( -((nNeed
-nWdt0b
)/2) );
139 aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
143 if (dynamic_cast<const SdrObjCustomShape
*>(this) == nullptr) // not justifying when in CustomShapes, to be able to detect if a shape has to be mirrored
144 ImpJustifyRect(aTmpRect
);
151 bool SdrTextObj::applySpecialDrag(SdrDragStat
& rDrag
)
153 tools::Rectangle
aNewRect(ImpDragCalcRect(rDrag
));
155 if(aNewRect
.TopLeft() != getRectangle().TopLeft() && (maGeo
.m_nRotationAngle
|| maGeo
.m_nShearAngle
))
157 Point
aNewPos(aNewRect
.TopLeft());
159 if (maGeo
.m_nShearAngle
)
160 ShearPoint(aNewPos
, getRectangle().TopLeft(), maGeo
.mfTanShearAngle
);
162 if (maGeo
.m_nRotationAngle
)
163 RotatePoint(aNewPos
, getRectangle().TopLeft(), maGeo
.mfSinRotationAngle
, maGeo
.mfCosRotationAngle
);
165 aNewRect
.SetPos(aNewPos
);
168 if (aNewRect
!= getRectangle())
170 NbcSetLogicRect(aNewRect
);
176 OUString
SdrTextObj::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
178 return ImpGetDescriptionStr(STR_DragRectResize
);
184 bool SdrTextObj::BegCreate(SdrDragStat
& rStat
)
186 rStat
.SetOrtho4Possible();
187 tools::Rectangle
aRect1(rStat
.GetStart(), rStat
.GetNow());
189 rStat
.SetActionRect(aRect1
);
190 setRectangle(aRect1
);
194 bool SdrTextObj::MovCreate(SdrDragStat
& rStat
)
196 tools::Rectangle aRect1
;
197 rStat
.TakeCreateRect(aRect1
);
198 ImpJustifyRect(aRect1
);
199 rStat
.SetActionRect(aRect1
);
200 setRectangle(aRect1
); // for ObjName
202 m_bSnapRectDirty
=true;
203 if (auto pRectObj
= dynamic_cast<SdrRectObj
*>(this)) {
204 pRectObj
->SetXPolyDirty();
209 bool SdrTextObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
211 tools::Rectangle
aRectangle(getRectangle());
212 rStat
.TakeCreateRect(aRectangle
);
213 ImpJustifyRect(aRectangle
);
214 setRectangle(aRectangle
);
218 SetBoundAndSnapRectsDirty();
219 if (auto pRectObj
= dynamic_cast<SdrRectObj
*>(this)) {
220 pRectObj
->SetXPolyDirty();
222 return (eCmd
==SdrCreateCmd::ForceEnd
|| rStat
.GetPointCount()>=2);
225 void SdrTextObj::BrkCreate(SdrDragStat
& /*rStat*/)
229 bool SdrTextObj::BckCreate(SdrDragStat
& /*rStat*/)
234 basegfx::B2DPolyPolygon
SdrTextObj::TakeCreatePoly(const SdrDragStat
& rDrag
) const
236 tools::Rectangle aRect1
;
237 rDrag
.TakeCreateRect(aRect1
);
240 basegfx::B2DPolyPolygon aRetval
;
241 const basegfx::B2DRange aRange
= vcl::unotools::b2DRectangleFromRectangle(aRect1
);
242 aRetval
.append(basegfx::utils::createPolygonFromRect(aRange
));
246 PointerStyle
SdrTextObj::GetCreatePointer() const
248 if (IsTextFrame()) return PointerStyle::DrawText
;
249 return PointerStyle::Cross
;
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */