1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26
27 #include <svx/svdotext.hxx>
28 #include <svx/svdhdl.hxx>
29 #include <svx/svddrag.hxx>
30 #include <svx/svdview.hxx>
31 #include <svx/svdorect.hxx> // fuer SetXPolyDirty in MovCreate bei SolidDragging
32 #include "svx/svdglob.hxx" // Stringcache
33 #include "svx/svdstr.hrc" // Objektname
34 #include <svx/svdoashp.hxx>
35 #include <tools/bigint.hxx>
36 #include <basegfx/polygon/b2dpolygon.hxx>
37 #include <basegfx/range/b2drange.hxx>
38 #include <basegfx/polygon/b2dpolygontools.hxx>
39
40 ////////////////////////////////////////////////////////////////////////////////////////////////////
41 //
42 // @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@
43 // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@
44 // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@
45 // @@ @@@@ @@@ @@ @@ @@ @@@@@ @@
46 // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@
47 // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@
48 // @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@
49 //
50 // Dragging, Handles, Create
51 //
52 ////////////////////////////////////////////////////////////////////////////////////////////////////
53
GetHdlCount() const54 sal_uInt32 SdrTextObj::GetHdlCount() const
55 {
56 return 8L;
57 }
58
GetHdl(sal_uInt32 nHdlNum) const59 SdrHdl* SdrTextObj::GetHdl(sal_uInt32 nHdlNum) const
60 {
61 SdrHdl* pH=NULL;
62 Point aPnt;
63 SdrHdlKind eKind=HDL_MOVE;
64 switch (nHdlNum) {
65 case 0: aPnt=aRect.TopLeft(); eKind=HDL_UPLFT; break; // Oben links
66 case 1: aPnt=aRect.TopCenter(); eKind=HDL_UPPER; break; // Oben
67 case 2: aPnt=aRect.TopRight(); eKind=HDL_UPRGT; break; // Oben rechts
68 case 3: aPnt=aRect.LeftCenter(); eKind=HDL_LEFT ; break; // Links
69 case 4: aPnt=aRect.RightCenter(); eKind=HDL_RIGHT; break; // Rechts
70 case 5: aPnt=aRect.BottomLeft(); eKind=HDL_LWLFT; break; // Unten links
71 case 6: aPnt=aRect.BottomCenter(); eKind=HDL_LOWER; break; // Unten
72 case 7: aPnt=aRect.BottomRight(); eKind=HDL_LWRGT; break; // Unten rechts
73 }
74 if (aGeo.nShearWink!=0) ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan);
75 if (aGeo.nDrehWink!=0) RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
76 if (eKind!=HDL_MOVE) {
77 pH=new SdrHdl(aPnt,eKind);
78 pH->SetObj((SdrObject*)this);
79 pH->SetDrehWink(aGeo.nDrehWink);
80 }
81 return pH;
82 }
83
84 ////////////////////////////////////////////////////////////////////////////////////////////////////
85
hasSpecialDrag() const86 bool SdrTextObj::hasSpecialDrag() const
87 {
88 return true;
89 }
90
ImpDragCalcRect(const SdrDragStat & rDrag) const91 Rectangle SdrTextObj::ImpDragCalcRect(const SdrDragStat& rDrag) const
92 {
93 Rectangle aTmpRect(aRect);
94 const SdrHdl* pHdl=rDrag.GetHdl();
95 SdrHdlKind eHdl=pHdl==NULL ? HDL_MOVE : pHdl->GetKind();
96 FASTBOOL bEcke=(eHdl==HDL_UPLFT || eHdl==HDL_UPRGT || eHdl==HDL_LWLFT || eHdl==HDL_LWRGT);
97 FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho();
98 FASTBOOL bBigOrtho=bEcke && bOrtho && rDrag.GetView()->IsBigOrtho();
99 Point aPos(rDrag.GetNow());
100 // Unrotate:
101 if (aGeo.nDrehWink!=0) RotatePoint(aPos,aTmpRect.TopLeft(),-aGeo.nSin,aGeo.nCos);
102 // Unshear:
103 if (aGeo.nShearWink!=0) ShearPoint(aPos,aTmpRect.TopLeft(),-aGeo.nTan);
104 //
105 FASTBOOL bLft=(eHdl==HDL_UPLFT || eHdl==HDL_LEFT || eHdl==HDL_LWLFT);
106 FASTBOOL bRgt=(eHdl==HDL_UPRGT || eHdl==HDL_RIGHT || eHdl==HDL_LWRGT);
107 FASTBOOL bTop=(eHdl==HDL_UPRGT || eHdl==HDL_UPPER || eHdl==HDL_UPLFT);
108 FASTBOOL bBtm=(eHdl==HDL_LWRGT || eHdl==HDL_LOWER || eHdl==HDL_LWLFT);
109 if (bLft) aTmpRect.Left() =aPos.X();
110 if (bRgt) aTmpRect.Right() =aPos.X();
111 if (bTop) aTmpRect.Top() =aPos.Y();
112 if (bBtm) aTmpRect.Bottom()=aPos.Y();
113 if (bOrtho) { // Ortho
114 long nWdt0=aRect.Right() -aRect.Left();
115 long nHgt0=aRect.Bottom()-aRect.Top();
116 long nXMul=aTmpRect.Right() -aTmpRect.Left();
117 long nYMul=aTmpRect.Bottom()-aTmpRect.Top();
118 long nXDiv=nWdt0;
119 long nYDiv=nHgt0;
120 FASTBOOL bXNeg=(nXMul<0)!=(nXDiv<0);
121 FASTBOOL bYNeg=(nYMul<0)!=(nYDiv<0);
122 nXMul=Abs(nXMul);
123 nYMul=Abs(nYMul);
124 nXDiv=Abs(nXDiv);
125 nYDiv=Abs(nYDiv);
126 Fraction aXFact(nXMul,nXDiv); // Fractions zum kuerzen
127 Fraction aYFact(nYMul,nYDiv); // und zum vergleichen
128 nXMul=aXFact.GetNumerator();
129 nYMul=aYFact.GetNumerator();
130 nXDiv=aXFact.GetDenominator();
131 nYDiv=aYFact.GetDenominator();
132 if (bEcke) { // Eckpunkthandles
133 FASTBOOL bUseX=(aXFact<aYFact) != bBigOrtho;
134 if (bUseX) {
135 long nNeed=long(BigInt(nHgt0)*BigInt(nXMul)/BigInt(nXDiv));
136 if (bYNeg) nNeed=-nNeed;
137 if (bTop) aTmpRect.Top()=aTmpRect.Bottom()-nNeed;
138 if (bBtm) aTmpRect.Bottom()=aTmpRect.Top()+nNeed;
139 } else {
140 long nNeed=long(BigInt(nWdt0)*BigInt(nYMul)/BigInt(nYDiv));
141 if (bXNeg) nNeed=-nNeed;
142 if (bLft) aTmpRect.Left()=aTmpRect.Right()-nNeed;
143 if (bRgt) aTmpRect.Right()=aTmpRect.Left()+nNeed;
144 }
145 } else { // Scheitelpunkthandles
146 if ((bLft || bRgt) && nXDiv!=0) {
147 long nHgt0b=aRect.Bottom()-aRect.Top();
148 long nNeed=long(BigInt(nHgt0b)*BigInt(nXMul)/BigInt(nXDiv));
149 aTmpRect.Top()-=(nNeed-nHgt0b)/2;
150 aTmpRect.Bottom()=aTmpRect.Top()+nNeed;
151 }
152 if ((bTop || bBtm) && nYDiv!=0) {
153 long nWdt0b=aRect.Right()-aRect.Left();
154 long nNeed=long(BigInt(nWdt0b)*BigInt(nYMul)/BigInt(nYDiv));
155 aTmpRect.Left()-=(nNeed-nWdt0b)/2;
156 aTmpRect.Right()=aTmpRect.Left()+nNeed;
157 }
158 }
159 }
160 if (!ISA(SdrObjCustomShape)) // not justifying for CustomShapes to be able to detect if a shape has to be mirrored
161 ImpJustifyRect(aTmpRect);
162 return aTmpRect;
163 }
164
165 ////////////////////////////////////////////////////////////////////////////////////////////////////
166 // drag
167
applySpecialDrag(SdrDragStat & rDrag)168 bool SdrTextObj::applySpecialDrag(SdrDragStat& rDrag)
169 {
170 Rectangle aNewRect(ImpDragCalcRect(rDrag));
171
172 if(aNewRect.TopLeft() != aRect.TopLeft() && (aGeo.nDrehWink || aGeo.nShearWink))
173 {
174 Point aNewPos(aNewRect.TopLeft());
175
176 if(aGeo.nShearWink)
177 ShearPoint(aNewPos,aRect.TopLeft(),aGeo.nTan);
178
179 if(aGeo.nDrehWink)
180 RotatePoint(aNewPos,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
181
182 aNewRect.SetPos(aNewPos);
183 }
184
185 if(aNewRect != aRect)
186 {
187 NbcSetLogicRect(aNewRect);
188 }
189
190 return true;
191 }
192
getSpecialDragComment(const SdrDragStat &) const193 String SdrTextObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const
194 {
195 XubString aStr;
196 ImpTakeDescriptionStr(STR_DragRectResize,aStr);
197 return aStr;
198 }
199
200 ////////////////////////////////////////////////////////////////////////////////////////////////////
201 // Create
202
BegCreate(SdrDragStat & rStat)203 FASTBOOL SdrTextObj::BegCreate(SdrDragStat& rStat)
204 {
205 rStat.SetOrtho4Possible();
206 Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
207 aRect1.Justify();
208 rStat.SetActionRect(aRect1);
209 aRect = aRect1;
210 return sal_True;
211 }
212
MovCreate(SdrDragStat & rStat)213 FASTBOOL SdrTextObj::MovCreate(SdrDragStat& rStat)
214 {
215 Rectangle aRect1;
216 rStat.TakeCreateRect(aRect1);
217 ImpJustifyRect(aRect1);
218 rStat.SetActionRect(aRect1);
219 aRect=aRect1; // fuer ObjName
220 SetBoundRectDirty();
221 bSnapRectDirty=sal_True;
222 if (HAS_BASE(SdrRectObj,this)) {
223 ((SdrRectObj*)this)->SetXPolyDirty();
224 }
225 return sal_True;
226 }
227
EndCreate(SdrDragStat & rStat,SdrCreateCmd eCmd)228 FASTBOOL SdrTextObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
229 {
230 rStat.TakeCreateRect(aRect);
231 ImpJustifyRect(aRect);
232
233 // #115391#
234 AdaptTextMinSize();
235
236 SetRectsDirty();
237 if (HAS_BASE(SdrRectObj,this)) {
238 ((SdrRectObj*)this)->SetXPolyDirty();
239 }
240 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
241 }
242
BrkCreate(SdrDragStat &)243 void SdrTextObj::BrkCreate(SdrDragStat& /*rStat*/)
244 {
245 }
246
BckCreate(SdrDragStat &)247 FASTBOOL SdrTextObj::BckCreate(SdrDragStat& /*rStat*/)
248 {
249 return sal_True;
250 }
251
TakeCreatePoly(const SdrDragStat & rDrag) const252 basegfx::B2DPolyPolygon SdrTextObj::TakeCreatePoly(const SdrDragStat& rDrag) const
253 {
254 Rectangle aRect1;
255 rDrag.TakeCreateRect(aRect1);
256 aRect1.Justify();
257
258 basegfx::B2DPolyPolygon aRetval;
259 const basegfx::B2DRange aRange(aRect1.Left(), aRect1.Top(), aRect1.Right(), aRect1.Bottom());
260 aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
261 return aRetval;
262 }
263
GetCreatePointer() const264 Pointer SdrTextObj::GetCreatePointer() const
265 {
266 if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT);
267 return Pointer(POINTER_CROSS);
268 }
269
270