/src/libreoffice/svx/source/svdraw/svdomeas.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <svx/dialmgr.hxx> |
21 | | #include <svx/strings.hrc> |
22 | | |
23 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
24 | | #include <basegfx/matrix/b2dhommatrixtools.hxx> |
25 | | #include <basegfx/point/b2dpoint.hxx> |
26 | | #include <basegfx/polygon/b2dpolygon.hxx> |
27 | | #include <basegfx/polygon/b2dpolypolygon.hxx> |
28 | | #include <editeng/editdata.hxx> |
29 | | #include <editeng/editobj.hxx> |
30 | | #include <editeng/eeitem.hxx> |
31 | | #include <editeng/flditem.hxx> |
32 | | #include <editeng/measfld.hxx> |
33 | | #include <editeng/outlobj.hxx> |
34 | | #include <math.h> |
35 | | #include <svl/style.hxx> |
36 | | |
37 | | #include <sdr/contact/viewcontactofsdrmeasureobj.hxx> |
38 | | #include <sdr/properties/measureproperties.hxx> |
39 | | #include <svx/svddrag.hxx> |
40 | | #include <svx/svdhdl.hxx> |
41 | | #include <svx/svdmodel.hxx> |
42 | | #include <svx/svdogrp.hxx> |
43 | | #include <svx/svdomeas.hxx> |
44 | | #include <svx/svdopath.hxx> |
45 | | #include <svx/svdoutl.hxx> |
46 | | #include <svx/svdpage.hxx> |
47 | | #include <svx/svdtrans.hxx> |
48 | | #include <svx/svdview.hxx> |
49 | | #include <svx/sxmbritm.hxx> |
50 | | #include <svx/sxmlhitm.hxx> |
51 | | #include <sxmsitm.hxx> |
52 | | #include <sxmtaitm.hxx> |
53 | | #include <svx/sxmtfitm.hxx> |
54 | | #include <svx/sxmtpitm.hxx> |
55 | | #include <svx/sxmtritm.hxx> |
56 | | #include <svx/sxmuitm.hxx> |
57 | | #include <svx/xlnedcit.hxx> |
58 | | #include <svx/xlnedit.hxx> |
59 | | #include <svx/xlnedwit.hxx> |
60 | | #include <svx/xlnstcit.hxx> |
61 | | #include <svx/xlnstit.hxx> |
62 | | #include <svx/xlnstwit.hxx> |
63 | | #include <svx/xlnwtit.hxx> |
64 | | #include <svx/xpoly.hxx> |
65 | | #include <unotools/syslocale.hxx> |
66 | | #include <unotools/localedatawrapper.hxx> |
67 | | #include <vcl/ptrstyle.hxx> |
68 | | |
69 | | |
70 | 0 | SdrMeasureObjGeoData::SdrMeasureObjGeoData() {} |
71 | 0 | SdrMeasureObjGeoData::~SdrMeasureObjGeoData() {} |
72 | | |
73 | | OUString SdrMeasureObj::TakeRepresentation(SdrMeasureFieldKind eMeasureFieldKind) const |
74 | 0 | { |
75 | 0 | OUString aStr; |
76 | 0 | double fMeasureScale = 1.0; |
77 | 0 | bool bTextRota90(false); |
78 | 0 | bool bShowUnit(false); |
79 | 0 | FieldUnit eMeasureUnit(FieldUnit::NONE); |
80 | 0 | FieldUnit eModUIUnit(FieldUnit::NONE); |
81 | |
|
82 | 0 | const SfxItemSet& rSet = GetMergedItemSet(); |
83 | 0 | bTextRota90 = rSet.Get(SDRATTR_MEASURETEXTROTA90).GetValue(); |
84 | 0 | eMeasureUnit = rSet.Get(SDRATTR_MEASUREUNIT).GetValue(); |
85 | 0 | fMeasureScale = rSet.Get(SDRATTR_MEASURESCALE).GetValue(); |
86 | 0 | bShowUnit = rSet.Get(SDRATTR_MEASURESHOWUNIT).GetValue(); |
87 | 0 | sal_Int16 nNumDigits = rSet.Get(SDRATTR_MEASUREDECIMALPLACES).GetValue(); |
88 | |
|
89 | 0 | switch(eMeasureFieldKind) |
90 | 0 | { |
91 | 0 | case SdrMeasureFieldKind::Value: |
92 | 0 | { |
93 | 0 | eModUIUnit = getSdrModelFromSdrObject().GetUIUnit(); |
94 | |
|
95 | 0 | if(eMeasureUnit == FieldUnit::NONE) |
96 | 0 | eMeasureUnit = eModUIUnit; |
97 | |
|
98 | 0 | sal_Int32 nLen(GetLen(m_aPt2 - m_aPt1)); |
99 | 0 | double fFact = 1.0; |
100 | |
|
101 | 0 | if(eMeasureUnit != eModUIUnit) |
102 | 0 | { |
103 | | // for the unit conversion |
104 | 0 | fFact *= GetMapFactor(eModUIUnit, eMeasureUnit).X(); |
105 | 0 | } |
106 | |
|
107 | 0 | if(fMeasureScale != 1.0) |
108 | 0 | { |
109 | 0 | fFact *= fMeasureScale; |
110 | 0 | } |
111 | |
|
112 | 0 | if(fFact != 1.0) |
113 | 0 | { |
114 | 0 | nLen = nLen * fFact; |
115 | 0 | } |
116 | |
|
117 | 0 | aStr = getSdrModelFromSdrObject().GetMetricString(nLen, true, nNumDigits); |
118 | |
|
119 | 0 | SvtSysLocale aSysLocale; |
120 | 0 | const LocaleDataWrapper& rLocaleDataWrapper = aSysLocale.GetLocaleData(); |
121 | 0 | sal_Unicode cDec(rLocaleDataWrapper.getNumDecimalSep()[0]); |
122 | 0 | sal_Unicode cDecAlt(rLocaleDataWrapper.getNumDecimalSepAlt().toChar()); |
123 | |
|
124 | 0 | if(aStr.indexOf(cDec) != -1 || (cDecAlt && aStr.indexOf(cDecAlt) != -1)) |
125 | 0 | { |
126 | 0 | sal_Int32 nLen2(aStr.getLength() - 1); |
127 | |
|
128 | 0 | while(aStr[nLen2] == '0') |
129 | 0 | { |
130 | 0 | aStr = aStr.copy(0, nLen2); |
131 | 0 | nLen2--; |
132 | 0 | } |
133 | |
|
134 | 0 | if(aStr[nLen2] == cDec || (cDecAlt && aStr[nLen2] == cDecAlt)) |
135 | 0 | { |
136 | 0 | aStr = aStr.copy(0, nLen2); |
137 | 0 | nLen2--; |
138 | 0 | } |
139 | |
|
140 | 0 | if(aStr.isEmpty()) |
141 | 0 | aStr += "0"; |
142 | 0 | } |
143 | |
|
144 | 0 | break; |
145 | 0 | } |
146 | 0 | case SdrMeasureFieldKind::Unit: |
147 | 0 | { |
148 | 0 | if(bShowUnit) |
149 | 0 | { |
150 | 0 | eModUIUnit = getSdrModelFromSdrObject().GetUIUnit(); |
151 | |
|
152 | 0 | if(eMeasureUnit == FieldUnit::NONE) |
153 | 0 | eMeasureUnit = eModUIUnit; |
154 | |
|
155 | 0 | aStr = SdrModel::GetUnitString(eMeasureUnit); |
156 | 0 | } |
157 | |
|
158 | 0 | break; |
159 | 0 | } |
160 | 0 | case SdrMeasureFieldKind::Rotate90Blanks: |
161 | 0 | { |
162 | 0 | if(bTextRota90) |
163 | 0 | { |
164 | 0 | aStr = " "; |
165 | 0 | } |
166 | |
|
167 | 0 | break; |
168 | 0 | } |
169 | 0 | } |
170 | 0 | return aStr; |
171 | 0 | } |
172 | | |
173 | | |
174 | | // BaseProperties section |
175 | | |
176 | | std::unique_ptr<sdr::properties::BaseProperties> SdrMeasureObj::CreateObjectSpecificProperties() |
177 | 0 | { |
178 | 0 | return std::make_unique<sdr::properties::MeasureProperties>(*this); |
179 | 0 | } |
180 | | |
181 | | |
182 | | // DrawContact section |
183 | | |
184 | | std::unique_ptr<sdr::contact::ViewContact> SdrMeasureObj::CreateObjectSpecificViewContact() |
185 | 0 | { |
186 | 0 | return std::make_unique<sdr::contact::ViewContactOfSdrMeasureObj>(*this); |
187 | 0 | } |
188 | | |
189 | | |
190 | | SdrMeasureObj::SdrMeasureObj(SdrModel& rSdrModel) |
191 | 0 | : SdrTextObj(rSdrModel), |
192 | 0 | m_bTextDirty(false) |
193 | 0 | { |
194 | | // #i25616# |
195 | 0 | mbSupportTextIndentingOnLineWidthChange = false; |
196 | 0 | } |
197 | | |
198 | | SdrMeasureObj::SdrMeasureObj(SdrModel& rSdrModel, SdrMeasureObj const & rSource) |
199 | 0 | : SdrTextObj(rSdrModel, rSource), |
200 | 0 | m_bTextDirty(false) |
201 | 0 | { |
202 | | // #i25616# |
203 | 0 | mbSupportTextIndentingOnLineWidthChange = false; |
204 | |
|
205 | 0 | m_aPt1 = rSource.m_aPt1; |
206 | 0 | m_aPt2 = rSource.m_aPt2; |
207 | 0 | m_bTextDirty = rSource.m_bTextDirty; |
208 | 0 | } |
209 | | |
210 | | SdrMeasureObj::SdrMeasureObj( |
211 | | SdrModel& rSdrModel, |
212 | | const Point& rPt1, |
213 | | const Point& rPt2) |
214 | 0 | : SdrTextObj(rSdrModel), |
215 | 0 | m_aPt1(rPt1), |
216 | 0 | m_aPt2(rPt2), |
217 | 0 | m_bTextDirty(false) |
218 | 0 | { |
219 | | // #i25616# |
220 | 0 | mbSupportTextIndentingOnLineWidthChange = false; |
221 | 0 | } |
222 | | |
223 | | SdrMeasureObj::~SdrMeasureObj() |
224 | 0 | { |
225 | 0 | } |
226 | | |
227 | | void SdrMeasureObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const |
228 | 0 | { |
229 | 0 | rInfo.bMoveAllowed =true; |
230 | 0 | rInfo.bResizeFreeAllowed=true; |
231 | 0 | rInfo.bResizePropAllowed=true; |
232 | 0 | rInfo.bRotateFreeAllowed=true; |
233 | 0 | rInfo.bRotate90Allowed =true; |
234 | 0 | rInfo.bMirrorFreeAllowed=true; |
235 | 0 | rInfo.bMirror45Allowed =true; |
236 | 0 | rInfo.bMirror90Allowed =true; |
237 | 0 | rInfo.bTransparenceAllowed = false; |
238 | 0 | rInfo.bShearAllowed =true; |
239 | 0 | rInfo.bEdgeRadiusAllowed=false; |
240 | 0 | rInfo.bNoOrthoDesired =true; |
241 | 0 | rInfo.bNoContortion =false; |
242 | 0 | rInfo.bCanConvToPath =false; |
243 | 0 | rInfo.bCanConvToPoly =true; |
244 | 0 | rInfo.bCanConvToPathLineToArea=false; |
245 | 0 | rInfo.bCanConvToPolyLineToArea=false; |
246 | 0 | rInfo.bCanConvToContour = LineGeometryUsageIsNecessary(); |
247 | 0 | } |
248 | | |
249 | | SdrObjKind SdrMeasureObj::GetObjIdentifier() const |
250 | 0 | { |
251 | 0 | return SdrObjKind::Measure; |
252 | 0 | } |
253 | | |
254 | | struct ImpMeasureRec : public SdrDragStatUserData |
255 | | { |
256 | | Point aPt1; |
257 | | Point aPt2; |
258 | | css::drawing::MeasureTextHorzPos eWantTextHPos; |
259 | | css::drawing::MeasureTextVertPos eWantTextVPos; |
260 | | tools::Long nLineDist; |
261 | | tools::Long nHelplineOverhang; |
262 | | tools::Long nHelplineDist; |
263 | | tools::Long nHelpline1Len; |
264 | | tools::Long nHelpline2Len; |
265 | | bool bBelowRefEdge; |
266 | | bool bTextRota90; |
267 | | bool bTextUpsideDown; |
268 | | bool bTextAutoAngle; |
269 | | Degree100 nTextAutoAngleView; |
270 | | }; |
271 | | |
272 | | namespace { |
273 | | |
274 | | struct ImpLineRec |
275 | | { |
276 | | Point aP1; |
277 | | Point aP2; |
278 | | }; |
279 | | |
280 | | } |
281 | | |
282 | | struct ImpMeasurePoly |
283 | | { |
284 | | ImpLineRec aMainline1; // those with the 1st arrowhead |
285 | | ImpLineRec aMainline2; // those with the 2nd arrowhead |
286 | | ImpLineRec aMainline3; // those in between |
287 | | ImpLineRec aHelpline1; |
288 | | ImpLineRec aHelpline2; |
289 | | Size aTextSize; |
290 | | tools::Long nLineLen; |
291 | | Degree100 nLineAngle; |
292 | | Degree100 nTextAngle; |
293 | | Degree100 nHlpAngle; |
294 | | double nLineSin; |
295 | | double nLineCos; |
296 | | sal_uInt16 nMainlineCnt; |
297 | | css::drawing::MeasureTextHorzPos eUsedTextHPos; |
298 | | css::drawing::MeasureTextVertPos eUsedTextVPos; |
299 | | tools::Long nLineWdt2; // half the line width |
300 | | tools::Long nArrow1Len; // length of 1st arrowhead; for Center, use only half |
301 | | tools::Long nArrow2Len; // length of 2nd arrowhead; for Center, use only half |
302 | | tools::Long nArrow1Wdt; // width of 1st arrow |
303 | | tools::Long nArrow2Wdt; // width of 2nd arrow |
304 | | tools::Long nShortLineLen; // line length, if PfeileAussen (arrowheads on the outside) |
305 | | bool bAutoUpsideDown; // UpsideDown via automation |
306 | | bool bBreakedLine; |
307 | | }; |
308 | | |
309 | | void SdrMeasureObj::ImpTakeAttr(ImpMeasureRec& rRec) const |
310 | 0 | { |
311 | 0 | rRec.aPt1 = m_aPt1; |
312 | 0 | rRec.aPt2 = m_aPt2; |
313 | |
|
314 | 0 | const SfxItemSet& rSet = GetObjectItemSet(); |
315 | 0 | rRec.eWantTextHPos =rSet.Get(SDRATTR_MEASURETEXTHPOS ).GetValue(); |
316 | 0 | rRec.eWantTextVPos =rSet.Get(SDRATTR_MEASURETEXTVPOS ).GetValue(); |
317 | 0 | rRec.nLineDist =rSet.Get(SDRATTR_MEASURELINEDIST ).GetValue(); |
318 | 0 | rRec.nHelplineOverhang =rSet.Get(SDRATTR_MEASUREHELPLINEOVERHANG).GetValue(); |
319 | 0 | rRec.nHelplineDist =rSet.Get(SDRATTR_MEASUREHELPLINEDIST ).GetValue(); |
320 | 0 | rRec.nHelpline1Len =rSet.Get(SDRATTR_MEASUREHELPLINE1LEN ).GetValue(); |
321 | 0 | rRec.nHelpline2Len =rSet.Get(SDRATTR_MEASUREHELPLINE2LEN ).GetValue(); |
322 | 0 | rRec.bBelowRefEdge =rSet.Get(SDRATTR_MEASUREBELOWREFEDGE ).GetValue(); |
323 | 0 | rRec.bTextRota90 =rSet.Get(SDRATTR_MEASURETEXTROTA90 ).GetValue(); |
324 | 0 | rRec.bTextUpsideDown =static_cast<const SdrMeasureTextUpsideDownItem& >(rSet.Get(SDRATTR_MEASURETEXTUPSIDEDOWN )).GetValue(); |
325 | 0 | rRec.bTextAutoAngle =rSet.Get(SDRATTR_MEASURETEXTAUTOANGLE ).GetValue(); |
326 | 0 | rRec.nTextAutoAngleView=static_cast<const SdrMeasureTextAutoAngleViewItem&>(rSet.Get(SDRATTR_MEASURETEXTAUTOANGLEVIEW)).GetValue(); |
327 | 0 | } |
328 | | |
329 | | static tools::Long impGetLineStartEndDistance(const basegfx::B2DPolyPolygon& rPolyPolygon, tools::Long nNewWidth, bool bCenter) |
330 | 0 | { |
331 | 0 | const basegfx::B2DRange aPolygonRange(rPolyPolygon.getB2DRange()); |
332 | 0 | const double fOldWidth(std::max(aPolygonRange.getWidth(), 1.0)); |
333 | 0 | const double fScale(static_cast<double>(nNewWidth) / fOldWidth); |
334 | 0 | tools::Long nHeight(basegfx::fround<tools::Long>(aPolygonRange.getHeight() * fScale)); |
335 | |
|
336 | 0 | if(bCenter) |
337 | 0 | { |
338 | 0 | nHeight /= 2; |
339 | 0 | } |
340 | |
|
341 | 0 | return nHeight; |
342 | 0 | } |
343 | | |
344 | | void SdrMeasureObj::ImpCalcGeometrics(const ImpMeasureRec& rRec, ImpMeasurePoly& rPol) const |
345 | 0 | { |
346 | 0 | Point aP1(rRec.aPt1); |
347 | 0 | Point aP2(rRec.aPt2); |
348 | 0 | Point aDelt(aP2); aDelt-=aP1; |
349 | |
|
350 | 0 | rPol.aTextSize=GetTextSize(); |
351 | 0 | rPol.nLineLen=GetLen(aDelt); |
352 | |
|
353 | 0 | rPol.nLineWdt2=0; |
354 | 0 | tools::Long nArrow1Len=0; bool bArrow1Center=false; |
355 | 0 | tools::Long nArrow2Len=0; bool bArrow2Center=false; |
356 | 0 | tools::Long nArrow1Wdt=0; |
357 | 0 | tools::Long nArrow2Wdt=0; |
358 | 0 | rPol.nArrow1Wdt=0; |
359 | 0 | rPol.nArrow2Wdt=0; |
360 | 0 | tools::Long nArrowNeed=0; |
361 | 0 | tools::Long nShortLen=0; |
362 | 0 | bool bPfeileAussen = false; |
363 | |
|
364 | 0 | const SfxItemSet& rSet = GetObjectItemSet(); |
365 | 0 | sal_Int32 nLineWdt = rSet.Get(XATTR_LINEWIDTH).GetValue(); // line width |
366 | 0 | rPol.nLineWdt2 = (nLineWdt + 1) / 2; |
367 | |
|
368 | 0 | nArrow1Wdt = rSet.Get(XATTR_LINESTARTWIDTH).GetValue(); |
369 | 0 | if(nArrow1Wdt < 0) |
370 | 0 | nArrow1Wdt = -nLineWdt * nArrow1Wdt / 100; // <0 = relative |
371 | |
|
372 | 0 | nArrow2Wdt = rSet.Get(XATTR_LINEENDWIDTH).GetValue(); |
373 | 0 | if(nArrow2Wdt < 0) |
374 | 0 | nArrow2Wdt = -nLineWdt * nArrow2Wdt / 100; // <0 = relative |
375 | |
|
376 | 0 | basegfx::B2DPolyPolygon aPol1(rSet.Get(XATTR_LINESTART).GetLineStartValue()); |
377 | 0 | basegfx::B2DPolyPolygon aPol2(rSet.Get(XATTR_LINEEND).GetLineEndValue()); |
378 | 0 | bArrow1Center = rSet.Get(XATTR_LINESTARTCENTER).GetValue(); |
379 | 0 | bArrow2Center = rSet.Get(XATTR_LINEENDCENTER).GetValue(); |
380 | 0 | nArrow1Len = impGetLineStartEndDistance(aPol1, nArrow1Wdt, bArrow1Center) - 1; |
381 | 0 | nArrow2Len = impGetLineStartEndDistance(aPol2, nArrow2Wdt, bArrow2Center) - 1; |
382 | | |
383 | | // nArrowLen is already halved at bCenter. |
384 | | // In the case of 2 arrowheads each 4mm long, we can't go below 10mm. |
385 | 0 | nArrowNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2; |
386 | 0 | if (rPol.nLineLen<nArrowNeed) bPfeileAussen = true; |
387 | 0 | nShortLen=(nArrow1Len+nArrow1Wdt + nArrow2Len+nArrow2Wdt) /2; |
388 | |
|
389 | 0 | rPol.eUsedTextHPos=rRec.eWantTextHPos; |
390 | 0 | rPol.eUsedTextVPos=rRec.eWantTextVPos; |
391 | 0 | if (rPol.eUsedTextVPos == css::drawing::MeasureTextVertPos_AUTO) |
392 | 0 | rPol.eUsedTextVPos = css::drawing::MeasureTextVertPos_EAST; |
393 | 0 | bool bBrkLine=false; |
394 | 0 | if (rPol.eUsedTextVPos == css::drawing::MeasureTextVertPos_CENTERED) |
395 | 0 | { |
396 | 0 | OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject(); |
397 | 0 | if (pOutlinerParaObject!=nullptr && pOutlinerParaObject->GetTextObject().GetParagraphCount()==1) |
398 | 0 | { |
399 | 0 | bBrkLine=true; // dashed line if there's only on paragraph. |
400 | 0 | } |
401 | 0 | } |
402 | 0 | rPol.bBreakedLine=bBrkLine; |
403 | 0 | if (rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_AUTO) { // if text is too wide, push it outside |
404 | 0 | bool bOutside = false; |
405 | 0 | tools::Long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height(); |
406 | 0 | if (nNeedSiz>rPol.nLineLen) bOutside = true; // text doesn't fit in between |
407 | 0 | if (bBrkLine) { |
408 | 0 | if (nNeedSiz+nArrowNeed>rPol.nLineLen) bPfeileAussen = true; // text fits in between, if arrowheads are on the outside |
409 | 0 | } else { |
410 | 0 | tools::Long nSmallNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2/4; |
411 | 0 | if (nNeedSiz+nSmallNeed>rPol.nLineLen) bPfeileAussen = true; // text fits in between, if arrowheads are on the outside |
412 | 0 | } |
413 | 0 | rPol.eUsedTextHPos=bOutside ? css::drawing::MeasureTextHorzPos_LEFTOUTSIDE : css::drawing::MeasureTextHorzPos_INSIDE; |
414 | 0 | } |
415 | 0 | if (rPol.eUsedTextHPos != css::drawing::MeasureTextHorzPos_INSIDE) bPfeileAussen = true; |
416 | 0 | rPol.nArrow1Wdt=nArrow1Wdt; |
417 | 0 | rPol.nArrow2Wdt=nArrow2Wdt; |
418 | 0 | rPol.nShortLineLen=nShortLen; |
419 | 0 | rPol.nArrow1Len=nArrow1Len; |
420 | 0 | rPol.nArrow2Len=nArrow2Len; |
421 | |
|
422 | 0 | rPol.nLineAngle=GetAngle(aDelt); |
423 | 0 | double a = toRadians(rPol.nLineAngle); |
424 | 0 | double nLineSin=sin(a); |
425 | 0 | double nLineCos=cos(a); |
426 | 0 | rPol.nLineSin=nLineSin; |
427 | 0 | rPol.nLineCos=nLineCos; |
428 | |
|
429 | 0 | rPol.nTextAngle=rPol.nLineAngle; |
430 | 0 | if (rRec.bTextRota90) rPol.nTextAngle+=9000_deg100; |
431 | |
|
432 | 0 | rPol.bAutoUpsideDown=false; |
433 | 0 | if (rRec.bTextAutoAngle) { |
434 | 0 | Degree100 nTmpAngle=NormAngle36000(rPol.nTextAngle-rRec.nTextAutoAngleView); |
435 | 0 | if (nTmpAngle>=18000_deg100) { |
436 | 0 | rPol.nTextAngle+=18000_deg100; |
437 | 0 | rPol.bAutoUpsideDown=true; |
438 | 0 | } |
439 | 0 | } |
440 | |
|
441 | 0 | if (rRec.bTextUpsideDown) rPol.nTextAngle+=18000_deg100; |
442 | 0 | rPol.nTextAngle=NormAngle36000(rPol.nTextAngle); |
443 | 0 | rPol.nHlpAngle=rPol.nLineAngle+9000_deg100; |
444 | 0 | if (rRec.bBelowRefEdge) rPol.nHlpAngle+=18000_deg100; |
445 | 0 | rPol.nHlpAngle=NormAngle36000(rPol.nHlpAngle); |
446 | 0 | double nHlpSin=nLineCos; |
447 | 0 | double nHlpCos=-nLineSin; |
448 | 0 | if (rRec.bBelowRefEdge) { |
449 | 0 | nHlpSin=-nHlpSin; |
450 | 0 | nHlpCos=-nHlpCos; |
451 | 0 | } |
452 | |
|
453 | 0 | tools::Long nLineDist=rRec.nLineDist; |
454 | 0 | tools::Long nOverhang=rRec.nHelplineOverhang; |
455 | 0 | tools::Long nHelplineDist=rRec.nHelplineDist; |
456 | |
|
457 | 0 | tools::Long dx = basegfx::fround<tools::Long>(nLineDist * nHlpCos); |
458 | 0 | tools::Long dy = basegfx::fround<tools::Long>(nLineDist * -nHlpSin); |
459 | 0 | tools::Long dxh1a = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline1Len) * nHlpCos); |
460 | 0 | tools::Long dyh1a = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline1Len) * -nHlpSin); |
461 | 0 | tools::Long dxh1b = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline2Len) * nHlpCos); |
462 | 0 | tools::Long dyh1b = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline2Len) * -nHlpSin); |
463 | 0 | tools::Long dxh2 = basegfx::fround<tools::Long>((nLineDist + nOverhang) * nHlpCos); |
464 | 0 | tools::Long dyh2 = basegfx::fround<tools::Long>((nLineDist + nOverhang) * -nHlpSin); |
465 | | |
466 | | // extension line 1 |
467 | 0 | rPol.aHelpline1.aP1=Point(aP1.X()+dxh1a,aP1.Y()+dyh1a); |
468 | 0 | rPol.aHelpline1.aP2=Point(aP1.X()+dxh2,aP1.Y()+dyh2); |
469 | | |
470 | | // extension line 2 |
471 | 0 | rPol.aHelpline2.aP1=Point(aP2.X()+dxh1b,aP2.Y()+dyh1b); |
472 | 0 | rPol.aHelpline2.aP2=Point(aP2.X()+dxh2,aP2.Y()+dyh2); |
473 | | |
474 | | // dimension line |
475 | 0 | Point aMainlinePt1(aP1.X()+dx,aP1.Y()+dy); |
476 | 0 | Point aMainlinePt2(aP2.X()+dx,aP2.Y()+dy); |
477 | 0 | if (!bPfeileAussen) { |
478 | 0 | rPol.aMainline1.aP1=aMainlinePt1; |
479 | 0 | rPol.aMainline1.aP2=aMainlinePt2; |
480 | 0 | rPol.aMainline2=rPol.aMainline1; |
481 | 0 | rPol.aMainline3=rPol.aMainline1; |
482 | 0 | rPol.nMainlineCnt=1; |
483 | 0 | if (bBrkLine) { |
484 | 0 | tools::Long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height(); |
485 | 0 | tools::Long nHalfLen=(rPol.nLineLen-nNeedSiz-nArrow1Wdt/4-nArrow2Wdt/4) /2; |
486 | 0 | rPol.nMainlineCnt=2; |
487 | 0 | rPol.aMainline1.aP2=aMainlinePt1; |
488 | 0 | rPol.aMainline1.aP2.AdjustX(nHalfLen ); |
489 | 0 | RotatePoint(rPol.aMainline1.aP2,rPol.aMainline1.aP1,nLineSin,nLineCos); |
490 | 0 | rPol.aMainline2.aP1=aMainlinePt2; |
491 | 0 | rPol.aMainline2.aP1.AdjustX( -nHalfLen ); |
492 | 0 | RotatePoint(rPol.aMainline2.aP1,rPol.aMainline2.aP2,nLineSin,nLineCos); |
493 | 0 | } |
494 | 0 | } else { |
495 | 0 | tools::Long nLen1=nShortLen; // arrowhead's width as line length outside of the arrowhead |
496 | 0 | tools::Long nLen2=nShortLen; |
497 | 0 | tools::Long nTextWdt=rRec.bTextRota90 ? rPol.aTextSize.Height() : rPol.aTextSize.Width(); |
498 | 0 | if (!bBrkLine) { |
499 | 0 | if (rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_LEFTOUTSIDE) nLen1=nArrow1Len+nTextWdt; |
500 | 0 | if (rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE) nLen2=nArrow2Len+nTextWdt; |
501 | 0 | } |
502 | 0 | rPol.aMainline1.aP1=aMainlinePt1; |
503 | 0 | rPol.aMainline1.aP2=aMainlinePt1; rPol.aMainline1.aP2.AdjustX( -nLen1 ); RotatePoint(rPol.aMainline1.aP2,aMainlinePt1,nLineSin,nLineCos); |
504 | 0 | rPol.aMainline2.aP1=aMainlinePt2; rPol.aMainline2.aP1.AdjustX(nLen2 ); RotatePoint(rPol.aMainline2.aP1,aMainlinePt2,nLineSin,nLineCos); |
505 | 0 | rPol.aMainline2.aP2=aMainlinePt2; |
506 | 0 | rPol.aMainline3.aP1=aMainlinePt1; |
507 | 0 | rPol.aMainline3.aP2=aMainlinePt2; |
508 | 0 | rPol.nMainlineCnt=3; |
509 | 0 | if (bBrkLine && rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_INSIDE) rPol.nMainlineCnt=2; |
510 | 0 | } |
511 | 0 | } |
512 | | |
513 | | basegfx::B2DPolyPolygon SdrMeasureObj::ImpCalcXPoly(const ImpMeasurePoly& rPol) |
514 | 0 | { |
515 | 0 | basegfx::B2DPolyPolygon aRetval; |
516 | 0 | basegfx::B2DPolygon aPartPolyA; |
517 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP1.X(), rPol.aMainline1.aP1.Y())); |
518 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP2.X(), rPol.aMainline1.aP2.Y())); |
519 | 0 | aRetval.append(aPartPolyA); |
520 | |
|
521 | 0 | if(rPol.nMainlineCnt > 1) |
522 | 0 | { |
523 | 0 | aPartPolyA.clear(); |
524 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP1.X(), rPol.aMainline2.aP1.Y())); |
525 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP2.X(), rPol.aMainline2.aP2.Y())); |
526 | 0 | aRetval.append(aPartPolyA); |
527 | 0 | } |
528 | |
|
529 | 0 | if(rPol.nMainlineCnt > 2) |
530 | 0 | { |
531 | 0 | aPartPolyA.clear(); |
532 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP1.X(), rPol.aMainline3.aP1.Y())); |
533 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP2.X(), rPol.aMainline3.aP2.Y())); |
534 | 0 | aRetval.append(aPartPolyA); |
535 | 0 | } |
536 | |
|
537 | 0 | aPartPolyA.clear(); |
538 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP1.X(), rPol.aHelpline1.aP1.Y())); |
539 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP2.X(), rPol.aHelpline1.aP2.Y())); |
540 | 0 | aRetval.append(aPartPolyA); |
541 | |
|
542 | 0 | aPartPolyA.clear(); |
543 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP1.X(), rPol.aHelpline2.aP1.Y())); |
544 | 0 | aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP2.X(), rPol.aHelpline2.aP2.Y())); |
545 | 0 | aRetval.append(aPartPolyA); |
546 | |
|
547 | 0 | return aRetval; |
548 | 0 | } |
549 | | |
550 | | bool SdrMeasureObj::CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara, sal_uInt16 nPos, |
551 | | bool bEdit, |
552 | | std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle, OUString& rRet) const |
553 | 0 | { |
554 | 0 | const SvxFieldData* pField=rField.GetField(); |
555 | 0 | const SdrMeasureField* pMeasureField=dynamic_cast<const SdrMeasureField*>( pField ); |
556 | 0 | if (pMeasureField!=nullptr) { |
557 | 0 | rRet = TakeRepresentation(pMeasureField->GetMeasureFieldKind()); |
558 | 0 | if (rpFldColor && !bEdit) |
559 | 0 | { |
560 | 0 | rpFldColor.reset(); |
561 | 0 | } |
562 | 0 | return true; |
563 | 0 | } else { |
564 | 0 | return SdrTextObj::CalcFieldValue(rField,nPara,nPos,bEdit,rpTxtColor,rpFldColor,rpFldLineStyle,rRet); |
565 | 0 | } |
566 | 0 | } |
567 | | |
568 | | void SdrMeasureObj::UndirtyText() const |
569 | 0 | { |
570 | 0 | if (!m_bTextDirty) |
571 | 0 | return; |
572 | | |
573 | 0 | SdrOutliner& rOutliner=ImpGetDrawOutliner(); |
574 | 0 | OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject(); |
575 | 0 | if(pOutlinerParaObject==nullptr) |
576 | 0 | { |
577 | 0 | rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Rotate90Blanks), EE_FEATURE_FIELD), ESelection(0,0)); |
578 | 0 | rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Value), EE_FEATURE_FIELD),ESelection(0,1)); |
579 | 0 | rOutliner.QuickInsertText(u" "_ustr, ESelection(0,2)); |
580 | 0 | rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Unit), EE_FEATURE_FIELD),ESelection(0,3)); |
581 | 0 | rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Rotate90Blanks), EE_FEATURE_FIELD),ESelection(0,4)); |
582 | |
|
583 | 0 | if(GetStyleSheet()) |
584 | 0 | rOutliner.SetStyleSheet(0, GetStyleSheet()); |
585 | |
|
586 | 0 | rOutliner.SetParaAttribs(0, GetObjectItemSet()); |
587 | | |
588 | | // cast to nonconst |
589 | 0 | const_cast<SdrMeasureObj*>(this)->NbcSetOutlinerParaObject( rOutliner.CreateParaObject() ); |
590 | 0 | } |
591 | 0 | else |
592 | 0 | { |
593 | 0 | rOutliner.SetText(*pOutlinerParaObject); |
594 | 0 | } |
595 | |
|
596 | 0 | rOutliner.SetUpdateLayout(true); |
597 | 0 | rOutliner.UpdateFields(); |
598 | 0 | Size aSiz(rOutliner.CalcTextSize()); |
599 | 0 | rOutliner.Clear(); |
600 | | // cast to nonconst three times |
601 | 0 | const_cast<SdrMeasureObj*>(this)->maTextSize = aSiz; |
602 | 0 | const_cast<SdrMeasureObj*>(this)->mbTextSizeDirty = false; |
603 | 0 | const_cast<SdrMeasureObj*>(this)->m_bTextDirty = false; |
604 | 0 | } |
605 | | |
606 | | void SdrMeasureObj::TakeUnrotatedSnapRect(tools::Rectangle& rRect) const |
607 | 0 | { |
608 | 0 | if (m_bTextDirty) UndirtyText(); |
609 | 0 | ImpMeasureRec aRec; |
610 | 0 | ImpMeasurePoly aMPol; |
611 | 0 | ImpTakeAttr(aRec); |
612 | 0 | ImpCalcGeometrics(aRec,aMPol); |
613 | | |
614 | | // determine TextSize including text frame margins |
615 | 0 | Size aTextSize2(aMPol.aTextSize); |
616 | 0 | if (aTextSize2.Width()<1) aTextSize2.setWidth(1 ); |
617 | 0 | if (aTextSize2.Height()<1) aTextSize2.setHeight(1 ); |
618 | 0 | aTextSize2.AdjustWidth(GetTextLeftDistance()+GetTextRightDistance() ); |
619 | 0 | aTextSize2.AdjustHeight(GetTextUpperDistance()+GetTextLowerDistance() ); |
620 | |
|
621 | 0 | Point aPt1b(aMPol.aMainline1.aP1); |
622 | 0 | tools::Long nLen=aMPol.nLineLen; |
623 | 0 | tools::Long nLWdt=aMPol.nLineWdt2; |
624 | 0 | tools::Long nArr1Len=aMPol.nArrow1Len; |
625 | 0 | tools::Long nArr2Len=aMPol.nArrow2Len; |
626 | 0 | if (aMPol.bBreakedLine) { |
627 | | // In the case of a dashed line and Outside, the text should be |
628 | | // placed next to the line at the arrowhead instead of directly |
629 | | // at the arrowhead. |
630 | 0 | nArr1Len=aMPol.nShortLineLen+aMPol.nArrow1Wdt/4; |
631 | 0 | nArr2Len=aMPol.nShortLineLen+aMPol.nArrow2Wdt/4; |
632 | 0 | } |
633 | |
|
634 | 0 | Point aTextPos; |
635 | 0 | bool bRota90=aRec.bTextRota90; |
636 | 0 | bool bUpsideDown=aRec.bTextUpsideDown!=aMPol.bAutoUpsideDown; |
637 | 0 | bool bBelowRefEdge=aRec.bBelowRefEdge; |
638 | 0 | css::drawing::MeasureTextHorzPos eMH=aMPol.eUsedTextHPos; |
639 | 0 | css::drawing::MeasureTextVertPos eMV=aMPol.eUsedTextVPos; |
640 | 0 | if (!bRota90) { |
641 | 0 | switch (eMH) { |
642 | 0 | case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: aTextPos.setX(aPt1b.X()-aTextSize2.Width()-nArr1Len-nLWdt ); break; |
643 | 0 | case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: aTextPos.setX(aPt1b.X()+nLen+nArr2Len+nLWdt ); break; |
644 | 0 | default: aTextPos.setX(aPt1b.X() ); aTextSize2.setWidth(nLen ); |
645 | 0 | } |
646 | 0 | switch (eMV) { |
647 | 0 | case css::drawing::MeasureTextVertPos_CENTERED: |
648 | 0 | aTextPos.setY(aPt1b.Y()-aTextSize2.Height()/2 ); break; |
649 | 0 | case css::drawing::MeasureTextVertPos_WEST: { |
650 | 0 | if (!bUpsideDown) aTextPos.setY(aPt1b.Y()+nLWdt ); |
651 | 0 | else aTextPos.setY(aPt1b.Y()-aTextSize2.Height()-nLWdt ); |
652 | 0 | } break; |
653 | 0 | default: { |
654 | 0 | if (!bUpsideDown) aTextPos.setY(aPt1b.Y()-aTextSize2.Height()-nLWdt ); |
655 | 0 | else aTextPos.setY(aPt1b.Y()+nLWdt ); |
656 | 0 | } |
657 | 0 | } |
658 | 0 | if (bUpsideDown) { |
659 | 0 | aTextPos.AdjustX(aTextSize2.Width() ); |
660 | 0 | aTextPos.AdjustY(aTextSize2.Height() ); |
661 | 0 | } |
662 | 0 | } else { // also if bTextRota90==TRUE |
663 | 0 | switch (eMH) { |
664 | 0 | case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: aTextPos.setX(aPt1b.X()-aTextSize2.Height()-nArr1Len ); break; |
665 | 0 | case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: aTextPos.setX(aPt1b.X()+nLen+nArr2Len ); break; |
666 | 0 | default: aTextPos.setX(aPt1b.X() ); aTextSize2.setHeight(nLen ); |
667 | 0 | } |
668 | 0 | switch (eMV) { |
669 | 0 | case css::drawing::MeasureTextVertPos_CENTERED: |
670 | 0 | aTextPos.setY(aPt1b.Y()+aTextSize2.Width()/2 ); break; |
671 | 0 | case css::drawing::MeasureTextVertPos_WEST: { |
672 | 0 | if (!bBelowRefEdge) aTextPos.setY(aPt1b.Y()+aTextSize2.Width()+nLWdt ); |
673 | 0 | else aTextPos.setY(aPt1b.Y()-nLWdt ); |
674 | 0 | } break; |
675 | 0 | default: { |
676 | 0 | if (!bBelowRefEdge) aTextPos.setY(aPt1b.Y()-nLWdt ); |
677 | 0 | else aTextPos.setY(aPt1b.Y()+aTextSize2.Width()+nLWdt ); |
678 | 0 | } |
679 | 0 | } |
680 | 0 | if (bUpsideDown) { |
681 | 0 | aTextPos.AdjustX(aTextSize2.Height() ); |
682 | 0 | aTextPos.AdjustY( -(aTextSize2.Width()) ); |
683 | 0 | } |
684 | 0 | } |
685 | 0 | if (aMPol.nTextAngle != maGeo.m_nRotationAngle) { |
686 | 0 | const_cast<SdrMeasureObj*>(this)->maGeo.m_nRotationAngle=aMPol.nTextAngle; |
687 | 0 | const_cast<SdrMeasureObj*>(this)->maGeo.RecalcSinCos(); |
688 | 0 | } |
689 | 0 | RotatePoint(aTextPos,aPt1b,aMPol.nLineSin,aMPol.nLineCos); |
690 | 0 | aTextSize2.AdjustWidth( 1 ); aTextSize2.AdjustHeight( 1 ); // because of the Rect-Ctor's odd behavior |
691 | 0 | rRect=tools::Rectangle(aTextPos,aTextSize2); |
692 | 0 | rRect.Normalize(); |
693 | 0 | const_cast<SdrMeasureObj*>(this)->setRectangle(rRect); |
694 | |
|
695 | 0 | if (aMPol.nTextAngle != maGeo.m_nRotationAngle) { |
696 | 0 | const_cast<SdrMeasureObj*>(this)->maGeo.m_nRotationAngle=aMPol.nTextAngle; |
697 | 0 | const_cast<SdrMeasureObj*>(this)->maGeo.RecalcSinCos(); |
698 | 0 | } |
699 | 0 | } |
700 | | |
701 | | rtl::Reference<SdrObject> SdrMeasureObj::CloneSdrObject(SdrModel& rTargetModel) const |
702 | 0 | { |
703 | 0 | return new SdrMeasureObj(rTargetModel, *this); |
704 | 0 | } |
705 | | |
706 | | OUString SdrMeasureObj::TakeObjNameSingul() const |
707 | 0 | { |
708 | 0 | OUString sName(SvxResId(STR_ObjNameSingulMEASURE)); |
709 | |
|
710 | 0 | OUString aName( GetName() ); |
711 | 0 | if (!aName.isEmpty()) |
712 | 0 | sName += " '" + aName + "'"; |
713 | |
|
714 | 0 | return sName; |
715 | 0 | } |
716 | | |
717 | | OUString SdrMeasureObj::TakeObjNamePlural() const |
718 | 0 | { |
719 | 0 | return SvxResId(STR_ObjNamePluralMEASURE); |
720 | 0 | } |
721 | | |
722 | | basegfx::B2DPolyPolygon SdrMeasureObj::TakeXorPoly() const |
723 | 0 | { |
724 | 0 | ImpMeasureRec aRec; |
725 | 0 | ImpMeasurePoly aMPol; |
726 | 0 | ImpTakeAttr(aRec); |
727 | 0 | ImpCalcGeometrics(aRec,aMPol); |
728 | 0 | return ImpCalcXPoly(aMPol); |
729 | 0 | } |
730 | | |
731 | | sal_uInt32 SdrMeasureObj::GetHdlCount() const |
732 | 0 | { |
733 | 0 | return 6; |
734 | 0 | } |
735 | | |
736 | | void SdrMeasureObj::AddToHdlList(SdrHdlList& rHdlList) const |
737 | 0 | { |
738 | 0 | ImpMeasureRec aRec; |
739 | 0 | ImpMeasurePoly aMPol; |
740 | 0 | ImpTakeAttr(aRec); |
741 | 0 | aRec.nHelplineDist=0; |
742 | 0 | ImpCalcGeometrics(aRec,aMPol); |
743 | |
|
744 | 0 | for (sal_uInt32 nHdlNum=0; nHdlNum<6; ++nHdlNum) |
745 | 0 | { |
746 | 0 | Point aPt; |
747 | 0 | switch (nHdlNum) { |
748 | 0 | case 0: aPt=aMPol.aHelpline1.aP1; break; |
749 | 0 | case 1: aPt=aMPol.aHelpline2.aP1; break; |
750 | 0 | case 2: aPt=m_aPt1; break; |
751 | 0 | case 3: aPt=m_aPt2; break; |
752 | 0 | case 4: aPt=aMPol.aHelpline1.aP2; break; |
753 | 0 | case 5: aPt=aMPol.aHelpline2.aP2; break; |
754 | 0 | } // switch |
755 | 0 | std::unique_ptr<SdrHdl> pHdl(new ImpMeasureHdl(aPt,SdrHdlKind::User)); |
756 | 0 | pHdl->SetObjHdlNum(nHdlNum); |
757 | 0 | pHdl->SetRotationAngle(aMPol.nLineAngle); |
758 | 0 | rHdlList.AddHdl(std::move(pHdl)); |
759 | 0 | } |
760 | 0 | } |
761 | | |
762 | | |
763 | | bool SdrMeasureObj::hasSpecialDrag() const |
764 | 0 | { |
765 | 0 | return true; |
766 | 0 | } |
767 | | |
768 | | bool SdrMeasureObj::beginSpecialDrag(SdrDragStat& rDrag) const |
769 | 0 | { |
770 | 0 | const SdrHdl* pHdl = rDrag.GetHdl(); |
771 | |
|
772 | 0 | if(pHdl) |
773 | 0 | { |
774 | 0 | const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); |
775 | |
|
776 | 0 | if(nHdlNum != 2 && nHdlNum != 3) |
777 | 0 | { |
778 | 0 | rDrag.SetEndDragChangesAttributes(true); |
779 | 0 | } |
780 | |
|
781 | 0 | return true; |
782 | 0 | } |
783 | | |
784 | 0 | return false; |
785 | 0 | } |
786 | | |
787 | | bool SdrMeasureObj::applySpecialDrag(SdrDragStat& rDrag) |
788 | 0 | { |
789 | 0 | ImpMeasureRec aMeasureRec; |
790 | 0 | const SdrHdl* pHdl = rDrag.GetHdl(); |
791 | 0 | const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); |
792 | |
|
793 | 0 | ImpTakeAttr(aMeasureRec); |
794 | 0 | ImpEvalDrag(aMeasureRec, rDrag); |
795 | |
|
796 | 0 | switch (nHdlNum) |
797 | 0 | { |
798 | 0 | case 2: |
799 | 0 | { |
800 | 0 | m_aPt1 = aMeasureRec.aPt1; |
801 | 0 | SetTextDirty(); |
802 | 0 | break; |
803 | 0 | } |
804 | 0 | case 3: |
805 | 0 | { |
806 | 0 | m_aPt2 = aMeasureRec.aPt2; |
807 | 0 | SetTextDirty(); |
808 | 0 | break; |
809 | 0 | } |
810 | 0 | default: |
811 | 0 | { |
812 | 0 | switch(nHdlNum) |
813 | 0 | { |
814 | 0 | case 0: |
815 | 0 | case 1: |
816 | 0 | { |
817 | 0 | ImpMeasureRec aOrigMeasureRec; |
818 | 0 | ImpTakeAttr(aOrigMeasureRec); |
819 | |
|
820 | 0 | if(aMeasureRec.nHelpline1Len != aOrigMeasureRec.nHelpline1Len) |
821 | 0 | { |
822 | 0 | SetObjectItem(makeSdrMeasureHelpline1LenItem(aMeasureRec.nHelpline1Len)); |
823 | 0 | } |
824 | |
|
825 | 0 | if(aMeasureRec.nHelpline2Len != aOrigMeasureRec.nHelpline2Len) |
826 | 0 | { |
827 | 0 | SetObjectItem(makeSdrMeasureHelpline2LenItem(aMeasureRec.nHelpline2Len)); |
828 | 0 | } |
829 | |
|
830 | 0 | break; |
831 | 0 | } |
832 | | |
833 | 0 | case 4: |
834 | 0 | case 5: |
835 | 0 | { |
836 | 0 | ImpMeasureRec aOrigMeasureRec; |
837 | 0 | ImpTakeAttr(aOrigMeasureRec); |
838 | |
|
839 | 0 | if(aMeasureRec.nLineDist != aOrigMeasureRec.nLineDist) |
840 | 0 | { |
841 | 0 | SetObjectItem(makeSdrMeasureLineDistItem(aMeasureRec.nLineDist)); |
842 | 0 | } |
843 | |
|
844 | 0 | if(aMeasureRec.bBelowRefEdge != aOrigMeasureRec.bBelowRefEdge) |
845 | 0 | { |
846 | 0 | SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec.bBelowRefEdge)); |
847 | 0 | } |
848 | 0 | } |
849 | 0 | } |
850 | 0 | } |
851 | 0 | } // switch |
852 | | |
853 | 0 | SetBoundAndSnapRectsDirty(); |
854 | 0 | SetChanged(); |
855 | |
|
856 | 0 | return true; |
857 | 0 | } |
858 | | |
859 | | OUString SdrMeasureObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const |
860 | 0 | { |
861 | 0 | return OUString(); |
862 | 0 | } |
863 | | |
864 | | void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec& rRec, const SdrDragStat& rDrag) const |
865 | 0 | { |
866 | 0 | Degree100 nLineAngle=GetAngle(rRec.aPt2-rRec.aPt1); |
867 | 0 | double a = toRadians(nLineAngle); |
868 | 0 | double nSin=sin(a); |
869 | 0 | double nCos=cos(a); |
870 | |
|
871 | 0 | const SdrHdl* pHdl=rDrag.GetHdl(); |
872 | 0 | sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); |
873 | 0 | bool bOrtho=rDrag.GetView()!=nullptr && rDrag.GetView()->IsOrtho(); |
874 | 0 | bool bBigOrtho=bOrtho && rDrag.GetView()->IsBigOrtho(); |
875 | 0 | bool bBelow=rRec.bBelowRefEdge; |
876 | 0 | Point aPt(rDrag.GetNow()); |
877 | |
|
878 | 0 | switch (nHdlNum) { |
879 | 0 | case 0: { |
880 | 0 | RotatePoint(aPt,m_aPt1,nSin,-nCos); |
881 | 0 | rRec.nHelpline1Len=m_aPt1.Y()-aPt.Y(); |
882 | 0 | if (bBelow) rRec.nHelpline1Len=-rRec.nHelpline1Len; |
883 | 0 | if (bOrtho) rRec.nHelpline2Len=rRec.nHelpline1Len; |
884 | 0 | } break; |
885 | 0 | case 1: { |
886 | 0 | RotatePoint(aPt,m_aPt2,nSin,-nCos); |
887 | 0 | rRec.nHelpline2Len=m_aPt2.Y()-aPt.Y(); |
888 | 0 | if (bBelow) rRec.nHelpline2Len=-rRec.nHelpline2Len; |
889 | 0 | if (bOrtho) rRec.nHelpline1Len=rRec.nHelpline2Len; |
890 | 0 | } break; |
891 | 0 | case 2: case 3: { |
892 | 0 | bool bAnf=nHdlNum==2; |
893 | 0 | Point& rMov=bAnf ? rRec.aPt1 : rRec.aPt2; |
894 | 0 | Point aMov(rMov); |
895 | 0 | Point aFix(bAnf ? rRec.aPt2 : rRec.aPt1); |
896 | 0 | if (bOrtho) { |
897 | 0 | tools::Long ndx0=aMov.X()-aFix.X(); |
898 | 0 | tools::Long ndy0=aMov.Y()-aFix.Y(); |
899 | 0 | bool bHLin=ndy0==0; |
900 | 0 | bool bVLin=ndx0==0; |
901 | 0 | if (!bHLin || !bVLin) { // else aPt1==aPt2 |
902 | 0 | tools::Long ndx=aPt.X()-aFix.X(); |
903 | 0 | tools::Long ndy=aPt.Y()-aFix.Y(); |
904 | 0 | double nXFact=0; if (!bVLin) nXFact=static_cast<double>(ndx)/static_cast<double>(ndx0); |
905 | 0 | double nYFact=0; if (!bHLin) nYFact=static_cast<double>(ndy)/static_cast<double>(ndy0); |
906 | 0 | bool bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho); |
907 | 0 | bool bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho); |
908 | 0 | if (bHor) ndy=tools::Long(ndy0*nXFact); |
909 | 0 | if (bVer) ndx=tools::Long(ndx0*nYFact); |
910 | 0 | aPt=aFix; |
911 | 0 | aPt.AdjustX(ndx ); |
912 | 0 | aPt.AdjustY(ndy ); |
913 | 0 | } // else Ortho8 |
914 | 0 | } |
915 | 0 | rMov=aPt; |
916 | 0 | } break; |
917 | 0 | case 4: case 5: { |
918 | 0 | tools::Long nVal0=rRec.nLineDist; |
919 | 0 | RotatePoint(aPt,(nHdlNum==4 ? m_aPt1 : m_aPt2),nSin,-nCos); |
920 | 0 | rRec.nLineDist=aPt.Y()- (nHdlNum==4 ? m_aPt1.Y() : m_aPt2.Y()); |
921 | 0 | if (bBelow) rRec.nLineDist=-rRec.nLineDist; |
922 | 0 | if (rRec.nLineDist<0) { |
923 | 0 | rRec.nLineDist=-rRec.nLineDist; |
924 | 0 | rRec.bBelowRefEdge=!bBelow; |
925 | 0 | } |
926 | 0 | rRec.nLineDist-=rRec.nHelplineOverhang; |
927 | 0 | if (bOrtho) rRec.nLineDist=nVal0; |
928 | 0 | } break; |
929 | 0 | } // switch |
930 | 0 | } |
931 | | |
932 | | |
933 | | bool SdrMeasureObj::BegCreate(SdrDragStat& rStat) |
934 | 0 | { |
935 | 0 | rStat.SetOrtho8Possible(); |
936 | 0 | m_aPt1=rStat.GetStart(); |
937 | 0 | m_aPt2=rStat.GetNow(); |
938 | 0 | SetTextDirty(); |
939 | 0 | return true; |
940 | 0 | } |
941 | | |
942 | | bool SdrMeasureObj::MovCreate(SdrDragStat& rStat) |
943 | 0 | { |
944 | 0 | SdrView* pView=rStat.GetView(); |
945 | 0 | m_aPt1=rStat.GetStart(); |
946 | 0 | m_aPt2=rStat.GetNow(); |
947 | 0 | if (pView!=nullptr && pView->IsCreate1stPointAsCenter()) { |
948 | 0 | m_aPt1+=m_aPt1; |
949 | 0 | m_aPt1-=rStat.GetNow(); |
950 | 0 | } |
951 | 0 | SetTextDirty(); |
952 | 0 | SetBoundRectDirty(); |
953 | 0 | m_bSnapRectDirty=true; |
954 | 0 | return true; |
955 | 0 | } |
956 | | |
957 | | bool SdrMeasureObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) |
958 | 0 | { |
959 | 0 | SetTextDirty(); |
960 | 0 | SetBoundAndSnapRectsDirty(); |
961 | 0 | return (eCmd==SdrCreateCmd::ForceEnd || rStat.GetPointCount()>=2); |
962 | 0 | } |
963 | | |
964 | | bool SdrMeasureObj::BckCreate(SdrDragStat& /*rStat*/) |
965 | 0 | { |
966 | 0 | return false; |
967 | 0 | } |
968 | | |
969 | | void SdrMeasureObj::BrkCreate(SdrDragStat& /*rStat*/) |
970 | 0 | { |
971 | 0 | } |
972 | | |
973 | | basegfx::B2DPolyPolygon SdrMeasureObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const |
974 | 0 | { |
975 | 0 | ImpMeasureRec aRec; |
976 | 0 | ImpMeasurePoly aMPol; |
977 | |
|
978 | 0 | ImpTakeAttr(aRec); |
979 | 0 | ImpCalcGeometrics(aRec, aMPol); |
980 | |
|
981 | 0 | return ImpCalcXPoly(aMPol); |
982 | 0 | } |
983 | | |
984 | | PointerStyle SdrMeasureObj::GetCreatePointer() const |
985 | 0 | { |
986 | 0 | return PointerStyle::Cross; |
987 | 0 | } |
988 | | |
989 | | void SdrMeasureObj::NbcMove(const Size& rSiz) |
990 | 0 | { |
991 | 0 | SdrTextObj::NbcMove(rSiz); |
992 | 0 | m_aPt1.Move(rSiz); |
993 | 0 | m_aPt2.Move(rSiz); |
994 | 0 | } |
995 | | |
996 | | void SdrMeasureObj::NbcResize(const Point& rRef, double xFact, double yFact) |
997 | 0 | { |
998 | 0 | SdrTextObj::NbcResize(rRef,xFact,yFact); |
999 | 0 | ResizePoint(m_aPt1,rRef,xFact,yFact); |
1000 | 0 | ResizePoint(m_aPt2,rRef,xFact,yFact); |
1001 | 0 | SetTextDirty(); |
1002 | 0 | } |
1003 | | |
1004 | | void SdrMeasureObj::NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs) |
1005 | 0 | { |
1006 | 0 | SdrTextObj::NbcRotate(rRef,nAngle,sn,cs); |
1007 | 0 | tools::Long nLen0=GetLen(m_aPt2-m_aPt1); |
1008 | 0 | RotatePoint(m_aPt1,rRef,sn,cs); |
1009 | 0 | RotatePoint(m_aPt2,rRef,sn,cs); |
1010 | 0 | tools::Long nLen1=GetLen(m_aPt2-m_aPt1); |
1011 | 0 | if (nLen1!=nLen0) { // rounding error! |
1012 | 0 | tools::Long dx=m_aPt2.X()-m_aPt1.X(); |
1013 | 0 | tools::Long dy=m_aPt2.Y()-m_aPt1.Y(); |
1014 | 0 | dx=BigMulDiv(dx,nLen0,nLen1); |
1015 | 0 | dy=BigMulDiv(dy,nLen0,nLen1); |
1016 | 0 | if (rRef==m_aPt2) { |
1017 | 0 | m_aPt1.setX(m_aPt2.X()-dx ); |
1018 | 0 | m_aPt1.setY(m_aPt2.Y()-dy ); |
1019 | 0 | } else { |
1020 | 0 | m_aPt2.setX(m_aPt1.X()+dx ); |
1021 | 0 | m_aPt2.setY(m_aPt1.Y()+dy ); |
1022 | 0 | } |
1023 | 0 | } |
1024 | 0 | SetBoundAndSnapRectsDirty(); |
1025 | 0 | } |
1026 | | |
1027 | | void SdrMeasureObj::NbcMirror(const Point& rRef1, const Point& rRef2) |
1028 | 0 | { |
1029 | 0 | SdrTextObj::NbcMirror(rRef1,rRef2); |
1030 | 0 | MirrorPoint(m_aPt1,rRef1,rRef2); |
1031 | 0 | MirrorPoint(m_aPt2,rRef1,rRef2); |
1032 | 0 | SetBoundAndSnapRectsDirty(); |
1033 | 0 | } |
1034 | | |
1035 | | void SdrMeasureObj::NbcShear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear) |
1036 | 0 | { |
1037 | 0 | SdrTextObj::NbcShear(rRef,nAngle,tn,bVShear); |
1038 | 0 | ShearPoint(m_aPt1,rRef,tn,bVShear); |
1039 | 0 | ShearPoint(m_aPt2,rRef,tn,bVShear); |
1040 | 0 | SetBoundAndSnapRectsDirty(); |
1041 | 0 | SetTextDirty(); |
1042 | 0 | } |
1043 | | |
1044 | | Degree100 SdrMeasureObj::GetRotateAngle() const |
1045 | 0 | { |
1046 | 0 | return GetAngle(m_aPt2-m_aPt1); |
1047 | 0 | } |
1048 | | |
1049 | | void SdrMeasureObj::RecalcSnapRect() |
1050 | 0 | { |
1051 | 0 | ImpMeasureRec aRec; |
1052 | 0 | ImpMeasurePoly aMPol; |
1053 | 0 | XPolyPolygon aXPP; |
1054 | |
|
1055 | 0 | ImpTakeAttr(aRec); |
1056 | 0 | ImpCalcGeometrics(aRec, aMPol); |
1057 | 0 | aXPP = XPolyPolygon(ImpCalcXPoly(aMPol)); |
1058 | 0 | maSnapRect = aXPP.GetBoundRect(); |
1059 | 0 | } |
1060 | | |
1061 | | sal_uInt32 SdrMeasureObj::GetSnapPointCount() const |
1062 | 0 | { |
1063 | 0 | return 2; |
1064 | 0 | } |
1065 | | |
1066 | | Point SdrMeasureObj::GetSnapPoint(sal_uInt32 i) const |
1067 | 0 | { |
1068 | 0 | if (i==0) return m_aPt1; |
1069 | 0 | else return m_aPt2; |
1070 | 0 | } |
1071 | | |
1072 | | bool SdrMeasureObj::IsPolyObj() const |
1073 | 0 | { |
1074 | 0 | return true; |
1075 | 0 | } |
1076 | | |
1077 | | sal_uInt32 SdrMeasureObj::GetPointCount() const |
1078 | 0 | { |
1079 | 0 | return 2; |
1080 | 0 | } |
1081 | | |
1082 | | Point SdrMeasureObj::GetPoint(sal_uInt32 i) const |
1083 | 0 | { |
1084 | 0 | return (0 == i) ? m_aPt1 : m_aPt2; |
1085 | 0 | } |
1086 | | |
1087 | | void SdrMeasureObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i) |
1088 | 0 | { |
1089 | 0 | if (0 == i) |
1090 | 0 | m_aPt1=rPnt; |
1091 | 0 | if (1 == i) |
1092 | 0 | m_aPt2=rPnt; |
1093 | 0 | SetBoundAndSnapRectsDirty(); |
1094 | 0 | SetTextDirty(); |
1095 | 0 | } |
1096 | | |
1097 | | std::unique_ptr<SdrObjGeoData> SdrMeasureObj::NewGeoData() const |
1098 | 0 | { |
1099 | 0 | return std::make_unique<SdrMeasureObjGeoData>(); |
1100 | 0 | } |
1101 | | |
1102 | | void SdrMeasureObj::SaveGeoData(SdrObjGeoData& rGeo) const |
1103 | 0 | { |
1104 | 0 | SdrTextObj::SaveGeoData(rGeo); |
1105 | 0 | SdrMeasureObjGeoData& rMGeo=static_cast<SdrMeasureObjGeoData&>(rGeo); |
1106 | 0 | rMGeo.aPt1=m_aPt1; |
1107 | 0 | rMGeo.aPt2=m_aPt2; |
1108 | 0 | } |
1109 | | |
1110 | | void SdrMeasureObj::RestoreGeoData(const SdrObjGeoData& rGeo) |
1111 | 0 | { |
1112 | 0 | SdrTextObj::RestoreGeoData(rGeo); |
1113 | 0 | const SdrMeasureObjGeoData& rMGeo=static_cast<const SdrMeasureObjGeoData&>(rGeo); |
1114 | 0 | m_aPt1=rMGeo.aPt1; |
1115 | 0 | m_aPt2=rMGeo.aPt2; |
1116 | 0 | SetTextDirty(); |
1117 | 0 | } |
1118 | | |
1119 | | rtl::Reference<SdrObject> SdrMeasureObj::DoConvertToPolyObj(bool bBezier, bool bAddText) const |
1120 | 0 | { |
1121 | | // get XOR Poly as base |
1122 | 0 | XPolyPolygon aTmpPolyPolygon(TakeXorPoly()); |
1123 | | |
1124 | | // get local ItemSet and StyleSheet |
1125 | 0 | SfxItemSet aSet(GetObjectItemSet()); |
1126 | 0 | SfxStyleSheet* pStyleSheet = GetStyleSheet(); |
1127 | | |
1128 | | // prepare group |
1129 | 0 | rtl::Reference<SdrObjGroup> pGroup(new SdrObjGroup(getSdrModelFromSdrObject())); |
1130 | | |
1131 | | // prepare parameters |
1132 | 0 | basegfx::B2DPolyPolygon aPolyPoly; |
1133 | 0 | rtl::Reference<SdrPathObj> pPath; |
1134 | 0 | sal_uInt16 nCount(aTmpPolyPolygon.Count()); |
1135 | 0 | sal_uInt16 nLoopStart(0); |
1136 | |
|
1137 | 0 | if(nCount == 3) |
1138 | 0 | { |
1139 | | // three lines, first one is the middle one |
1140 | 0 | aPolyPoly.clear(); |
1141 | 0 | aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); |
1142 | |
|
1143 | 0 | pPath = new SdrPathObj( |
1144 | 0 | getSdrModelFromSdrObject(), |
1145 | 0 | SdrObjKind::PathLine, |
1146 | 0 | aPolyPoly); |
1147 | |
|
1148 | 0 | pPath->SetMergedItemSet(aSet); |
1149 | 0 | pPath->SetStyleSheet(pStyleSheet, true); |
1150 | 0 | pGroup->GetSubList()->NbcInsertObject(pPath.get()); |
1151 | 0 | aSet.Put(XLineStartWidthItem(0)); |
1152 | 0 | aSet.Put(XLineEndWidthItem(0)); |
1153 | 0 | nLoopStart = 1; |
1154 | 0 | } |
1155 | 0 | else if(nCount == 4) |
1156 | 0 | { |
1157 | | // four lines, middle line with gap, so there are two lines used |
1158 | | // which have one arrow each |
1159 | 0 | sal_Int32 nEndWidth = aSet.Get(XATTR_LINEENDWIDTH).GetValue(); |
1160 | 0 | aSet.Put(XLineEndWidthItem(0)); |
1161 | |
|
1162 | 0 | aPolyPoly.clear(); |
1163 | 0 | aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); |
1164 | 0 | pPath = new SdrPathObj( |
1165 | 0 | getSdrModelFromSdrObject(), |
1166 | 0 | SdrObjKind::PathLine, |
1167 | 0 | aPolyPoly); |
1168 | |
|
1169 | 0 | pPath->SetMergedItemSet(aSet); |
1170 | 0 | pPath->SetStyleSheet(pStyleSheet, true); |
1171 | |
|
1172 | 0 | pGroup->GetSubList()->NbcInsertObject(pPath.get()); |
1173 | |
|
1174 | 0 | aSet.Put(XLineEndWidthItem(nEndWidth)); |
1175 | 0 | aSet.Put(XLineStartWidthItem(0)); |
1176 | |
|
1177 | 0 | aPolyPoly.clear(); |
1178 | 0 | aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon()); |
1179 | 0 | pPath = new SdrPathObj( |
1180 | 0 | getSdrModelFromSdrObject(), |
1181 | 0 | SdrObjKind::PathLine, |
1182 | 0 | aPolyPoly); |
1183 | |
|
1184 | 0 | pPath->SetMergedItemSet(aSet); |
1185 | 0 | pPath->SetStyleSheet(pStyleSheet, true); |
1186 | |
|
1187 | 0 | pGroup->GetSubList()->NbcInsertObject(pPath.get()); |
1188 | |
|
1189 | 0 | aSet.Put(XLineEndWidthItem(0)); |
1190 | 0 | nLoopStart = 2; |
1191 | 0 | } |
1192 | 0 | else if(nCount == 5) |
1193 | 0 | { |
1194 | | // five lines, first two are the outer ones |
1195 | 0 | sal_Int32 nEndWidth = aSet.Get(XATTR_LINEENDWIDTH).GetValue(); |
1196 | |
|
1197 | 0 | aSet.Put(XLineEndWidthItem(0)); |
1198 | |
|
1199 | 0 | aPolyPoly.clear(); |
1200 | 0 | aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); |
1201 | 0 | pPath = new SdrPathObj( |
1202 | 0 | getSdrModelFromSdrObject(), |
1203 | 0 | SdrObjKind::PathLine, |
1204 | 0 | aPolyPoly); |
1205 | |
|
1206 | 0 | pPath->SetMergedItemSet(aSet); |
1207 | 0 | pPath->SetStyleSheet(pStyleSheet, true); |
1208 | |
|
1209 | 0 | pGroup->GetSubList()->NbcInsertObject(pPath.get()); |
1210 | |
|
1211 | 0 | aSet.Put(XLineEndWidthItem(nEndWidth)); |
1212 | 0 | aSet.Put(XLineStartWidthItem(0)); |
1213 | |
|
1214 | 0 | aPolyPoly.clear(); |
1215 | 0 | aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon()); |
1216 | 0 | pPath = new SdrPathObj( |
1217 | 0 | getSdrModelFromSdrObject(), |
1218 | 0 | SdrObjKind::PathLine, |
1219 | 0 | aPolyPoly); |
1220 | |
|
1221 | 0 | pPath->SetMergedItemSet(aSet); |
1222 | 0 | pPath->SetStyleSheet(pStyleSheet, true); |
1223 | |
|
1224 | 0 | pGroup->GetSubList()->NbcInsertObject(pPath.get()); |
1225 | |
|
1226 | 0 | aSet.Put(XLineEndWidthItem(0)); |
1227 | 0 | nLoopStart = 2; |
1228 | 0 | } |
1229 | |
|
1230 | 0 | for(;nLoopStart<nCount;nLoopStart++) |
1231 | 0 | { |
1232 | 0 | aPolyPoly.clear(); |
1233 | 0 | aPolyPoly.append(aTmpPolyPolygon[nLoopStart].getB2DPolygon()); |
1234 | 0 | pPath = new SdrPathObj( |
1235 | 0 | getSdrModelFromSdrObject(), |
1236 | 0 | SdrObjKind::PathLine, |
1237 | 0 | aPolyPoly); |
1238 | |
|
1239 | 0 | pPath->SetMergedItemSet(aSet); |
1240 | 0 | pPath->SetStyleSheet(pStyleSheet, true); |
1241 | |
|
1242 | 0 | pGroup->GetSubList()->NbcInsertObject(pPath.get()); |
1243 | 0 | } |
1244 | |
|
1245 | 0 | if(bAddText) |
1246 | 0 | { |
1247 | 0 | return ImpConvertAddText(std::move(pGroup), bBezier); |
1248 | 0 | } |
1249 | 0 | else |
1250 | 0 | { |
1251 | 0 | return pGroup; |
1252 | 0 | } |
1253 | 0 | } |
1254 | | |
1255 | | bool SdrMeasureObj::BegTextEdit(SdrOutliner& rOutl) |
1256 | 0 | { |
1257 | 0 | UndirtyText(); |
1258 | 0 | return SdrTextObj::BegTextEdit(rOutl); |
1259 | 0 | } |
1260 | | |
1261 | | const Size& SdrMeasureObj::GetTextSize() const |
1262 | 0 | { |
1263 | 0 | if (m_bTextDirty) UndirtyText(); |
1264 | 0 | return SdrTextObj::GetTextSize(); |
1265 | 0 | } |
1266 | | |
1267 | | OutlinerParaObject* SdrMeasureObj::GetOutlinerParaObject() const |
1268 | 0 | { |
1269 | 0 | if(m_bTextDirty) |
1270 | 0 | UndirtyText(); |
1271 | 0 | return SdrTextObj::GetOutlinerParaObject(); |
1272 | 0 | } |
1273 | | |
1274 | | void SdrMeasureObj::NbcSetOutlinerParaObject(std::optional<OutlinerParaObject> pTextObject, bool bAdjustTextFrameWidthAndHeight) |
1275 | 0 | { |
1276 | 0 | SdrTextObj::NbcSetOutlinerParaObject(std::move(pTextObject), bAdjustTextFrameWidthAndHeight); |
1277 | 0 | if(SdrTextObj::GetOutlinerParaObject()) |
1278 | 0 | SetTextDirty(); // recalculate text |
1279 | 0 | } |
1280 | | |
1281 | | void SdrMeasureObj::TakeTextRect( SdrOutliner& rOutliner, tools::Rectangle& rTextRect, bool bNoEditText, |
1282 | | tools::Rectangle* pAnchorRect, bool bLineWidth ) const |
1283 | 0 | { |
1284 | 0 | if (m_bTextDirty) UndirtyText(); |
1285 | 0 | SdrTextObj::TakeTextRect( rOutliner, rTextRect, bNoEditText, pAnchorRect, bLineWidth ); |
1286 | 0 | } |
1287 | | |
1288 | | void SdrMeasureObj::TakeTextAnchorRect(tools::Rectangle& rAnchorRect) const |
1289 | 0 | { |
1290 | 0 | if (m_bTextDirty) UndirtyText(); |
1291 | 0 | SdrTextObj::TakeTextAnchorRect(rAnchorRect); |
1292 | 0 | } |
1293 | | |
1294 | | void SdrMeasureObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, tools::Rectangle* pViewInit, tools::Rectangle* pViewMin) const |
1295 | 0 | { |
1296 | 0 | if (m_bTextDirty) UndirtyText(); |
1297 | 0 | SdrTextObj::TakeTextEditArea(pPaperMin,pPaperMax,pViewInit,pViewMin); |
1298 | 0 | } |
1299 | | |
1300 | | EEAnchorMode SdrMeasureObj::GetOutlinerViewAnchorMode() const |
1301 | 0 | { |
1302 | 0 | if (m_bTextDirty) UndirtyText(); |
1303 | 0 | ImpMeasureRec aRec; |
1304 | 0 | ImpMeasurePoly aMPol; |
1305 | 0 | ImpTakeAttr(aRec); |
1306 | 0 | ImpCalcGeometrics(aRec,aMPol); |
1307 | |
|
1308 | 0 | SdrTextHorzAdjust eTH=GetTextHorizontalAdjust(); |
1309 | 0 | SdrTextVertAdjust eTV=GetTextVerticalAdjust(); |
1310 | 0 | css::drawing::MeasureTextHorzPos eMH = aMPol.eUsedTextHPos; |
1311 | 0 | css::drawing::MeasureTextVertPos eMV = aMPol.eUsedTextVPos; |
1312 | 0 | bool bTextRota90=aRec.bTextRota90; |
1313 | 0 | bool bBelowRefEdge=aRec.bBelowRefEdge; |
1314 | | |
1315 | | // TODO: bTextUpsideDown should be interpreted here! |
1316 | 0 | if (!bTextRota90) { |
1317 | 0 | if (eMH==css::drawing::MeasureTextHorzPos_LEFTOUTSIDE) eTH=SDRTEXTHORZADJUST_RIGHT; |
1318 | 0 | if (eMH==css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE) eTH=SDRTEXTHORZADJUST_LEFT; |
1319 | | // at eMH==css::drawing::MeasureTextHorzPos_INSIDE we can anchor horizontally |
1320 | 0 | if (eMV==css::drawing::MeasureTextVertPos_EAST) eTV=SDRTEXTVERTADJUST_BOTTOM; |
1321 | 0 | if (eMV==css::drawing::MeasureTextVertPos_WEST) eTV=SDRTEXTVERTADJUST_TOP; |
1322 | 0 | if (eMV==css::drawing::MeasureTextVertPos_CENTERED) eTV=SDRTEXTVERTADJUST_CENTER; |
1323 | 0 | } else { |
1324 | 0 | if (eMH==css::drawing::MeasureTextHorzPos_LEFTOUTSIDE) eTV=SDRTEXTVERTADJUST_BOTTOM; |
1325 | 0 | if (eMH==css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE) eTV=SDRTEXTVERTADJUST_TOP; |
1326 | | // at eMH==css::drawing::MeasureTextHorzPos_INSIDE we can anchor vertically |
1327 | 0 | if (!bBelowRefEdge) { |
1328 | 0 | if (eMV==css::drawing::MeasureTextVertPos_EAST) eTH=SDRTEXTHORZADJUST_LEFT; |
1329 | 0 | if (eMV==css::drawing::MeasureTextVertPos_WEST) eTH=SDRTEXTHORZADJUST_RIGHT; |
1330 | 0 | } else { |
1331 | 0 | if (eMV==css::drawing::MeasureTextVertPos_EAST) eTH=SDRTEXTHORZADJUST_RIGHT; |
1332 | 0 | if (eMV==css::drawing::MeasureTextVertPos_WEST) eTH=SDRTEXTHORZADJUST_LEFT; |
1333 | 0 | } |
1334 | 0 | if (eMV==css::drawing::MeasureTextVertPos_CENTERED) eTH=SDRTEXTHORZADJUST_CENTER; |
1335 | 0 | } |
1336 | |
|
1337 | 0 | EEAnchorMode eRet=EEAnchorMode::BottomHCenter; |
1338 | 0 | if (eTH==SDRTEXTHORZADJUST_LEFT) { |
1339 | 0 | if (eTV==SDRTEXTVERTADJUST_TOP) eRet=EEAnchorMode::TopLeft; |
1340 | 0 | else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=EEAnchorMode::BottomLeft; |
1341 | 0 | else eRet=EEAnchorMode::VCenterLeft; |
1342 | 0 | } else if (eTH==SDRTEXTHORZADJUST_RIGHT) { |
1343 | 0 | if (eTV==SDRTEXTVERTADJUST_TOP) eRet=EEAnchorMode::TopRight; |
1344 | 0 | else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=EEAnchorMode::BottomRight; |
1345 | 0 | else eRet=EEAnchorMode::VCenterRight; |
1346 | 0 | } else { |
1347 | 0 | if (eTV==SDRTEXTVERTADJUST_TOP) eRet=EEAnchorMode::TopHCenter; |
1348 | 0 | else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=EEAnchorMode::BottomHCenter; |
1349 | 0 | else eRet=EEAnchorMode::VCenterHCenter; |
1350 | 0 | } |
1351 | 0 | return eRet; |
1352 | 0 | } |
1353 | | |
1354 | | |
1355 | | // #i97878# |
1356 | | // TRGetBaseGeometry/TRSetBaseGeometry needs to be based on two positions, |
1357 | | // same as line geometry in SdrPathObj. Thus needs to be overridden and |
1358 | | // implemented since currently it is derived from SdrTextObj which uses |
1359 | | // a functionality based on SnapRect which is not useful here |
1360 | | |
1361 | | bool SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const |
1362 | 0 | { |
1363 | | // handle the same as a simple line since the definition is based on two points |
1364 | 0 | const basegfx::B2DRange aRange(m_aPt1.X(), m_aPt1.Y(), m_aPt2.X(), m_aPt2.Y()); |
1365 | 0 | basegfx::B2DTuple aScale(aRange.getRange()); |
1366 | 0 | basegfx::B2DTuple aTranslate(aRange.getMinimum()); |
1367 | | |
1368 | | // position maybe relative to anchor position, convert |
1369 | 0 | if( getSdrModelFromSdrObject().IsWriter() ) |
1370 | 0 | { |
1371 | 0 | if(GetAnchorPos().X() || GetAnchorPos().Y()) |
1372 | 0 | { |
1373 | 0 | aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); |
1374 | 0 | } |
1375 | 0 | } |
1376 | | |
1377 | | // build return value matrix |
1378 | 0 | rMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(aScale, aTranslate); |
1379 | |
|
1380 | 0 | return true; |
1381 | 0 | } |
1382 | | |
1383 | | void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) |
1384 | 0 | { |
1385 | | // use given transformation to derive the two defining points from unit line |
1386 | 0 | basegfx::B2DPoint aPosA(rMatrix * basegfx::B2DPoint(0.0, 0.0)); |
1387 | 0 | basegfx::B2DPoint aPosB(rMatrix * basegfx::B2DPoint(1.0, 0.0)); |
1388 | |
|
1389 | 0 | if( getSdrModelFromSdrObject().IsWriter() ) |
1390 | 0 | { |
1391 | | // if anchor is used, make position relative to it |
1392 | 0 | if(GetAnchorPos().X() || GetAnchorPos().Y()) |
1393 | 0 | { |
1394 | 0 | const basegfx::B2DVector aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y()); |
1395 | |
|
1396 | 0 | aPosA += aAnchorOffset; |
1397 | 0 | aPosB += aAnchorOffset; |
1398 | 0 | } |
1399 | 0 | } |
1400 | | |
1401 | | // derive new model data |
1402 | 0 | const Point aNewPt1(basegfx::fround<tools::Long>(aPosA.getX()), basegfx::fround<tools::Long>(aPosA.getY())); |
1403 | 0 | const Point aNewPt2(basegfx::fround<tools::Long>(aPosB.getX()), basegfx::fround<tools::Long>(aPosB.getY())); |
1404 | |
|
1405 | 0 | if(aNewPt1 == m_aPt1 && aNewPt2 == m_aPt2) |
1406 | 0 | return; |
1407 | | |
1408 | | // set model values and broadcast |
1409 | 0 | tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect(); |
1410 | |
|
1411 | 0 | m_aPt1 = aNewPt1; |
1412 | 0 | m_aPt2 = aNewPt2; |
1413 | |
|
1414 | 0 | SetTextDirty(); |
1415 | 0 | ActionChanged(); |
1416 | 0 | SetChanged(); |
1417 | 0 | BroadcastObjectChange(); |
1418 | 0 | SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0); |
1419 | 0 | } |
1420 | | |
1421 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |