xref: /AOO41X/main/svx/source/svdraw/svdomeas.cxx (revision ae2dc0fa19335fe713e6dbbf20d81f8e1d5c6ee5)
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/svdomeas.hxx>
28 #include <math.h>
29 #include "svx/svditext.hxx" //
30 #include <svx/xpoly.hxx>
31 #include <svx/svdtrans.hxx>
32 #include <svx/svdhdl.hxx>
33 #include <svx/svdoutl.hxx>
34 #include <svx/svddrag.hxx>
35 #include <svx/svdpool.hxx>
36 #include <svx/svdattrx.hxx>
37 #include <svx/svdmodel.hxx>
38 #include <svx/svdview.hxx>
39 #include "svx/svdglob.hxx"   // StringCache
40 #include "svx/svdstr.hrc"    // Objektname
41 #include <svl/style.hxx>
42 #include <svl/smplhint.hxx>
43 #include <editeng/eeitem.hxx>
44 #include <svx/xlnstit.hxx>
45 #include <svx/xlnstwit.hxx>
46 #include <svx/xlnedit.hxx>
47 #include <svx/xlnwtit.hxx>
48 #include <svx/xlnedwit.hxx>
49 #include <svx/xlnstcit.hxx>
50 #include <svx/xlnedcit.hxx>
51 #include <editeng/outlobj.hxx>
52 #include <editeng/outliner.hxx>
53 #include <editeng/editobj.hxx>
54 #include <editeng/measfld.hxx>
55 #include <editeng/flditem.hxx>
56 #include <svx/svdogrp.hxx>
57 #include <svx/svdopath.hxx>
58 #include <svx/svdpage.hxx>
59 #include <unotools/syslocale.hxx>
60 #include "svdoimp.hxx"
61 #include <svx/sdr/properties/measureproperties.hxx>
62 #include <svx/sdr/contact/viewcontactofsdrmeasureobj.hxx>
63 #include <basegfx/point/b2dpoint.hxx>
64 #include <basegfx/polygon/b2dpolygon.hxx>
65 #include <basegfx/polygon/b2dpolypolygon.hxx>
66 #include <basegfx/matrix/b2dhommatrix.hxx>
67 #include <basegfx/matrix/b2dhommatrixtools.hxx>
68 
69 ////////////////////////////////////////////////////////////////////////////////////////////////////
70 
SdrMeasureObjGeoData()71 SdrMeasureObjGeoData::SdrMeasureObjGeoData() {}
~SdrMeasureObjGeoData()72 SdrMeasureObjGeoData::~SdrMeasureObjGeoData() {}
73 
TakeRepresentation(XubString & rStr,SdrMeasureFieldKind eMeasureFieldKind) const74 void SdrMeasureObj::TakeRepresentation( XubString& rStr, SdrMeasureFieldKind eMeasureFieldKind ) const
75 {
76     rStr.Erase();
77     Fraction aMeasureScale(1, 1);
78     sal_Bool bTextRota90(sal_False);
79     sal_Bool bShowUnit(sal_False);
80     FieldUnit eMeasureUnit(FUNIT_NONE);
81     FieldUnit eModUIUnit(FUNIT_NONE);
82 
83     const SfxItemSet& rSet = GetMergedItemSet();
84     bTextRota90 = ((SdrMeasureTextRota90Item&)rSet.Get(SDRATTR_MEASURETEXTROTA90)).GetValue();
85     eMeasureUnit = ((SdrMeasureUnitItem&)rSet.Get(SDRATTR_MEASUREUNIT)).GetValue();
86     aMeasureScale = ((SdrMeasureScaleItem&)rSet.Get(SDRATTR_MEASURESCALE)).GetValue();
87     bShowUnit = ((SdrMeasureShowUnitItem&)rSet.Get(SDRATTR_MEASURESHOWUNIT)).GetValue();
88     sal_Int16 nNumDigits = ((SdrMeasureDecimalPlacesItem&)rSet.Get(SDRATTR_MEASUREDECIMALPLACES)).GetValue();
89 
90     //SdrModel* pModel = rObj.pModel;
91 
92     switch(eMeasureFieldKind)
93     {
94         case SDRMEASUREFIELD_VALUE:
95         {
96             if(pModel)
97             {
98                 eModUIUnit = pModel->GetUIUnit();
99 
100                 if(eMeasureUnit == FUNIT_NONE)
101                     eMeasureUnit = eModUIUnit;
102 
103                 sal_Int32 nLen(GetLen(aPt2 - aPt1));
104                 Fraction aFact(1,1);
105 
106                 if(eMeasureUnit != eModUIUnit)
107                 {
108                     // Zur Umrechnung der Einheiten
109                     aFact *= GetMapFactor(eModUIUnit, eMeasureUnit).X();
110                 }
111 
112                 if(aMeasureScale.GetNumerator() != aMeasureScale.GetDenominator())
113                 {
114                     aFact *= aMeasureScale;
115                 }
116 
117                 if(aFact.GetNumerator() != aFact.GetDenominator())
118                 {
119                     // Scaling ueber BigInt, um Ueberlaeufe zu vermeiden
120                     nLen = BigMulDiv(nLen, aFact.GetNumerator(), aFact.GetDenominator());
121                 }
122 
123                 pModel->TakeMetricStr(nLen, rStr, sal_True, nNumDigits);
124 
125                 if(!aFact.IsValid())
126                 {
127                     rStr = String();
128                     rStr += sal_Unicode('?');
129                 }
130 
131                 sal_Unicode cDec(SvtSysLocale().GetLocaleData().getNumDecimalSep().GetChar(0));
132 
133                 if(rStr.Search(cDec) != STRING_NOTFOUND)
134                 {
135                     xub_StrLen nLen2(rStr.Len() - 1);
136 
137                     while(rStr.GetChar(nLen2) == sal_Unicode('0'))
138                     {
139                         rStr.Erase(nLen2);
140                         nLen2--;
141                     }
142 
143                     if(rStr.GetChar(nLen2) == cDec)
144                     {
145                         rStr.Erase(nLen2);
146                         nLen2--;
147                     }
148 
149                     if(!rStr.Len())
150                         rStr += sal_Unicode('0');
151                 }
152             }
153             else
154             {
155                 // falls kein Model da ... (z.B. Preview im Dialog)
156                 rStr = String();
157                 rStr.AppendAscii("4711");
158             }
159 
160             break;
161         }
162         case SDRMEASUREFIELD_UNIT:
163         {
164             if(bShowUnit)
165             {
166                 if(pModel)
167                 {
168                     eModUIUnit = pModel->GetUIUnit();
169 
170                     if(eMeasureUnit == FUNIT_NONE)
171                         eMeasureUnit = eModUIUnit;
172 
173                     if(bShowUnit)
174                         pModel->TakeUnitStr(eMeasureUnit, rStr);
175                 }
176             }
177 
178             break;
179         }
180         case SDRMEASUREFIELD_ROTA90BLANCS:
181         {
182             if(bTextRota90)
183             {
184                 rStr = String();
185                 rStr += sal_Unicode(' ');
186             }
187 
188             break;
189         }
190     }
191 }
192 
193 //////////////////////////////////////////////////////////////////////////////
194 // BaseProperties section
195 
CreateObjectSpecificProperties()196 sdr::properties::BaseProperties* SdrMeasureObj::CreateObjectSpecificProperties()
197 {
198     return new sdr::properties::MeasureProperties(*this);
199 }
200 
201 //////////////////////////////////////////////////////////////////////////////
202 // DrawContact section
203 
CreateObjectSpecificViewContact()204 sdr::contact::ViewContact* SdrMeasureObj::CreateObjectSpecificViewContact()
205 {
206     return new sdr::contact::ViewContactOfSdrMeasureObj(*this);
207 }
208 
209 //////////////////////////////////////////////////////////////////////////////
210 
211 TYPEINIT1(SdrMeasureObj,SdrTextObj);
212 
SdrMeasureObj()213 SdrMeasureObj::SdrMeasureObj():
214     bTextDirty(sal_False)
215 {
216     // #i25616#
217     mbSupportTextIndentingOnLineWidthChange = sal_False;
218 }
219 
SdrMeasureObj(const Point & rPt1,const Point & rPt2)220 SdrMeasureObj::SdrMeasureObj(const Point& rPt1, const Point& rPt2):
221     aPt1(rPt1),
222     aPt2(rPt2),
223     bTextDirty(sal_False)
224 {
225     // #i25616#
226     mbSupportTextIndentingOnLineWidthChange = sal_False;
227 }
228 
~SdrMeasureObj()229 SdrMeasureObj::~SdrMeasureObj()
230 {
231 }
232 
TakeObjInfo(SdrObjTransformInfoRec & rInfo) const233 void SdrMeasureObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
234 {
235     rInfo.bSelectAllowed    =sal_True;
236     rInfo.bMoveAllowed      =sal_True;
237     rInfo.bResizeFreeAllowed=sal_True;
238     rInfo.bResizePropAllowed=sal_True;
239     rInfo.bRotateFreeAllowed=sal_True;
240     rInfo.bRotate90Allowed  =sal_True;
241     rInfo.bMirrorFreeAllowed=sal_True;
242     rInfo.bMirror45Allowed  =sal_True;
243     rInfo.bMirror90Allowed  =sal_True;
244     rInfo.bTransparenceAllowed = sal_False;
245     rInfo.bGradientAllowed = sal_False;
246     rInfo.bShearAllowed     =sal_True;
247     rInfo.bEdgeRadiusAllowed=sal_False;
248     rInfo.bNoOrthoDesired   =sal_True;
249     rInfo.bNoContortion     =sal_False;
250     rInfo.bCanConvToPath    =sal_False;
251     rInfo.bCanConvToPoly    =sal_True;
252     rInfo.bCanConvToPathLineToArea=sal_False;
253     rInfo.bCanConvToPolyLineToArea=sal_False;
254     rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
255 }
256 
GetObjIdentifier() const257 sal_uInt16 SdrMeasureObj::GetObjIdentifier() const
258 {
259     return (sal_uInt16)OBJ_MEASURE;
260 }
261 
262 struct ImpMeasureRec : public SdrDragStatUserData
263 {
264     Point                       aPt1;
265     Point                       aPt2;
266     SdrMeasureKind              eKind;
267     SdrMeasureTextHPos          eWantTextHPos;
268     SdrMeasureTextVPos          eWantTextVPos;
269     long                        nLineDist;
270     long                        nHelplineOverhang;
271     long                        nHelplineDist;
272     long                        nHelpline1Len;
273     long                        nHelpline2Len;
274     FASTBOOL                    bBelowRefEdge;
275     FASTBOOL                    bTextRota90;
276     FASTBOOL                    bTextUpsideDown;
277     long                        nMeasureOverhang;
278     FieldUnit                   eMeasureUnit;
279     Fraction                    aMeasureScale;
280     FASTBOOL                    bShowUnit;
281     String                      aFormatString;
282     FASTBOOL                    bTextAutoAngle;
283     long                        nTextAutoAngleView;
284     FASTBOOL                    bTextIsFixedAngle;
285     long                        nTextFixedAngle;
286 };
287 
288 struct ImpLineRec
289 {
290     Point                       aP1;
291     Point                       aP2;
292 };
293 
294 struct ImpMeasurePoly
295 {
296     ImpLineRec                  aMainline1; // die mit dem 1. Pfeil
297     ImpLineRec                  aMainline2; // die mit dem 2. Pfeil
298     ImpLineRec                  aMainline3; // die dazwischen
299     ImpLineRec                  aHelpline1;
300     ImpLineRec                  aHelpline2;
301     Rectangle                   aTextRect;
302     Size                        aTextSize;
303     long                        nLineLen;
304     long                        nLineWink;
305     long                        nTextWink;
306     long                        nHlpWink;
307     double                      nLineSin;
308     double                      nLineCos;
309     double                      nHlpSin;
310     double                      nHlpCos;
311     sal_uInt16                      nMainlineAnz;
312     SdrMeasureTextHPos          eUsedTextHPos;
313     SdrMeasureTextVPos          eUsedTextVPos;
314     long                        nLineWdt2;  // Halbe Strichstaerke
315     long                        nArrow1Len; // Laenge des 1. Pfeils. Bei Center nur die Haelfte
316     long                        nArrow2Len; // Laenge des 2. Pfeils. Bei Center nur die Haelfte
317     long                        nArrow1Wdt; // Breite des 1. Pfeils
318     long                        nArrow2Wdt; // Breite des 2. Pfeils
319     long                        nShortLineLen; // Linienlaenge, wenn PfeileAussen
320     FASTBOOL                    bArrow1Center; // Pfeil 1 zentriert?
321     FASTBOOL                    bArrow2Center; // Pfeil 2 zentriert?
322     FASTBOOL                    bAutoUpsideDown; // UpsideDown durch Automatik
323     FASTBOOL                    bPfeileAussen;
324     FASTBOOL                    bBreakedLine;
325 };
326 
ImpTakeAttr(ImpMeasureRec & rRec) const327 void SdrMeasureObj::ImpTakeAttr(ImpMeasureRec& rRec) const
328 {
329     rRec.aPt1 = aPt1;
330     rRec.aPt2 = aPt2;
331 
332     const SfxItemSet& rSet = GetObjectItemSet();
333     rRec.eKind            =((SdrMeasureKindItem&            )rSet.Get(SDRATTR_MEASUREKIND            )).GetValue();
334     rRec.eWantTextHPos    =((SdrMeasureTextHPosItem&        )rSet.Get(SDRATTR_MEASURETEXTHPOS        )).GetValue();
335     rRec.eWantTextVPos    =((SdrMeasureTextVPosItem&        )rSet.Get(SDRATTR_MEASURETEXTVPOS        )).GetValue();
336     rRec.nLineDist        =((SdrMeasureLineDistItem&        )rSet.Get(SDRATTR_MEASURELINEDIST        )).GetValue();
337     rRec.nHelplineOverhang=((SdrMeasureHelplineOverhangItem&)rSet.Get(SDRATTR_MEASUREHELPLINEOVERHANG)).GetValue();
338     rRec.nHelplineDist    =((SdrMeasureHelplineDistItem&    )rSet.Get(SDRATTR_MEASUREHELPLINEDIST    )).GetValue();
339     rRec.nHelpline1Len    =((SdrMeasureHelpline1LenItem&    )rSet.Get(SDRATTR_MEASUREHELPLINE1LEN    )).GetValue();
340     rRec.nHelpline2Len    =((SdrMeasureHelpline2LenItem&    )rSet.Get(SDRATTR_MEASUREHELPLINE2LEN    )).GetValue();
341     rRec.bBelowRefEdge    =((SdrMeasureBelowRefEdgeItem&    )rSet.Get(SDRATTR_MEASUREBELOWREFEDGE    )).GetValue();
342     rRec.bTextRota90      =((SdrMeasureTextRota90Item&      )rSet.Get(SDRATTR_MEASURETEXTROTA90      )).GetValue();
343     rRec.bTextUpsideDown  =((SdrMeasureTextUpsideDownItem&  )rSet.Get(SDRATTR_MEASURETEXTUPSIDEDOWN  )).GetValue();
344     rRec.nMeasureOverhang =((SdrMeasureOverhangItem&        )rSet.Get(SDRATTR_MEASUREOVERHANG        )).GetValue();
345     rRec.eMeasureUnit     =((SdrMeasureUnitItem&            )rSet.Get(SDRATTR_MEASUREUNIT            )).GetValue();
346     rRec.aMeasureScale    =((SdrMeasureScaleItem&           )rSet.Get(SDRATTR_MEASURESCALE           )).GetValue();
347     rRec.bShowUnit        =((SdrMeasureShowUnitItem&        )rSet.Get(SDRATTR_MEASURESHOWUNIT        )).GetValue();
348     rRec.aFormatString    =((SdrMeasureFormatStringItem&    )rSet.Get(SDRATTR_MEASUREFORMATSTRING    )).GetValue();
349     rRec.bTextAutoAngle    =((SdrMeasureTextAutoAngleItem&    )rSet.Get(SDRATTR_MEASURETEXTAUTOANGLE    )).GetValue();
350     rRec.nTextAutoAngleView=((SdrMeasureTextAutoAngleViewItem&)rSet.Get(SDRATTR_MEASURETEXTAUTOANGLEVIEW)).GetValue();
351     rRec.bTextIsFixedAngle =((SdrMeasureTextIsFixedAngleItem& )rSet.Get(SDRATTR_MEASURETEXTISFIXEDANGLE )).GetValue();
352     rRec.nTextFixedAngle   =((SdrMeasureTextFixedAngleItem&   )rSet.Get(SDRATTR_MEASURETEXTFIXEDANGLE   )).GetValue();
353 }
354 
impGetLineStartEndDistance(const basegfx::B2DPolyPolygon & rPolyPolygon,long nNewWidth,bool bCenter)355 long impGetLineStartEndDistance(const basegfx::B2DPolyPolygon& rPolyPolygon, long nNewWidth, bool bCenter)
356 {
357     const basegfx::B2DRange aPolygonRange(rPolyPolygon.getB2DRange());
358     const double fOldWidth(aPolygonRange.getWidth() > 1.0 ? aPolygonRange.getWidth() : 1.0);
359     const double fScale((double)nNewWidth / fOldWidth);
360     long nHeight(basegfx::fround(aPolygonRange.getHeight() * fScale));
361 
362     if(bCenter)
363     {
364         nHeight /= 2L;
365     }
366 
367     return nHeight;
368 }
369 
ImpCalcGeometrics(const ImpMeasureRec & rRec,ImpMeasurePoly & rPol) const370 void SdrMeasureObj::ImpCalcGeometrics(const ImpMeasureRec& rRec, ImpMeasurePoly& rPol) const
371 {
372     Point aP1(rRec.aPt1);
373     Point aP2(rRec.aPt2);
374     Point aDelt(aP2); aDelt-=aP1;
375 
376     rPol.aTextSize=GetTextSize();
377     rPol.nLineLen=GetLen(aDelt);
378 
379     rPol.nLineWdt2=0;
380     long nArrow1Len=0; bool bArrow1Center=false;
381     long nArrow2Len=0; bool bArrow2Center=false;
382     long nArrow1Wdt=0;
383     long nArrow2Wdt=0;
384     rPol.nArrow1Wdt=0;
385     rPol.nArrow2Wdt=0;
386     long nArrowNeed=0;
387     long nShortLen=0;
388     FASTBOOL bPfeileAussen=sal_False;
389 
390     const SfxItemSet& rSet = GetObjectItemSet();
391     sal_Int32 nLineWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue(); // Strichstaerke
392     rPol.nLineWdt2 = (nLineWdt + 1) / 2;
393 
394     nArrow1Wdt = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
395     if(nArrow1Wdt < 0)
396         nArrow1Wdt = -nLineWdt * nArrow1Wdt / 100; // <0 = relativ
397 
398     nArrow2Wdt = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue();
399     if(nArrow2Wdt < 0)
400         nArrow2Wdt = -nLineWdt * nArrow2Wdt / 100; // <0 = relativ
401 
402     basegfx::B2DPolyPolygon aPol1(((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetLineStartValue());
403     basegfx::B2DPolyPolygon aPol2(((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetLineEndValue());
404     bArrow1Center = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue();
405     bArrow2Center = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue();
406     nArrow1Len = impGetLineStartEndDistance(aPol1, nArrow1Wdt, bArrow1Center) - 1;
407     nArrow2Len = impGetLineStartEndDistance(aPol2, nArrow2Wdt, bArrow2Center) - 1;
408 
409     // nArrowLen ist bei bCenter bereits halbiert
410     // Bei 2 Pfeilen a 4mm ist unter 10mm Schluss.
411     nArrowNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2;
412     if (rPol.nLineLen<nArrowNeed) bPfeileAussen=sal_True;
413     nShortLen=(nArrow1Len+nArrow1Wdt + nArrow2Len+nArrow2Wdt) /2;
414 
415     rPol.eUsedTextHPos=rRec.eWantTextHPos;
416     rPol.eUsedTextVPos=rRec.eWantTextVPos;
417     if (rPol.eUsedTextVPos==SDRMEASURE_TEXTVAUTO) rPol.eUsedTextVPos=SDRMEASURE_ABOVE;
418     FASTBOOL bBrkLine=rPol.eUsedTextVPos==SDRMEASURETEXT_BREAKEDLINE;
419     if (rPol.eUsedTextVPos==SDRMEASURETEXT_VERTICALCENTERED)
420     {
421         OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject();
422         if (pOutlinerParaObject!=NULL && pOutlinerParaObject->GetTextObject().GetParagraphCount()==1)
423         {
424             bBrkLine=sal_True; // Unterbrochene Linie, wenn nur 1 Absatz.
425         }
426     }
427     rPol.bBreakedLine=bBrkLine;
428     if (rPol.eUsedTextHPos==SDRMEASURE_TEXTHAUTO) { // bei zu breitem Text diesen eventuell nach aussen schieben
429         FASTBOOL bOutside=sal_False;
430         long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height();
431         if (nNeedSiz>rPol.nLineLen) bOutside=sal_True; // Text passt nicht in die Mitte
432         if (bBrkLine) {
433             if (nNeedSiz+nArrowNeed>rPol.nLineLen) bPfeileAussen=sal_True; // Text passt in die Mitte, wenn die Pfeile nach aussen kommen
434         } else {
435             long nSmallNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2/4;
436             if (nNeedSiz+nSmallNeed>rPol.nLineLen) bPfeileAussen=sal_True; // Text passt in die Mitte, wenn die Pfeile nach aussen kommen
437         }
438         rPol.eUsedTextHPos=bOutside ? SDRMEASURE_TEXTLEFTOUTSIDE : SDRMEASURE_TEXTINSIDE;
439     }
440     if (rPol.eUsedTextHPos!=SDRMEASURE_TEXTINSIDE) bPfeileAussen=sal_True;
441     rPol.nArrow1Wdt=nArrow1Wdt;
442     rPol.nArrow2Wdt=nArrow2Wdt;
443     rPol.nShortLineLen=nShortLen;
444     rPol.bPfeileAussen=bPfeileAussen;
445     rPol.nArrow1Len=nArrow1Len;
446     rPol.bArrow1Center=bArrow1Center;
447     rPol.nArrow2Len=nArrow2Len;
448     rPol.bArrow2Center=bArrow2Center;
449 
450     rPol.nLineWink=GetAngle(aDelt);
451     double a=rPol.nLineWink*nPi180;
452     double nLineSin=sin(a);
453     double nLineCos=cos(a);
454     rPol.nLineSin=nLineSin;
455     rPol.nLineCos=nLineCos;
456 
457     rPol.nTextWink=rPol.nLineWink;
458     if (rRec.bTextRota90) rPol.nTextWink+=9000;
459 
460     rPol.bAutoUpsideDown=sal_False;
461     if (rRec.bTextAutoAngle) {
462         long nTmpWink=NormAngle360(rPol.nTextWink-rRec.nTextAutoAngleView);
463         if (nTmpWink>=18000) {
464             rPol.nTextWink+=18000;
465             rPol.bAutoUpsideDown=sal_True;
466         }
467     }
468 
469     if (rRec.bTextUpsideDown) rPol.nTextWink+=18000;
470     rPol.nTextWink=NormAngle360(rPol.nTextWink);
471     rPol.nHlpWink=rPol.nLineWink+9000;
472     if (rRec.bBelowRefEdge) rPol.nHlpWink+=18000;
473     rPol.nHlpWink=NormAngle360(rPol.nHlpWink);
474     double nHlpSin=nLineCos;
475     double nHlpCos=-nLineSin;
476     if (rRec.bBelowRefEdge) {
477         nHlpSin=-nHlpSin;
478         nHlpCos=-nHlpCos;
479     }
480     rPol.nHlpSin=nHlpSin;
481     rPol.nHlpCos=nHlpCos;
482 
483     long nLineDist=rRec.nLineDist;
484     long nOverhang=rRec.nHelplineOverhang;
485     long nHelplineDist=rRec.nHelplineDist;
486 
487     long dx= Round(nLineDist*nHlpCos);
488     long dy=-Round(nLineDist*nHlpSin);
489     long dxh1a= Round((nHelplineDist-rRec.nHelpline1Len)*nHlpCos);
490     long dyh1a=-Round((nHelplineDist-rRec.nHelpline1Len)*nHlpSin);
491     long dxh1b= Round((nHelplineDist-rRec.nHelpline2Len)*nHlpCos);
492     long dyh1b=-Round((nHelplineDist-rRec.nHelpline2Len)*nHlpSin);
493     long dxh2= Round((nLineDist+nOverhang)*nHlpCos);
494     long dyh2=-Round((nLineDist+nOverhang)*nHlpSin);
495 
496     // Masshilfslinie 1
497     rPol.aHelpline1.aP1=Point(aP1.X()+dxh1a,aP1.Y()+dyh1a);
498     rPol.aHelpline1.aP2=Point(aP1.X()+dxh2,aP1.Y()+dyh2);
499 
500     // Masshilfslinie 2
501     rPol.aHelpline2.aP1=Point(aP2.X()+dxh1b,aP2.Y()+dyh1b);
502     rPol.aHelpline2.aP2=Point(aP2.X()+dxh2,aP2.Y()+dyh2);
503 
504     // Masslinie(n)
505     Point aMainlinePt1(aP1.X()+dx,aP1.Y()+dy);
506     Point aMainlinePt2(aP2.X()+dx,aP2.Y()+dy);
507     if (!bPfeileAussen) {
508         rPol.aMainline1.aP1=aMainlinePt1;
509         rPol.aMainline1.aP2=aMainlinePt2;
510         rPol.aMainline2=rPol.aMainline1;
511         rPol.aMainline3=rPol.aMainline1;
512         rPol.nMainlineAnz=1;
513         if (bBrkLine) {
514             long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height();
515             long nHalfLen=(rPol.nLineLen-nNeedSiz-nArrow1Wdt/4-nArrow2Wdt/4) /2;
516             rPol.nMainlineAnz=2;
517             rPol.aMainline1.aP2=aMainlinePt1;
518             rPol.aMainline1.aP2.X()+=nHalfLen;
519             RotatePoint(rPol.aMainline1.aP2,rPol.aMainline1.aP1,nLineSin,nLineCos);
520             rPol.aMainline2.aP1=aMainlinePt2;
521             rPol.aMainline2.aP1.X()-=nHalfLen;
522             RotatePoint(rPol.aMainline2.aP1,rPol.aMainline2.aP2,nLineSin,nLineCos);
523         }
524     } else {
525         long nLen1=nShortLen; // Pfeilbreite als Linienlaenge ausserhalb des Pfeils
526         long nLen2=nShortLen;
527         long nTextWdt=rRec.bTextRota90 ? rPol.aTextSize.Height() : rPol.aTextSize.Width();
528         if (!bBrkLine) {
529             if (rPol.eUsedTextHPos==SDRMEASURE_TEXTLEFTOUTSIDE) nLen1=nArrow1Len+nTextWdt;
530             if (rPol.eUsedTextHPos==SDRMEASURE_TEXTRIGHTOUTSIDE) nLen2=nArrow2Len+nTextWdt;
531         }
532         rPol.aMainline1.aP1=aMainlinePt1;
533         rPol.aMainline1.aP2=aMainlinePt1; rPol.aMainline1.aP2.X()-=nLen1; RotatePoint(rPol.aMainline1.aP2,aMainlinePt1,nLineSin,nLineCos);
534         rPol.aMainline2.aP1=aMainlinePt2; rPol.aMainline2.aP1.X()+=nLen2; RotatePoint(rPol.aMainline2.aP1,aMainlinePt2,nLineSin,nLineCos);
535         rPol.aMainline2.aP2=aMainlinePt2;
536         rPol.aMainline3.aP1=aMainlinePt1;
537         rPol.aMainline3.aP2=aMainlinePt2;
538         rPol.nMainlineAnz=3;
539         if (bBrkLine && rPol.eUsedTextHPos==SDRMEASURE_TEXTINSIDE) rPol.nMainlineAnz=2;
540     }
541 }
542 
ImpCalcXPoly(const ImpMeasurePoly & rPol) const543 basegfx::B2DPolyPolygon SdrMeasureObj::ImpCalcXPoly(const ImpMeasurePoly& rPol) const
544 {
545     basegfx::B2DPolyPolygon aRetval;
546     basegfx::B2DPolygon aPartPolyA;
547     aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP1.X(), rPol.aMainline1.aP1.Y()));
548     aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP2.X(), rPol.aMainline1.aP2.Y()));
549     aRetval.append(aPartPolyA);
550 
551     if(rPol.nMainlineAnz > 1)
552     {
553         aPartPolyA.clear();
554         aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP1.X(), rPol.aMainline2.aP1.Y()));
555         aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP2.X(), rPol.aMainline2.aP2.Y()));
556         aRetval.append(aPartPolyA);
557     }
558 
559     if(rPol.nMainlineAnz > 2)
560     {
561         aPartPolyA.clear();
562         aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP1.X(), rPol.aMainline3.aP1.Y()));
563         aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP2.X(), rPol.aMainline3.aP2.Y()));
564         aRetval.append(aPartPolyA);
565     }
566 
567     aPartPolyA.clear();
568     aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP1.X(), rPol.aHelpline1.aP1.Y()));
569     aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP2.X(), rPol.aHelpline1.aP2.Y()));
570     aRetval.append(aPartPolyA);
571 
572     aPartPolyA.clear();
573     aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP1.X(), rPol.aHelpline2.aP1.Y()));
574     aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP2.X(), rPol.aHelpline2.aP2.Y()));
575     aRetval.append(aPartPolyA);
576 
577     return aRetval;
578 }
579 
CalcFieldValue(const SvxFieldItem & rField,sal_uInt16 nPara,sal_uInt16 nPos,FASTBOOL bEdit,Color * & rpTxtColor,Color * & rpFldColor,XubString & rRet) const580 FASTBOOL SdrMeasureObj::CalcFieldValue(const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos,
581     FASTBOOL bEdit,
582     Color*& rpTxtColor, Color*& rpFldColor, XubString& rRet) const
583 {
584     const SvxFieldData* pField=rField.GetField();
585     SdrMeasureField* pMeasureField=PTR_CAST(SdrMeasureField,pField);
586     if (pMeasureField!=NULL) {
587         TakeRepresentation(rRet, pMeasureField->GetMeasureFieldKind());
588         if (rpFldColor!=NULL) {
589             if (!bEdit)
590             {
591                 delete rpFldColor;
592                 rpFldColor=NULL;
593             }
594         }
595         return sal_True;
596     } else {
597         return SdrTextObj::CalcFieldValue(rField,nPara,nPos,bEdit,rpTxtColor,rpFldColor,rRet);
598     }
599 }
600 
UndirtyText() const601 void SdrMeasureObj::UndirtyText() const
602 {
603     if (bTextDirty)
604     {
605         SdrOutliner& rOutliner=ImpGetDrawOutliner();
606         OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject();
607         if(pOutlinerParaObject==NULL)
608         {
609             rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS), EE_FEATURE_FIELD), ESelection(0,0));
610             rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_VALUE), EE_FEATURE_FIELD),ESelection(0,1));
611             rOutliner.QuickInsertText(String(sal_Unicode(' ')), ESelection(0,2));
612             rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_UNIT), EE_FEATURE_FIELD),ESelection(0,3));
613             rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS), EE_FEATURE_FIELD),ESelection(0,4));
614 
615             if(GetStyleSheet())
616                 rOutliner.SetStyleSheet(0, GetStyleSheet());
617 
618             rOutliner.SetParaAttribs(0, GetObjectItemSet());
619 
620             // casting auf nonconst
621             const_cast<SdrMeasureObj*>(this)->NbcSetOutlinerParaObject( rOutliner.CreateParaObject() );
622         }
623         else
624         {
625             rOutliner.SetText(*pOutlinerParaObject);
626         }
627 
628         rOutliner.SetUpdateMode(sal_True);
629         rOutliner.UpdateFields();
630         Size aSiz(rOutliner.CalcTextSize());
631         rOutliner.Clear();
632         // 3x casting auf nonconst
633         ((SdrMeasureObj*)this)->aTextSize=aSiz;
634         ((SdrMeasureObj*)this)->bTextSizeDirty=sal_False;
635         ((SdrMeasureObj*)this)->bTextDirty=sal_False;
636     }
637 }
638 
TakeUnrotatedSnapRect(Rectangle & rRect) const639 void SdrMeasureObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
640 {
641     if (bTextDirty) UndirtyText();
642     ImpMeasureRec aRec;
643     ImpMeasurePoly aMPol;
644     ImpTakeAttr(aRec);
645     ImpCalcGeometrics(aRec,aMPol);
646 
647     // TextSize ermitteln inkl. Textrahmenabstaende
648     Size aTextSize2(aMPol.aTextSize);
649     if (aTextSize2.Width()<1) aTextSize2.Width()=1;
650     if (aTextSize2.Height()<1) aTextSize2.Height()=1;
651     aTextSize2.Width()+=GetTextLeftDistance()+GetTextRightDistance();
652     aTextSize2.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
653 
654     Point aPt1b(aMPol.aMainline1.aP1);
655     long nLen=aMPol.nLineLen;
656     long nLWdt=aMPol.nLineWdt2;
657     long nArr1Len=aMPol.nArrow1Len;
658     long nArr2Len=aMPol.nArrow2Len;
659     if (aMPol.bBreakedLine) {
660         // Bei Unterbrochener Linie und Outside muss der Text nicht neben den
661         // Pfeil sondern neben die Linie an dem Pfeil plaziert werden
662         nArr1Len=aMPol.nShortLineLen+aMPol.nArrow1Wdt/4;
663         nArr2Len=aMPol.nShortLineLen+aMPol.nArrow2Wdt/4;
664     }
665 
666     Point aTextPos;
667     FASTBOOL bRota90=aRec.bTextRota90;
668     FASTBOOL bUpsideDown=aRec.bTextUpsideDown!=aMPol.bAutoUpsideDown;
669     FASTBOOL bBelowRefEdge=aRec.bBelowRefEdge;
670     SdrMeasureTextHPos eMH=aMPol.eUsedTextHPos;
671     SdrMeasureTextVPos eMV=aMPol.eUsedTextVPos;
672     if (!bRota90) {
673         switch (eMH) {
674             case SDRMEASURE_TEXTLEFTOUTSIDE: aTextPos.X()=aPt1b.X()-aTextSize2.Width()-nArr1Len-nLWdt; break;
675             case SDRMEASURE_TEXTRIGHTOUTSIDE: aTextPos.X()=aPt1b.X()+nLen+nArr2Len+nLWdt; break;
676             default: aTextPos.X()=aPt1b.X(); aTextSize2.Width()=nLen;
677         }
678         switch (eMV) {
679             case SDRMEASURETEXT_VERTICALCENTERED:
680             case SDRMEASURETEXT_BREAKEDLINE: aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()/2; break;
681             case SDRMEASURE_BELOW: {
682                 if (!bUpsideDown) aTextPos.Y()=aPt1b.Y()+nLWdt;
683                 else aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()-nLWdt;
684             } break;
685             default: {
686                 if (!bUpsideDown) aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()-nLWdt;
687                 else aTextPos.Y()=aPt1b.Y()+nLWdt;
688             }
689         }
690         if (bUpsideDown) {
691             aTextPos.X()+=aTextSize2.Width();
692             aTextPos.Y()+=aTextSize2.Height();
693         }
694     } else { // also wenn bTextRota90==TRUE
695         switch (eMH) {
696             case SDRMEASURE_TEXTLEFTOUTSIDE: aTextPos.X()=aPt1b.X()-aTextSize2.Height()-nArr1Len; break;
697             case SDRMEASURE_TEXTRIGHTOUTSIDE: aTextPos.X()=aPt1b.X()+nLen+nArr2Len; break;
698             default: aTextPos.X()=aPt1b.X(); aTextSize2.Height()=nLen;
699         }
700         switch (eMV) {
701             case SDRMEASURETEXT_VERTICALCENTERED:
702             case SDRMEASURETEXT_BREAKEDLINE: aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()/2; break;
703             case SDRMEASURE_BELOW: {
704                 if (!bBelowRefEdge) aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()+nLWdt;
705                 else aTextPos.Y()=aPt1b.Y()-nLWdt;
706             } break;
707             default: {
708                 if (!bBelowRefEdge) aTextPos.Y()=aPt1b.Y()-nLWdt;
709                 else aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()+nLWdt;
710             }
711         }
712         if (bUpsideDown) {
713             aTextPos.X()+=aTextSize2.Height();
714             aTextPos.Y()-=aTextSize2.Width();
715         }
716     }
717     if (aMPol.nTextWink!=aGeo.nDrehWink) {
718         ((SdrMeasureObj*)this)->aGeo.nDrehWink=aMPol.nTextWink;
719         ((SdrMeasureObj*)this)->aGeo.RecalcSinCos();
720     }
721     RotatePoint(aTextPos,aPt1b,aMPol.nLineSin,aMPol.nLineCos);
722     aTextSize2.Width()++; aTextSize2.Height()++; // wg. des komischen Verhaltens beim Rect-Ctor
723     rRect=Rectangle(aTextPos,aTextSize2);
724     rRect.Justify();
725     ((SdrMeasureObj*)this)->aRect=rRect;
726 
727     if (aMPol.nTextWink!=aGeo.nDrehWink) {
728         ((SdrMeasureObj*)this)->aGeo.nDrehWink=aMPol.nTextWink;
729         ((SdrMeasureObj*)this)->aGeo.RecalcSinCos();
730     }
731 }
732 
operator =(const SdrObject & rObj)733 void SdrMeasureObj::operator=(const SdrObject& rObj)
734 {
735     SdrTextObj::operator=(rObj);
736     aPt1=((SdrMeasureObj&)rObj).aPt1;
737     aPt2=((SdrMeasureObj&)rObj).aPt2;
738     bTextDirty=((SdrMeasureObj&)rObj).bTextDirty;
739 }
740 
TakeObjNameSingul(XubString & rName) const741 void SdrMeasureObj::TakeObjNameSingul(XubString& rName) const
742 {
743     rName=ImpGetResStr(STR_ObjNameSingulMEASURE);
744 
745     String aName( GetName() );
746     if(aName.Len())
747     {
748         rName += sal_Unicode(' ');
749         rName += sal_Unicode('\'');
750         rName += aName;
751         rName += sal_Unicode('\'');
752     }
753 }
754 
TakeObjNamePlural(XubString & rName) const755 void SdrMeasureObj::TakeObjNamePlural(XubString& rName) const
756 {
757     rName=ImpGetResStr(STR_ObjNamePluralMEASURE);
758 }
759 
TakeXorPoly() const760 basegfx::B2DPolyPolygon SdrMeasureObj::TakeXorPoly() const
761 {
762     ImpMeasureRec aRec;
763     ImpMeasurePoly aMPol;
764     ImpTakeAttr(aRec);
765     ImpCalcGeometrics(aRec,aMPol);
766     return ImpCalcXPoly(aMPol);
767 }
768 
GetHdlCount() const769 sal_uInt32 SdrMeasureObj::GetHdlCount() const
770 {
771     return 6L;
772 }
773 
GetHdl(sal_uInt32 nHdlNum) const774 SdrHdl* SdrMeasureObj::GetHdl(sal_uInt32 nHdlNum) const
775 {
776     ImpMeasureRec aRec;
777     ImpMeasurePoly aMPol;
778     ImpTakeAttr(aRec);
779     aRec.nHelplineDist=0;
780     ImpCalcGeometrics(aRec,aMPol);
781     Point aPt;
782     //SdrHdlKind eHdl=HDL_POLY;
783     switch (nHdlNum) {
784         case 0: aPt=aMPol.aHelpline1.aP1; break;
785         case 1: aPt=aMPol.aHelpline2.aP1; break;
786         case 2: aPt=aPt1;       break;
787         case 3: aPt=aPt2;       break;
788         case 4: aPt=aMPol.aHelpline1.aP2; break;
789         case 5: aPt=aMPol.aHelpline2.aP2; break;
790     } // switch
791     SdrHdl* pHdl=new ImpMeasureHdl(aPt,HDL_USER);
792     pHdl->SetObjHdlNum(nHdlNum);
793     pHdl->SetDrehWink(aMPol.nLineWink);
794     return pHdl;
795 }
796 
797 ////////////////////////////////////////////////////////////////////////////////////////////////////
798 
hasSpecialDrag() const799 bool SdrMeasureObj::hasSpecialDrag() const
800 {
801     return true;
802 }
803 
beginSpecialDrag(SdrDragStat & rDrag) const804 bool SdrMeasureObj::beginSpecialDrag(SdrDragStat& rDrag) const
805 {
806     const SdrHdl* pHdl = rDrag.GetHdl();
807 
808     if(pHdl)
809     {
810         const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
811 
812         if(nHdlNum != 2 && nHdlNum != 3)
813         {
814             rDrag.SetEndDragChangesAttributes(true);
815         }
816 
817         return true;
818     }
819 
820     return false;
821 }
822 
applySpecialDrag(SdrDragStat & rDrag)823 bool SdrMeasureObj::applySpecialDrag(SdrDragStat& rDrag)
824 {
825     ImpMeasureRec aMeasureRec;
826     const SdrHdl* pHdl = rDrag.GetHdl();
827     const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
828 
829     ImpTakeAttr(aMeasureRec);
830     ImpEvalDrag(aMeasureRec, rDrag);
831 
832     switch (nHdlNum)
833     {
834         case 2:
835         {
836             aPt1 = aMeasureRec.aPt1;
837             SetTextDirty();
838             break;
839         }
840         case 3:
841         {
842             aPt2 = aMeasureRec.aPt2;
843             SetTextDirty();
844             break;
845         }
846         default:
847         {
848             switch(nHdlNum)
849             {
850                 case 0:
851                 case 1:
852                 {
853                     ImpMeasureRec aOrigMeasureRec;
854                     ImpTakeAttr(aOrigMeasureRec);
855 
856                     if(aMeasureRec.nHelpline1Len != aOrigMeasureRec.nHelpline1Len)
857                     {
858                         SetObjectItem(SdrMeasureHelpline1LenItem(aMeasureRec.nHelpline1Len));
859                     }
860 
861                     if(aMeasureRec.nHelpline2Len != aOrigMeasureRec.nHelpline2Len)
862                     {
863                         SetObjectItem(SdrMeasureHelpline2LenItem(aMeasureRec.nHelpline2Len));
864                     }
865 
866                     break;
867                 }
868 
869                 case 4:
870                 case 5:
871                 {
872                     ImpMeasureRec aOrigMeasureRec;
873                     ImpTakeAttr(aOrigMeasureRec);
874 
875                     if(aMeasureRec.nLineDist != aOrigMeasureRec.nLineDist)
876                     {
877                         SetObjectItem(SdrMeasureLineDistItem(aMeasureRec.nLineDist));
878                     }
879 
880                     if(aMeasureRec.bBelowRefEdge != aOrigMeasureRec.bBelowRefEdge)
881                     {
882                         SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec.bBelowRefEdge));
883                     }
884                 }
885             }
886         }
887     } // switch
888 
889     SetRectsDirty();
890     SetChanged();
891 
892     return true;
893 }
894 
getSpecialDragComment(const SdrDragStat &) const895 String SdrMeasureObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const
896 {
897     XubString aStr;
898     return aStr;
899 }
900 
ImpEvalDrag(ImpMeasureRec & rRec,const SdrDragStat & rDrag) const901 void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec& rRec, const SdrDragStat& rDrag) const
902 {
903     long nLineWink=GetAngle(rRec.aPt2-rRec.aPt1);
904     double a=nLineWink*nPi180;
905     double nSin=sin(a);
906     double nCos=cos(a);
907 
908     const SdrHdl* pHdl=rDrag.GetHdl();
909     sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
910     FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho();
911     FASTBOOL bBigOrtho=bOrtho && rDrag.GetView()->IsBigOrtho();
912     FASTBOOL bBelow=rRec.bBelowRefEdge;
913     Point aPt(rDrag.GetNow());
914 
915     switch (nHdlNum) {
916         case 0: {
917             RotatePoint(aPt,aPt1,nSin,-nCos);
918             rRec.nHelpline1Len=aPt1.Y()-aPt.Y();
919             if (bBelow) rRec.nHelpline1Len=-rRec.nHelpline1Len;
920             if (bOrtho) rRec.nHelpline2Len=rRec.nHelpline1Len;
921         } break;
922         case 1: {
923             RotatePoint(aPt,aPt2,nSin,-nCos);
924             rRec.nHelpline2Len=aPt2.Y()-aPt.Y();
925             if (bBelow) rRec.nHelpline2Len=-rRec.nHelpline2Len;
926             if (bOrtho) rRec.nHelpline1Len=rRec.nHelpline2Len;
927         } break;
928         case 2: case 3: {
929             FASTBOOL bAnf=nHdlNum==2;
930             Point& rMov=bAnf ? rRec.aPt1 : rRec.aPt2;
931             Point aMov(rMov);
932             Point aFix(bAnf ? rRec.aPt2 : rRec.aPt1);
933             if (bOrtho) {
934                 long ndx0=aMov.X()-aFix.X();
935                 long ndy0=aMov.Y()-aFix.Y();
936                 FASTBOOL bHLin=ndy0==0;
937                 FASTBOOL bVLin=ndx0==0;
938                 if (!bHLin || !bVLin) { // sonst ist aPt1==aPt2
939                     long ndx=aPt.X()-aFix.X();
940                     long ndy=aPt.Y()-aFix.Y();
941                     double nXFact=0; if (!bVLin) nXFact=(double)ndx/(double)ndx0;
942                     double nYFact=0; if (!bHLin) nYFact=(double)ndy/(double)ndy0;
943                     FASTBOOL bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho);
944                     FASTBOOL bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho);
945                     if (bHor) ndy=long(ndy0*nXFact);
946                     if (bVer) ndx=long(ndx0*nYFact);
947                     aPt=aFix;
948                     aPt.X()+=ndx;
949                     aPt.Y()+=ndy;
950                 } // else Ortho8
951             }
952             rMov=aPt;
953         } break;
954         case 4: case 5: {
955             long nVal0=rRec.nLineDist;
956             RotatePoint(aPt,(nHdlNum==4 ? aPt1 : aPt2),nSin,-nCos);
957             rRec.nLineDist=aPt.Y()- (nHdlNum==4 ? aPt1.Y() : aPt2.Y());
958             if (bBelow) rRec.nLineDist=-rRec.nLineDist;
959             if (rRec.nLineDist<0) {
960                 rRec.nLineDist=-rRec.nLineDist;
961                 rRec.bBelowRefEdge=!bBelow;
962             }
963             rRec.nLineDist-=rRec.nHelplineOverhang;
964             if (bOrtho) rRec.nLineDist=nVal0;
965         } break;
966     } // switch
967 }
968 
969 ////////////////////////////////////////////////////////////////////////////////////////////////////
970 
BegCreate(SdrDragStat & rStat)971 FASTBOOL SdrMeasureObj::BegCreate(SdrDragStat& rStat)
972 {
973     rStat.SetOrtho8Possible();
974     aPt1=rStat.GetStart();
975     aPt2=rStat.GetNow();
976     SetTextDirty();
977     return sal_True;
978 }
979 
MovCreate(SdrDragStat & rStat)980 FASTBOOL SdrMeasureObj::MovCreate(SdrDragStat& rStat)
981 {
982     SdrView* pView=rStat.GetView();
983     aPt1=rStat.GetStart();
984     aPt2=rStat.GetNow();
985     if (pView!=NULL && pView->IsCreate1stPointAsCenter()) {
986         aPt1+=aPt1;
987         aPt1-=rStat.Now();
988     }
989     SetTextDirty();
990     SetBoundRectDirty();
991     bSnapRectDirty=sal_True;
992     return sal_True;
993 }
994 
EndCreate(SdrDragStat & rStat,SdrCreateCmd eCmd)995 FASTBOOL SdrMeasureObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
996 {
997     SetTextDirty();
998     SetRectsDirty();
999     return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
1000 }
1001 
BckCreate(SdrDragStat &)1002 FASTBOOL SdrMeasureObj::BckCreate(SdrDragStat& /*rStat*/)
1003 {
1004     return sal_False;
1005 }
1006 
BrkCreate(SdrDragStat &)1007 void SdrMeasureObj::BrkCreate(SdrDragStat& /*rStat*/)
1008 {
1009 }
1010 
TakeCreatePoly(const SdrDragStat &) const1011 basegfx::B2DPolyPolygon SdrMeasureObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
1012 {
1013     ImpMeasureRec aRec;
1014     ImpMeasurePoly aMPol;
1015 
1016     ImpTakeAttr(aRec);
1017     ImpCalcGeometrics(aRec, aMPol);
1018 
1019     return ImpCalcXPoly(aMPol);
1020 }
1021 
GetCreatePointer() const1022 Pointer SdrMeasureObj::GetCreatePointer() const
1023 {
1024     return Pointer(POINTER_CROSS);
1025 }
1026 
NbcMove(const Size & rSiz)1027 void SdrMeasureObj::NbcMove(const Size& rSiz)
1028 {
1029     SdrTextObj::NbcMove(rSiz);
1030     MovePoint(aPt1,rSiz);
1031     MovePoint(aPt2,rSiz);
1032 }
1033 
NbcResize(const Point & rRef,const Fraction & xFact,const Fraction & yFact)1034 void SdrMeasureObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
1035 {
1036     SdrTextObj::NbcResize(rRef,xFact,yFact);
1037     ResizePoint(aPt1,rRef,xFact,yFact);
1038     ResizePoint(aPt2,rRef,xFact,yFact);
1039     SetTextDirty();
1040 }
1041 
NbcRotate(const Point & rRef,long nWink,double sn,double cs)1042 void SdrMeasureObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
1043 {
1044     SdrTextObj::NbcRotate(rRef,nWink,sn,cs);
1045     long nLen0=GetLen(aPt2-aPt1);
1046     RotatePoint(aPt1,rRef,sn,cs);
1047     RotatePoint(aPt2,rRef,sn,cs);
1048     long nLen1=GetLen(aPt2-aPt1);
1049     if (nLen1!=nLen0) { // Aha, Rundungsfehler
1050         long dx=aPt2.X()-aPt1.X();
1051         long dy=aPt2.Y()-aPt1.Y();
1052         dx=BigMulDiv(dx,nLen0,nLen1);
1053         dy=BigMulDiv(dy,nLen0,nLen1);
1054         if (rRef==aPt2) {
1055             aPt1.X()=aPt2.X()-dx;
1056             aPt1.Y()=aPt2.Y()-dy;
1057         } else {
1058             aPt2.X()=aPt1.X()+dx;
1059             aPt2.Y()=aPt1.Y()+dy;
1060         }
1061     }
1062     SetRectsDirty();
1063 }
1064 
NbcMirror(const Point & rRef1,const Point & rRef2)1065 void SdrMeasureObj::NbcMirror(const Point& rRef1, const Point& rRef2)
1066 {
1067     SdrTextObj::NbcMirror(rRef1,rRef2);
1068     MirrorPoint(aPt1,rRef1,rRef2);
1069     MirrorPoint(aPt2,rRef1,rRef2);
1070     SetRectsDirty();
1071 }
1072 
NbcShear(const Point & rRef,long nWink,double tn,FASTBOOL bVShear)1073 void SdrMeasureObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
1074 {
1075     SdrTextObj::NbcShear(rRef,nWink,tn,bVShear);
1076     ShearPoint(aPt1,rRef,tn,bVShear);
1077     ShearPoint(aPt2,rRef,tn,bVShear);
1078     SetRectsDirty();
1079     SetTextDirty();
1080 }
1081 
GetRotateAngle() const1082 long SdrMeasureObj::GetRotateAngle() const
1083 {
1084     return GetAngle(aPt2-aPt1);
1085 }
1086 
RecalcSnapRect()1087 void SdrMeasureObj::RecalcSnapRect()
1088 {
1089     // #94520# Added correct implementation here.
1090     ImpMeasureRec aRec;
1091     ImpMeasurePoly aMPol;
1092     XPolyPolygon aXPP;
1093 
1094     ImpTakeAttr(aRec);
1095     ImpCalcGeometrics(aRec, aMPol);
1096     aXPP = XPolyPolygon(ImpCalcXPoly(aMPol));
1097     maSnapRect = aXPP.GetBoundRect();
1098 }
1099 
GetSnapPointCount() const1100 sal_uInt32 SdrMeasureObj::GetSnapPointCount() const
1101 {
1102     return 2L;
1103 }
1104 
GetSnapPoint(sal_uInt32 i) const1105 Point SdrMeasureObj::GetSnapPoint(sal_uInt32 i) const
1106 {
1107     if (i==0) return aPt1;
1108     else return aPt2;
1109 }
1110 
IsPolyObj() const1111 sal_Bool SdrMeasureObj::IsPolyObj() const
1112 {
1113     return sal_True;
1114 }
1115 
GetPointCount() const1116 sal_uInt32 SdrMeasureObj::GetPointCount() const
1117 {
1118     return 2L;
1119 }
1120 
GetPoint(sal_uInt32 i) const1121 Point SdrMeasureObj::GetPoint(sal_uInt32 i) const
1122 {
1123      return (0L == i) ? aPt1 : aPt2;
1124 }
1125 
NbcSetPoint(const Point & rPnt,sal_uInt32 i)1126 void SdrMeasureObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
1127 {
1128     if (0L == i)
1129         aPt1=rPnt;
1130     if (1L == i)
1131         aPt2=rPnt;
1132     SetRectsDirty();
1133     SetTextDirty();
1134 }
1135 
NewGeoData() const1136 SdrObjGeoData* SdrMeasureObj::NewGeoData() const
1137 {
1138     return new SdrMeasureObjGeoData;
1139 }
1140 
SaveGeoData(SdrObjGeoData & rGeo) const1141 void SdrMeasureObj::SaveGeoData(SdrObjGeoData& rGeo) const
1142 {
1143     SdrTextObj::SaveGeoData(rGeo);
1144     SdrMeasureObjGeoData& rMGeo=(SdrMeasureObjGeoData&)rGeo;
1145     rMGeo.aPt1=aPt1;
1146     rMGeo.aPt2=aPt2;
1147 }
1148 
RestGeoData(const SdrObjGeoData & rGeo)1149 void SdrMeasureObj::RestGeoData(const SdrObjGeoData& rGeo)
1150 {
1151     SdrTextObj::RestGeoData(rGeo);
1152     SdrMeasureObjGeoData& rMGeo=(SdrMeasureObjGeoData&)rGeo;
1153     aPt1=rMGeo.aPt1;
1154     aPt2=rMGeo.aPt2;
1155     SetTextDirty();
1156 }
1157 
DoConvertToPolyObj(sal_Bool bBezier,bool bAddText) const1158 SdrObject* SdrMeasureObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const
1159 {
1160     // get XOR Poly as base
1161     XPolyPolygon aTmpPolyPolygon(TakeXorPoly());
1162 
1163     // get local ItemSet and StyleSheet
1164     SfxItemSet aSet(GetObjectItemSet());
1165     SfxStyleSheet* pStyleSheet = GetStyleSheet();
1166 
1167     // prepare group
1168     SdrObjGroup* pGroup = new SdrObjGroup;
1169     pGroup->SetModel(GetModel());
1170 
1171     // prepare parameters
1172     basegfx::B2DPolyPolygon aPolyPoly;
1173     SdrPathObj* pPath;
1174     sal_uInt16 nCount(aTmpPolyPolygon.Count());
1175     sal_uInt16 nLoopStart(0);
1176 
1177     if(nCount == 3)
1178     {
1179         // three lines, first one is the middle one
1180         aPolyPoly.clear();
1181         aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon());
1182 
1183         pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly);
1184         pPath->SetModel(GetModel());
1185         pPath->SetMergedItemSet(aSet);
1186         pPath->SetStyleSheet(pStyleSheet, true);
1187         pGroup->GetSubList()->NbcInsertObject(pPath);
1188         aSet.Put(XLineStartWidthItem(0L));
1189         aSet.Put(XLineEndWidthItem(0L));
1190         nLoopStart = 1;
1191     }
1192     else if(nCount == 4)
1193     {
1194         // four lines, middle line with gap, so there are two lines used
1195         // which have one arrow each
1196         //sal_Int32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
1197         sal_Int32 nEndWidth = ((const XLineEndWidthItem&)(aSet.Get(XATTR_LINEENDWIDTH))).GetValue();
1198         aSet.Put(XLineEndWidthItem(0L));
1199 
1200         aPolyPoly.clear();
1201         aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon());
1202         pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly);
1203         pPath->SetModel(GetModel());
1204         pPath->SetMergedItemSet(aSet);
1205         pPath->SetStyleSheet(pStyleSheet, true);
1206 
1207         pGroup->GetSubList()->NbcInsertObject(pPath);
1208 
1209         aSet.Put(XLineEndWidthItem(nEndWidth));
1210         aSet.Put(XLineStartWidthItem(0L));
1211 
1212         aPolyPoly.clear();
1213         aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon());
1214         pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly);
1215         pPath->SetModel(GetModel());
1216         pPath->SetMergedItemSet(aSet);
1217         pPath->SetStyleSheet(pStyleSheet, true);
1218 
1219         pGroup->GetSubList()->NbcInsertObject(pPath);
1220 
1221         aSet.Put(XLineEndWidthItem(0L));
1222         nLoopStart = 2;
1223     }
1224     else if(nCount == 5)
1225     {
1226         // five lines, first two are the outer ones
1227         //sal_Int32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
1228         sal_Int32 nEndWidth = ((const XLineEndWidthItem&)(aSet.Get(XATTR_LINEENDWIDTH))).GetValue();
1229 
1230         aSet.Put(XLineEndWidthItem(0L));
1231 
1232         aPolyPoly.clear();
1233         aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon());
1234         pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly);
1235         pPath->SetModel(GetModel());
1236         pPath->SetMergedItemSet(aSet);
1237         pPath->SetStyleSheet(pStyleSheet, true);
1238 
1239         pGroup->GetSubList()->NbcInsertObject(pPath);
1240 
1241         aSet.Put(XLineEndWidthItem(nEndWidth));
1242         aSet.Put(XLineStartWidthItem(0L));
1243 
1244         aPolyPoly.clear();
1245         aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon());
1246         pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly);
1247         pPath->SetModel(GetModel());
1248         pPath->SetMergedItemSet(aSet);
1249         pPath->SetStyleSheet(pStyleSheet, true);
1250 
1251         pGroup->GetSubList()->NbcInsertObject(pPath);
1252 
1253         aSet.Put(XLineEndWidthItem(0L));
1254         nLoopStart = 2;
1255     }
1256 
1257     for(;nLoopStart<nCount;nLoopStart++)
1258     {
1259         aPolyPoly.clear();
1260         aPolyPoly.append(aTmpPolyPolygon[nLoopStart].getB2DPolygon());
1261         pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly);
1262         pPath->SetModel(GetModel());
1263         pPath->SetMergedItemSet(aSet);
1264         pPath->SetStyleSheet(pStyleSheet, true);
1265 
1266         pGroup->GetSubList()->NbcInsertObject(pPath);
1267     }
1268 
1269     if(bAddText)
1270     {
1271         return ImpConvertAddText(pGroup, bBezier);
1272     }
1273     else
1274     {
1275         return pGroup;
1276     }
1277 }
1278 
BegTextEdit(SdrOutliner & rOutl)1279 sal_Bool SdrMeasureObj::BegTextEdit(SdrOutliner& rOutl)
1280 {
1281     UndirtyText();
1282     return SdrTextObj::BegTextEdit(rOutl);
1283 }
1284 
GetTextSize() const1285 const Size& SdrMeasureObj::GetTextSize() const
1286 {
1287     if (bTextDirty) UndirtyText();
1288     return SdrTextObj::GetTextSize();
1289 }
1290 
GetOutlinerParaObject() const1291 OutlinerParaObject* SdrMeasureObj::GetOutlinerParaObject() const
1292 {
1293     if(bTextDirty)
1294         UndirtyText();
1295     return SdrTextObj::GetOutlinerParaObject();
1296 }
1297 
NbcSetOutlinerParaObject(OutlinerParaObject * pTextObject)1298 void SdrMeasureObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
1299 {
1300     SdrTextObj::NbcSetOutlinerParaObject(pTextObject);
1301     if(SdrTextObj::GetOutlinerParaObject())
1302         SetTextDirty(); // Text neu berechnen!
1303 }
1304 
TakeTextRect(SdrOutliner & rOutliner,Rectangle & rTextRect,FASTBOOL bNoEditText,Rectangle * pAnchorRect,sal_Bool bLineWidth) const1305 void SdrMeasureObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText,
1306     Rectangle* pAnchorRect, sal_Bool bLineWidth ) const
1307 {
1308     if (bTextDirty) UndirtyText();
1309     SdrTextObj::TakeTextRect( rOutliner, rTextRect, bNoEditText, pAnchorRect, bLineWidth );
1310 }
1311 
TakeTextAnchorRect(Rectangle & rAnchorRect) const1312 void SdrMeasureObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const
1313 {
1314     if (bTextDirty) UndirtyText();
1315     SdrTextObj::TakeTextAnchorRect(rAnchorRect);
1316 }
1317 
TakeTextEditArea(Size * pPaperMin,Size * pPaperMax,Rectangle * pViewInit,Rectangle * pViewMin) const1318 void SdrMeasureObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const
1319 {
1320     if (bTextDirty) UndirtyText();
1321     SdrTextObj::TakeTextEditArea(pPaperMin,pPaperMax,pViewInit,pViewMin);
1322 }
1323 
GetOutlinerViewAnchorMode() const1324 sal_uInt16 SdrMeasureObj::GetOutlinerViewAnchorMode() const
1325 {
1326     if (bTextDirty) UndirtyText();
1327     ImpMeasureRec aRec;
1328     ImpMeasurePoly aMPol;
1329     ImpTakeAttr(aRec);
1330     ImpCalcGeometrics(aRec,aMPol);
1331 
1332     SdrTextHorzAdjust eTH=GetTextHorizontalAdjust();
1333     SdrTextVertAdjust eTV=GetTextVerticalAdjust();
1334     SdrMeasureTextHPos eMH=aMPol.eUsedTextHPos;
1335     SdrMeasureTextVPos eMV=aMPol.eUsedTextVPos;
1336     FASTBOOL bTextRota90=aRec.bTextRota90;
1337     //int bTextUpsideDown=aRec.bTextUpsideDown;
1338     FASTBOOL bBelowRefEdge=aRec.bBelowRefEdge;
1339 
1340     // bTextUpsideDown muss hier noch ausgewertet werden!!!!
1341     if (!bTextRota90) {
1342         if (eMH==SDRMEASURE_TEXTLEFTOUTSIDE) eTH=SDRTEXTHORZADJUST_RIGHT;
1343         if (eMH==SDRMEASURE_TEXTRIGHTOUTSIDE) eTH=SDRTEXTHORZADJUST_LEFT;
1344         // bei eMH==SDRMEASURE_TEXTINSIDE kann horizontal geankert werden.
1345         if (eMV==SDRMEASURE_ABOVE) eTV=SDRTEXTVERTADJUST_BOTTOM;
1346         if (eMV==SDRMEASURE_BELOW) eTV=SDRTEXTVERTADJUST_TOP;
1347         if (eMV==SDRMEASURETEXT_BREAKEDLINE || eMV==SDRMEASURETEXT_VERTICALCENTERED) eTV=SDRTEXTVERTADJUST_CENTER;
1348     } else {
1349         if (eMH==SDRMEASURE_TEXTLEFTOUTSIDE) eTV=SDRTEXTVERTADJUST_BOTTOM;
1350         if (eMH==SDRMEASURE_TEXTRIGHTOUTSIDE) eTV=SDRTEXTVERTADJUST_TOP;
1351         // bei eMH==SDRMEASURE_TEXTINSIDE kann vertikal geankert werden.
1352         if (!bBelowRefEdge) {
1353             if (eMV==SDRMEASURE_ABOVE) eTH=SDRTEXTHORZADJUST_LEFT;
1354             if (eMV==SDRMEASURE_BELOW) eTH=SDRTEXTHORZADJUST_RIGHT;
1355         } else {
1356             if (eMV==SDRMEASURE_ABOVE) eTH=SDRTEXTHORZADJUST_RIGHT;
1357             if (eMV==SDRMEASURE_BELOW) eTH=SDRTEXTHORZADJUST_LEFT;
1358         }
1359         if (eMV==SDRMEASURETEXT_BREAKEDLINE || eMV==SDRMEASURETEXT_VERTICALCENTERED) eTH=SDRTEXTHORZADJUST_CENTER;
1360     }
1361 
1362     EVAnchorMode eRet=ANCHOR_BOTTOM_HCENTER;
1363     if (eTH==SDRTEXTHORZADJUST_LEFT) {
1364         if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_LEFT;
1365         else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_LEFT;
1366         else eRet=ANCHOR_VCENTER_LEFT;
1367     } else if (eTH==SDRTEXTHORZADJUST_RIGHT) {
1368         if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_RIGHT;
1369         else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_RIGHT;
1370         else eRet=ANCHOR_VCENTER_RIGHT;
1371     } else {
1372         if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_HCENTER;
1373         else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_HCENTER;
1374         else eRet=ANCHOR_VCENTER_HCENTER;
1375     }
1376     return (sal_uInt16)eRet;
1377 }
1378 
1379 //////////////////////////////////////////////////////////////////////////////
1380 // #i97878#
1381 // TRGetBaseGeometry/TRSetBaseGeometry needs to be based on two positions,
1382 // same as line geometry in SdrPathObj. Thus needs to be overloaded and
1383 // implemented since currently it is derived from SdrTextObj which uses
1384 // a functionality based on SnapRect which is not useful here
1385 
ImplTwipsToMM(double fVal)1386 inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); }
ImplMMToTwips(double fVal)1387 inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); }
1388 
TRGetBaseGeometry(basegfx::B2DHomMatrix & rMatrix,basegfx::B2DPolyPolygon &) const1389 sal_Bool SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
1390 {
1391     // handle the same as a simple line since the definition is based on two points
1392     const basegfx::B2DRange aRange(aPt1.X(), aPt1.Y(), aPt2.X(), aPt2.Y());
1393     basegfx::B2DTuple aScale(aRange.getRange());
1394     basegfx::B2DTuple aTranslate(aRange.getMinimum());
1395 
1396     // position maybe relative to anchorpos, convert
1397     if( pModel->IsWriter() )
1398     {
1399         if(GetAnchorPos().X() || GetAnchorPos().Y())
1400         {
1401             aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1402         }
1403     }
1404 
1405     // force MapUnit to 100th mm
1406     SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0);
1407     if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1408     {
1409         switch(eMapUnit)
1410         {
1411             case SFX_MAPUNIT_TWIP :
1412             {
1413                 // postion
1414                 aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
1415                 aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
1416 
1417                 // size
1418                 aScale.setX(ImplTwipsToMM(aScale.getX()));
1419                 aScale.setY(ImplTwipsToMM(aScale.getY()));
1420 
1421                 break;
1422             }
1423             default:
1424             {
1425                 DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1426             }
1427         }
1428     }
1429 
1430     // build return value matrix
1431     rMatrix = basegfx::tools::createScaleTranslateB2DHomMatrix(aScale, aTranslate);
1432 
1433     return sal_True;
1434 }
1435 
TRSetBaseGeometry(const basegfx::B2DHomMatrix & rMatrix,const basegfx::B2DPolyPolygon &)1436 void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
1437 {
1438     // use given transformation to derive the two defining points from unit line
1439     basegfx::B2DPoint aPosA(rMatrix * basegfx::B2DPoint(0.0, 0.0));
1440     basegfx::B2DPoint aPosB(rMatrix * basegfx::B2DPoint(1.0, 0.0));
1441 
1442     // force metric to pool metric
1443     SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0);
1444     if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1445     {
1446         switch(eMapUnit)
1447         {
1448             case SFX_MAPUNIT_TWIP :
1449             {
1450                 // position
1451                 aPosA.setX(ImplMMToTwips(aPosA.getX()));
1452                 aPosA.setY(ImplMMToTwips(aPosA.getY()));
1453                 aPosB.setX(ImplMMToTwips(aPosB.getX()));
1454                 aPosB.setY(ImplMMToTwips(aPosB.getY()));
1455 
1456                 break;
1457             }
1458             default:
1459             {
1460                 DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1461             }
1462         }
1463     }
1464 
1465     if( pModel->IsWriter() )
1466     {
1467         // if anchor is used, make position relative to it
1468         if(GetAnchorPos().X() || GetAnchorPos().Y())
1469         {
1470             const basegfx::B2DVector aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y());
1471 
1472             aPosA += aAnchorOffset;
1473             aPosB += aAnchorOffset;
1474         }
1475     }
1476 
1477     // derive new model data
1478     const Point aNewPt1(basegfx::fround(aPosA.getX()), basegfx::fround(aPosA.getY()));
1479     const Point aNewPt2(basegfx::fround(aPosB.getX()), basegfx::fround(aPosB.getY()));
1480 
1481     if(aNewPt1 != aPt1 || aNewPt2 != aPt2)
1482     {
1483         // set model values and broadcast
1484         Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
1485 
1486         aPt1 = aNewPt1;
1487         aPt2 = aNewPt2;
1488 
1489         SetTextDirty();
1490         ActionChanged();
1491         SetChanged();
1492         BroadcastObjectChange();
1493         SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
1494     }
1495 }
1496 
1497 //////////////////////////////////////////////////////////////////////////////
1498 // eof
1499