1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svx/svdomeas.hxx>
23 #include <svx/xpoly.hxx>
24 #include <svx/svdtrans.hxx>
25 #include <svx/svdhdl.hxx>
26 #include <svx/svdoutl.hxx>
27 #include <svx/svddrag.hxx>
28 #include <svx/svdpool.hxx>
29 #include <svx/svdattrx.hxx>
30 #include <svx/svdmodel.hxx>
31 #include <svx/svdview.hxx>
32 #include "svx/svdglob.hxx" // StringCache
33 #include "svx/svdstr.hrc" // the object's name
34 #include <svl/style.hxx>
35 #include <svl/smplhint.hxx>
36 #include <editeng/editdata.hxx>
37 #include <editeng/eeitem.hxx>
38 #include <svx/xlnstit.hxx>
39 #include <svx/xlnstwit.hxx>
40 #include <svx/xlnedit.hxx>
41 #include <svx/xlnwtit.hxx>
42 #include <svx/xlnedwit.hxx>
43 #include <svx/xlnstcit.hxx>
44 #include <svx/xlnedcit.hxx>
45 #include <editeng/outlobj.hxx>
46 #include <editeng/outliner.hxx>
47 #include <editeng/editobj.hxx>
48 #include <editeng/measfld.hxx>
49 #include <editeng/flditem.hxx>
50 #include <svx/svdogrp.hxx>
51 #include <svx/svdopath.hxx>
52 #include <svx/svdpage.hxx>
53 #include <unotools/syslocale.hxx>
54 #include <svx/sdr/properties/measureproperties.hxx>
55 #include <svx/sdr/contact/viewcontactofsdrmeasureobj.hxx>
56 #include <basegfx/point/b2dpoint.hxx>
57 #include <basegfx/polygon/b2dpolygon.hxx>
58 #include <basegfx/polygon/b2dpolypolygon.hxx>
59 #include <basegfx/matrix/b2dhommatrix.hxx>
60 #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 #include "svdconv.hxx"
63 ////////////////////////////////////////////////////////////////////////////////////////////////////
65 SdrMeasureObjGeoData::SdrMeasureObjGeoData() {}
66 SdrMeasureObjGeoData::~SdrMeasureObjGeoData() {}
68 void SdrMeasureObj::TakeRepresentation( XubString
& rStr
, SdrMeasureFieldKind eMeasureFieldKind
) const
71 Fraction
aMeasureScale(1, 1);
72 sal_Bool
bTextRota90(sal_False
);
73 sal_Bool
bShowUnit(sal_False
);
74 FieldUnit
eMeasureUnit(FUNIT_NONE
);
75 FieldUnit
eModUIUnit(FUNIT_NONE
);
77 const SfxItemSet
& rSet
= GetMergedItemSet();
78 bTextRota90
= ((SdrMeasureTextRota90Item
&)rSet
.Get(SDRATTR_MEASURETEXTROTA90
)).GetValue();
79 eMeasureUnit
= ((SdrMeasureUnitItem
&)rSet
.Get(SDRATTR_MEASUREUNIT
)).GetValue();
80 aMeasureScale
= ((SdrMeasureScaleItem
&)rSet
.Get(SDRATTR_MEASURESCALE
)).GetValue();
81 bShowUnit
= ((SdrMeasureShowUnitItem
&)rSet
.Get(SDRATTR_MEASURESHOWUNIT
)).GetValue();
82 sal_Int16 nNumDigits
= ((SdrMeasureDecimalPlacesItem
&)rSet
.Get(SDRATTR_MEASUREDECIMALPLACES
)).GetValue();
84 switch(eMeasureFieldKind
)
86 case SDRMEASUREFIELD_VALUE
:
90 eModUIUnit
= pModel
->GetUIUnit();
92 if(eMeasureUnit
== FUNIT_NONE
)
93 eMeasureUnit
= eModUIUnit
;
95 sal_Int32
nLen(GetLen(aPt2
- aPt1
));
98 if(eMeasureUnit
!= eModUIUnit
)
100 // for the unit conversion
101 aFact
*= GetMapFactor(eModUIUnit
, eMeasureUnit
).X();
104 if(aMeasureScale
.GetNumerator() != aMeasureScale
.GetDenominator())
106 aFact
*= aMeasureScale
;
109 if(aFact
.GetNumerator() != aFact
.GetDenominator())
111 // scale via BigInt, to avoid overruns
112 nLen
= BigMulDiv(nLen
, aFact
.GetNumerator(), aFact
.GetDenominator());
116 pModel
->TakeMetricStr(nLen
, aTmp
, true, nNumDigits
);
122 rStr
+= sal_Unicode('?');
125 sal_Unicode
cDec(SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]);
127 if(rStr
.Search(cDec
) != STRING_NOTFOUND
)
129 xub_StrLen
nLen2(rStr
.Len() - 1);
131 while(rStr
.GetChar(nLen2
) == sal_Unicode('0'))
137 if(rStr
.GetChar(nLen2
) == cDec
)
144 rStr
+= sal_Unicode('0');
149 // if there's no Model ... (e. g. preview in dialog)
151 rStr
.AppendAscii("4711");
156 case SDRMEASUREFIELD_UNIT
:
162 eModUIUnit
= pModel
->GetUIUnit();
164 if(eMeasureUnit
== FUNIT_NONE
)
165 eMeasureUnit
= eModUIUnit
;
168 pModel
->TakeUnitStr(eMeasureUnit
, rStr
);
174 case SDRMEASUREFIELD_ROTA90BLANCS
:
179 rStr
+= sal_Unicode(' ');
187 //////////////////////////////////////////////////////////////////////////////
188 // BaseProperties section
190 sdr::properties::BaseProperties
* SdrMeasureObj::CreateObjectSpecificProperties()
192 return new sdr::properties::MeasureProperties(*this);
195 //////////////////////////////////////////////////////////////////////////////
196 // DrawContact section
198 sdr::contact::ViewContact
* SdrMeasureObj::CreateObjectSpecificViewContact()
200 return new sdr::contact::ViewContactOfSdrMeasureObj(*this);
203 //////////////////////////////////////////////////////////////////////////////
205 TYPEINIT1(SdrMeasureObj
,SdrTextObj
);
207 SdrMeasureObj::SdrMeasureObj():
208 bTextDirty(sal_False
)
211 mbSupportTextIndentingOnLineWidthChange
= sal_False
;
214 SdrMeasureObj::SdrMeasureObj(const Point
& rPt1
, const Point
& rPt2
):
217 bTextDirty(sal_False
)
220 mbSupportTextIndentingOnLineWidthChange
= sal_False
;
223 SdrMeasureObj::~SdrMeasureObj()
227 void SdrMeasureObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
229 rInfo
.bSelectAllowed
=sal_True
;
230 rInfo
.bMoveAllowed
=sal_True
;
231 rInfo
.bResizeFreeAllowed
=sal_True
;
232 rInfo
.bResizePropAllowed
=sal_True
;
233 rInfo
.bRotateFreeAllowed
=sal_True
;
234 rInfo
.bRotate90Allowed
=sal_True
;
235 rInfo
.bMirrorFreeAllowed
=sal_True
;
236 rInfo
.bMirror45Allowed
=sal_True
;
237 rInfo
.bMirror90Allowed
=sal_True
;
238 rInfo
.bTransparenceAllowed
= sal_False
;
239 rInfo
.bGradientAllowed
= sal_False
;
240 rInfo
.bShearAllowed
=sal_True
;
241 rInfo
.bEdgeRadiusAllowed
=sal_False
;
242 rInfo
.bNoOrthoDesired
=sal_True
;
243 rInfo
.bNoContortion
=sal_False
;
244 rInfo
.bCanConvToPath
=sal_False
;
245 rInfo
.bCanConvToPoly
=sal_True
;
246 rInfo
.bCanConvToPathLineToArea
=sal_False
;
247 rInfo
.bCanConvToPolyLineToArea
=sal_False
;
248 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
251 sal_uInt16
SdrMeasureObj::GetObjIdentifier() const
253 return (sal_uInt16
)OBJ_MEASURE
;
256 struct ImpMeasureRec
: public SdrDragStatUserData
260 SdrMeasureKind eKind
;
261 SdrMeasureTextHPos eWantTextHPos
;
262 SdrMeasureTextVPos eWantTextVPos
;
264 long nHelplineOverhang
;
270 bool bTextUpsideDown
;
271 long nMeasureOverhang
;
272 FieldUnit eMeasureUnit
;
273 Fraction aMeasureScale
;
275 String aFormatString
;
277 long nTextAutoAngleView
;
278 bool bTextIsFixedAngle
;
279 long nTextFixedAngle
;
288 struct ImpMeasurePoly
290 ImpLineRec aMainline1
; // those with the 1st arrowhead
291 ImpLineRec aMainline2
; // those with the 2nd arrowhead
292 ImpLineRec aMainline3
; // those in between
293 ImpLineRec aHelpline1
;
294 ImpLineRec aHelpline2
;
305 sal_uInt16 nMainlineAnz
;
306 SdrMeasureTextHPos eUsedTextHPos
;
307 SdrMeasureTextVPos eUsedTextVPos
;
308 long nLineWdt2
; // half the line width
309 long nArrow1Len
; // length of 1st arrowhead; for Center, use only half
310 long nArrow2Len
; // length of 2nd arrowhead; for Center, use only half
311 long nArrow1Wdt
; // width of 1st arrow
312 long nArrow2Wdt
; // width of 2nd arrow
313 long nShortLineLen
; // line length, if PfeileAussen (arrowheads on the outside)
314 bool bArrow1Center
; // arrowhead 1 centered?
315 bool bArrow2Center
; // arrowhead 2 centered?
316 bool bAutoUpsideDown
; // UpsideDown via automation
317 bool bPfeileAussen
; // arrowheads on the outside
321 void SdrMeasureObj::ImpTakeAttr(ImpMeasureRec
& rRec
) const
326 const SfxItemSet
& rSet
= GetObjectItemSet();
327 rRec
.eKind
=((SdrMeasureKindItem
& )rSet
.Get(SDRATTR_MEASUREKIND
)).GetValue();
328 rRec
.eWantTextHPos
=((SdrMeasureTextHPosItem
& )rSet
.Get(SDRATTR_MEASURETEXTHPOS
)).GetValue();
329 rRec
.eWantTextVPos
=((SdrMeasureTextVPosItem
& )rSet
.Get(SDRATTR_MEASURETEXTVPOS
)).GetValue();
330 rRec
.nLineDist
=((SdrMeasureLineDistItem
& )rSet
.Get(SDRATTR_MEASURELINEDIST
)).GetValue();
331 rRec
.nHelplineOverhang
=((SdrMeasureHelplineOverhangItem
&)rSet
.Get(SDRATTR_MEASUREHELPLINEOVERHANG
)).GetValue();
332 rRec
.nHelplineDist
=((SdrMeasureHelplineDistItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINEDIST
)).GetValue();
333 rRec
.nHelpline1Len
=((SdrMeasureHelpline1LenItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINE1LEN
)).GetValue();
334 rRec
.nHelpline2Len
=((SdrMeasureHelpline2LenItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINE2LEN
)).GetValue();
335 rRec
.bBelowRefEdge
=((SdrMeasureBelowRefEdgeItem
& )rSet
.Get(SDRATTR_MEASUREBELOWREFEDGE
)).GetValue();
336 rRec
.bTextRota90
=((SdrMeasureTextRota90Item
& )rSet
.Get(SDRATTR_MEASURETEXTROTA90
)).GetValue();
337 rRec
.bTextUpsideDown
=((SdrMeasureTextUpsideDownItem
& )rSet
.Get(SDRATTR_MEASURETEXTUPSIDEDOWN
)).GetValue();
338 rRec
.nMeasureOverhang
=((SdrMeasureOverhangItem
& )rSet
.Get(SDRATTR_MEASUREOVERHANG
)).GetValue();
339 rRec
.eMeasureUnit
=((SdrMeasureUnitItem
& )rSet
.Get(SDRATTR_MEASUREUNIT
)).GetValue();
340 rRec
.aMeasureScale
=((SdrMeasureScaleItem
& )rSet
.Get(SDRATTR_MEASURESCALE
)).GetValue();
341 rRec
.bShowUnit
=((SdrMeasureShowUnitItem
& )rSet
.Get(SDRATTR_MEASURESHOWUNIT
)).GetValue();
342 rRec
.aFormatString
=((SdrMeasureFormatStringItem
& )rSet
.Get(SDRATTR_MEASUREFORMATSTRING
)).GetValue();
343 rRec
.bTextAutoAngle
=((SdrMeasureTextAutoAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTAUTOANGLE
)).GetValue();
344 rRec
.nTextAutoAngleView
=((SdrMeasureTextAutoAngleViewItem
&)rSet
.Get(SDRATTR_MEASURETEXTAUTOANGLEVIEW
)).GetValue();
345 rRec
.bTextIsFixedAngle
=((SdrMeasureTextIsFixedAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTISFIXEDANGLE
)).GetValue();
346 rRec
.nTextFixedAngle
=((SdrMeasureTextFixedAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTFIXEDANGLE
)).GetValue();
349 long impGetLineStartEndDistance(const basegfx::B2DPolyPolygon
& rPolyPolygon
, long nNewWidth
, bool bCenter
)
351 const basegfx::B2DRange
aPolygonRange(rPolyPolygon
.getB2DRange());
352 const double fOldWidth(aPolygonRange
.getWidth() > 1.0 ? aPolygonRange
.getWidth() : 1.0);
353 const double fScale((double)nNewWidth
/ fOldWidth
);
354 long nHeight(basegfx::fround(aPolygonRange
.getHeight() * fScale
));
364 void SdrMeasureObj::ImpCalcGeometrics(const ImpMeasureRec
& rRec
, ImpMeasurePoly
& rPol
) const
366 Point
aP1(rRec
.aPt1
);
367 Point
aP2(rRec
.aPt2
);
368 Point
aDelt(aP2
); aDelt
-=aP1
;
370 rPol
.aTextSize
=GetTextSize();
371 rPol
.nLineLen
=GetLen(aDelt
);
374 long nArrow1Len
=0; bool bArrow1Center
=false;
375 long nArrow2Len
=0; bool bArrow2Center
=false;
382 bool bPfeileAussen
= false;
384 const SfxItemSet
& rSet
= GetObjectItemSet();
385 sal_Int32 nLineWdt
= ((XLineWidthItem
&)(rSet
.Get(XATTR_LINEWIDTH
))).GetValue(); // line width
386 rPol
.nLineWdt2
= (nLineWdt
+ 1) / 2;
388 nArrow1Wdt
= ((const XLineStartWidthItem
&)(rSet
.Get(XATTR_LINESTARTWIDTH
))).GetValue();
390 nArrow1Wdt
= -nLineWdt
* nArrow1Wdt
/ 100; // <0 = relativ
392 nArrow2Wdt
= ((const XLineEndWidthItem
&)(rSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
394 nArrow2Wdt
= -nLineWdt
* nArrow2Wdt
/ 100; // <0 = relativ
396 basegfx::B2DPolyPolygon
aPol1(((const XLineStartItem
&)(rSet
.Get(XATTR_LINESTART
))).GetLineStartValue());
397 basegfx::B2DPolyPolygon
aPol2(((const XLineEndItem
&)(rSet
.Get(XATTR_LINEEND
))).GetLineEndValue());
398 bArrow1Center
= ((const XLineStartCenterItem
&)(rSet
.Get(XATTR_LINESTARTCENTER
))).GetValue();
399 bArrow2Center
= ((const XLineEndCenterItem
&)(rSet
.Get(XATTR_LINEENDCENTER
))).GetValue();
400 nArrow1Len
= impGetLineStartEndDistance(aPol1
, nArrow1Wdt
, bArrow1Center
) - 1;
401 nArrow2Len
= impGetLineStartEndDistance(aPol2
, nArrow2Wdt
, bArrow2Center
) - 1;
403 // nArrowLen is already halved at bCenter.
404 // In the case of 2 arrowheads each 4mm long, we can't go below 10mm.
405 nArrowNeed
=nArrow1Len
+nArrow2Len
+(nArrow1Wdt
+nArrow2Wdt
)/2;
406 if (rPol
.nLineLen
<nArrowNeed
) bPfeileAussen
= true;
407 nShortLen
=(nArrow1Len
+nArrow1Wdt
+ nArrow2Len
+nArrow2Wdt
) /2;
409 rPol
.eUsedTextHPos
=rRec
.eWantTextHPos
;
410 rPol
.eUsedTextVPos
=rRec
.eWantTextVPos
;
411 if (rPol
.eUsedTextVPos
==SDRMEASURE_TEXTVAUTO
) rPol
.eUsedTextVPos
=SDRMEASURE_ABOVE
;
412 bool bBrkLine
=rPol
.eUsedTextVPos
==SDRMEASURETEXT_BREAKEDLINE
;
413 if (rPol
.eUsedTextVPos
==SDRMEASURETEXT_VERTICALCENTERED
)
415 OutlinerParaObject
* pOutlinerParaObject
= SdrTextObj::GetOutlinerParaObject();
416 if (pOutlinerParaObject
!=NULL
&& pOutlinerParaObject
->GetTextObject().GetParagraphCount()==1)
418 bBrkLine
=sal_True
; // dashed line if there's only on paragraph.
421 rPol
.bBreakedLine
=bBrkLine
;
422 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTHAUTO
) { // if text is too wide, push it outside
423 bool bOutside
= false;
424 long nNeedSiz
=!rRec
.bTextRota90
? rPol
.aTextSize
.Width() : rPol
.aTextSize
.Height();
425 if (nNeedSiz
>rPol
.nLineLen
) bOutside
= true; // text doesn't fit in between
427 if (nNeedSiz
+nArrowNeed
>rPol
.nLineLen
) bPfeileAussen
= true; // text fits in between, if arrowheads are on the outside
429 long nSmallNeed
=nArrow1Len
+nArrow2Len
+(nArrow1Wdt
+nArrow2Wdt
)/2/4;
430 if (nNeedSiz
+nSmallNeed
>rPol
.nLineLen
) bPfeileAussen
= true; // text fits in between, if arrowheads are on the outside
432 rPol
.eUsedTextHPos
=bOutside
? SDRMEASURE_TEXTLEFTOUTSIDE
: SDRMEASURE_TEXTINSIDE
;
434 if (rPol
.eUsedTextHPos
!=SDRMEASURE_TEXTINSIDE
) bPfeileAussen
= true;
435 rPol
.nArrow1Wdt
=nArrow1Wdt
;
436 rPol
.nArrow2Wdt
=nArrow2Wdt
;
437 rPol
.nShortLineLen
=nShortLen
;
438 rPol
.bPfeileAussen
=bPfeileAussen
;
439 rPol
.nArrow1Len
=nArrow1Len
;
440 rPol
.bArrow1Center
=bArrow1Center
;
441 rPol
.nArrow2Len
=nArrow2Len
;
442 rPol
.bArrow2Center
=bArrow2Center
;
444 rPol
.nLineWink
=GetAngle(aDelt
);
445 double a
=rPol
.nLineWink
*nPi180
;
446 double nLineSin
=sin(a
);
447 double nLineCos
=cos(a
);
448 rPol
.nLineSin
=nLineSin
;
449 rPol
.nLineCos
=nLineCos
;
451 rPol
.nTextWink
=rPol
.nLineWink
;
452 if (rRec
.bTextRota90
) rPol
.nTextWink
+=9000;
454 rPol
.bAutoUpsideDown
=sal_False
;
455 if (rRec
.bTextAutoAngle
) {
456 long nTmpWink
=NormAngle360(rPol
.nTextWink
-rRec
.nTextAutoAngleView
);
457 if (nTmpWink
>=18000) {
458 rPol
.nTextWink
+=18000;
459 rPol
.bAutoUpsideDown
=sal_True
;
463 if (rRec
.bTextUpsideDown
) rPol
.nTextWink
+=18000;
464 rPol
.nTextWink
=NormAngle360(rPol
.nTextWink
);
465 rPol
.nHlpWink
=rPol
.nLineWink
+9000;
466 if (rRec
.bBelowRefEdge
) rPol
.nHlpWink
+=18000;
467 rPol
.nHlpWink
=NormAngle360(rPol
.nHlpWink
);
468 double nHlpSin
=nLineCos
;
469 double nHlpCos
=-nLineSin
;
470 if (rRec
.bBelowRefEdge
) {
474 rPol
.nHlpSin
=nHlpSin
;
475 rPol
.nHlpCos
=nHlpCos
;
477 long nLineDist
=rRec
.nLineDist
;
478 long nOverhang
=rRec
.nHelplineOverhang
;
479 long nHelplineDist
=rRec
.nHelplineDist
;
481 long dx
= Round(nLineDist
*nHlpCos
);
482 long dy
=-Round(nLineDist
*nHlpSin
);
483 long dxh1a
= Round((nHelplineDist
-rRec
.nHelpline1Len
)*nHlpCos
);
484 long dyh1a
=-Round((nHelplineDist
-rRec
.nHelpline1Len
)*nHlpSin
);
485 long dxh1b
= Round((nHelplineDist
-rRec
.nHelpline2Len
)*nHlpCos
);
486 long dyh1b
=-Round((nHelplineDist
-rRec
.nHelpline2Len
)*nHlpSin
);
487 long dxh2
= Round((nLineDist
+nOverhang
)*nHlpCos
);
488 long dyh2
=-Round((nLineDist
+nOverhang
)*nHlpSin
);
491 rPol
.aHelpline1
.aP1
=Point(aP1
.X()+dxh1a
,aP1
.Y()+dyh1a
);
492 rPol
.aHelpline1
.aP2
=Point(aP1
.X()+dxh2
,aP1
.Y()+dyh2
);
495 rPol
.aHelpline2
.aP1
=Point(aP2
.X()+dxh1b
,aP2
.Y()+dyh1b
);
496 rPol
.aHelpline2
.aP2
=Point(aP2
.X()+dxh2
,aP2
.Y()+dyh2
);
499 Point
aMainlinePt1(aP1
.X()+dx
,aP1
.Y()+dy
);
500 Point
aMainlinePt2(aP2
.X()+dx
,aP2
.Y()+dy
);
501 if (!bPfeileAussen
) {
502 rPol
.aMainline1
.aP1
=aMainlinePt1
;
503 rPol
.aMainline1
.aP2
=aMainlinePt2
;
504 rPol
.aMainline2
=rPol
.aMainline1
;
505 rPol
.aMainline3
=rPol
.aMainline1
;
508 long nNeedSiz
=!rRec
.bTextRota90
? rPol
.aTextSize
.Width() : rPol
.aTextSize
.Height();
509 long nHalfLen
=(rPol
.nLineLen
-nNeedSiz
-nArrow1Wdt
/4-nArrow2Wdt
/4) /2;
511 rPol
.aMainline1
.aP2
=aMainlinePt1
;
512 rPol
.aMainline1
.aP2
.X()+=nHalfLen
;
513 RotatePoint(rPol
.aMainline1
.aP2
,rPol
.aMainline1
.aP1
,nLineSin
,nLineCos
);
514 rPol
.aMainline2
.aP1
=aMainlinePt2
;
515 rPol
.aMainline2
.aP1
.X()-=nHalfLen
;
516 RotatePoint(rPol
.aMainline2
.aP1
,rPol
.aMainline2
.aP2
,nLineSin
,nLineCos
);
519 long nLen1
=nShortLen
; // arrowhead's width as line length outside of the arrowhead
520 long nLen2
=nShortLen
;
521 long nTextWdt
=rRec
.bTextRota90
? rPol
.aTextSize
.Height() : rPol
.aTextSize
.Width();
523 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTLEFTOUTSIDE
) nLen1
=nArrow1Len
+nTextWdt
;
524 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTRIGHTOUTSIDE
) nLen2
=nArrow2Len
+nTextWdt
;
526 rPol
.aMainline1
.aP1
=aMainlinePt1
;
527 rPol
.aMainline1
.aP2
=aMainlinePt1
; rPol
.aMainline1
.aP2
.X()-=nLen1
; RotatePoint(rPol
.aMainline1
.aP2
,aMainlinePt1
,nLineSin
,nLineCos
);
528 rPol
.aMainline2
.aP1
=aMainlinePt2
; rPol
.aMainline2
.aP1
.X()+=nLen2
; RotatePoint(rPol
.aMainline2
.aP1
,aMainlinePt2
,nLineSin
,nLineCos
);
529 rPol
.aMainline2
.aP2
=aMainlinePt2
;
530 rPol
.aMainline3
.aP1
=aMainlinePt1
;
531 rPol
.aMainline3
.aP2
=aMainlinePt2
;
533 if (bBrkLine
&& rPol
.eUsedTextHPos
==SDRMEASURE_TEXTINSIDE
) rPol
.nMainlineAnz
=2;
537 basegfx::B2DPolyPolygon
SdrMeasureObj::ImpCalcXPoly(const ImpMeasurePoly
& rPol
) const
539 basegfx::B2DPolyPolygon aRetval
;
540 basegfx::B2DPolygon aPartPolyA
;
541 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline1
.aP1
.X(), rPol
.aMainline1
.aP1
.Y()));
542 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline1
.aP2
.X(), rPol
.aMainline1
.aP2
.Y()));
543 aRetval
.append(aPartPolyA
);
545 if(rPol
.nMainlineAnz
> 1)
548 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline2
.aP1
.X(), rPol
.aMainline2
.aP1
.Y()));
549 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline2
.aP2
.X(), rPol
.aMainline2
.aP2
.Y()));
550 aRetval
.append(aPartPolyA
);
553 if(rPol
.nMainlineAnz
> 2)
556 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline3
.aP1
.X(), rPol
.aMainline3
.aP1
.Y()));
557 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline3
.aP2
.X(), rPol
.aMainline3
.aP2
.Y()));
558 aRetval
.append(aPartPolyA
);
562 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline1
.aP1
.X(), rPol
.aHelpline1
.aP1
.Y()));
563 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline1
.aP2
.X(), rPol
.aHelpline1
.aP2
.Y()));
564 aRetval
.append(aPartPolyA
);
567 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline2
.aP1
.X(), rPol
.aHelpline2
.aP1
.Y()));
568 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline2
.aP2
.X(), rPol
.aHelpline2
.aP2
.Y()));
569 aRetval
.append(aPartPolyA
);
574 bool SdrMeasureObj::CalcFieldValue(const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_uInt16 nPos
,
576 Color
*& rpTxtColor
, Color
*& rpFldColor
, XubString
& rRet
) const
578 const SvxFieldData
* pField
=rField
.GetField();
579 SdrMeasureField
* pMeasureField
=PTR_CAST(SdrMeasureField
,pField
);
580 if (pMeasureField
!=NULL
) {
581 TakeRepresentation(rRet
, pMeasureField
->GetMeasureFieldKind());
582 if (rpFldColor
!=NULL
) {
591 return SdrTextObj::CalcFieldValue(rField
,nPara
,nPos
,bEdit
,rpTxtColor
,rpFldColor
,rRet
);
595 void SdrMeasureObj::UndirtyText() const
599 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
600 OutlinerParaObject
* pOutlinerParaObject
= SdrTextObj::GetOutlinerParaObject();
601 if(pOutlinerParaObject
==NULL
)
603 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS
), EE_FEATURE_FIELD
), ESelection(0,0));
604 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_VALUE
), EE_FEATURE_FIELD
),ESelection(0,1));
605 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_UNIT
), EE_FEATURE_FIELD
),ESelection(0,2));
606 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS
), EE_FEATURE_FIELD
),ESelection(0,3));
609 rOutliner
.SetStyleSheet(0, GetStyleSheet());
611 rOutliner
.SetParaAttribs(0, GetObjectItemSet());
614 const_cast<SdrMeasureObj
*>(this)->NbcSetOutlinerParaObject( rOutliner
.CreateParaObject() );
618 rOutliner
.SetText(*pOutlinerParaObject
);
621 rOutliner
.SetUpdateMode(sal_True
);
622 rOutliner
.UpdateFields();
623 Size
aSiz(rOutliner
.CalcTextSize());
625 // cast to nonconst three times
626 ((SdrMeasureObj
*)this)->aTextSize
=aSiz
;
627 ((SdrMeasureObj
*)this)->bTextSizeDirty
=sal_False
;
628 ((SdrMeasureObj
*)this)->bTextDirty
=sal_False
;
632 void SdrMeasureObj::TakeUnrotatedSnapRect(Rectangle
& rRect
) const
634 if (bTextDirty
) UndirtyText();
636 ImpMeasurePoly aMPol
;
638 ImpCalcGeometrics(aRec
,aMPol
);
640 // determine TextSize including text frame margins
641 Size
aTextSize2(aMPol
.aTextSize
);
642 if (aTextSize2
.Width()<1) aTextSize2
.Width()=1;
643 if (aTextSize2
.Height()<1) aTextSize2
.Height()=1;
644 aTextSize2
.Width()+=GetTextLeftDistance()+GetTextRightDistance();
645 aTextSize2
.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
647 Point
aPt1b(aMPol
.aMainline1
.aP1
);
648 long nLen
=aMPol
.nLineLen
;
649 long nLWdt
=aMPol
.nLineWdt2
;
650 long nArr1Len
=aMPol
.nArrow1Len
;
651 long nArr2Len
=aMPol
.nArrow2Len
;
652 if (aMPol
.bBreakedLine
) {
653 // In the case of a dashed line and Outside, the text should be
654 // placed next to the line at the arrowhead instead of directly
656 nArr1Len
=aMPol
.nShortLineLen
+aMPol
.nArrow1Wdt
/4;
657 nArr2Len
=aMPol
.nShortLineLen
+aMPol
.nArrow2Wdt
/4;
661 bool bRota90
=aRec
.bTextRota90
;
662 bool bUpsideDown
=aRec
.bTextUpsideDown
!=aMPol
.bAutoUpsideDown
;
663 bool bBelowRefEdge
=aRec
.bBelowRefEdge
;
664 SdrMeasureTextHPos eMH
=aMPol
.eUsedTextHPos
;
665 SdrMeasureTextVPos eMV
=aMPol
.eUsedTextVPos
;
668 case SDRMEASURE_TEXTLEFTOUTSIDE
: aTextPos
.X()=aPt1b
.X()-aTextSize2
.Width()-nArr1Len
-nLWdt
; break;
669 case SDRMEASURE_TEXTRIGHTOUTSIDE
: aTextPos
.X()=aPt1b
.X()+nLen
+nArr2Len
+nLWdt
; break;
670 default: aTextPos
.X()=aPt1b
.X(); aTextSize2
.Width()=nLen
;
673 case SDRMEASURETEXT_VERTICALCENTERED
:
674 case SDRMEASURETEXT_BREAKEDLINE
: aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()/2; break;
675 case SDRMEASURE_BELOW
: {
676 if (!bUpsideDown
) aTextPos
.Y()=aPt1b
.Y()+nLWdt
;
677 else aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()-nLWdt
;
680 if (!bUpsideDown
) aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()-nLWdt
;
681 else aTextPos
.Y()=aPt1b
.Y()+nLWdt
;
685 aTextPos
.X()+=aTextSize2
.Width();
686 aTextPos
.Y()+=aTextSize2
.Height();
688 } else { // also if bTextRota90==TRUE
690 case SDRMEASURE_TEXTLEFTOUTSIDE
: aTextPos
.X()=aPt1b
.X()-aTextSize2
.Height()-nArr1Len
; break;
691 case SDRMEASURE_TEXTRIGHTOUTSIDE
: aTextPos
.X()=aPt1b
.X()+nLen
+nArr2Len
; break;
692 default: aTextPos
.X()=aPt1b
.X(); aTextSize2
.Height()=nLen
;
695 case SDRMEASURETEXT_VERTICALCENTERED
:
696 case SDRMEASURETEXT_BREAKEDLINE
: aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()/2; break;
697 case SDRMEASURE_BELOW
: {
698 if (!bBelowRefEdge
) aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()+nLWdt
;
699 else aTextPos
.Y()=aPt1b
.Y()-nLWdt
;
702 if (!bBelowRefEdge
) aTextPos
.Y()=aPt1b
.Y()-nLWdt
;
703 else aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()+nLWdt
;
707 aTextPos
.X()+=aTextSize2
.Height();
708 aTextPos
.Y()-=aTextSize2
.Width();
711 if (aMPol
.nTextWink
!=aGeo
.nDrehWink
) {
712 ((SdrMeasureObj
*)this)->aGeo
.nDrehWink
=aMPol
.nTextWink
;
713 ((SdrMeasureObj
*)this)->aGeo
.RecalcSinCos();
715 RotatePoint(aTextPos
,aPt1b
,aMPol
.nLineSin
,aMPol
.nLineCos
);
716 aTextSize2
.Width()++; aTextSize2
.Height()++; // because of the Rect-Ctor's odd behavior
717 rRect
=Rectangle(aTextPos
,aTextSize2
);
719 ((SdrMeasureObj
*)this)->aRect
=rRect
;
721 if (aMPol
.nTextWink
!=aGeo
.nDrehWink
) {
722 ((SdrMeasureObj
*)this)->aGeo
.nDrehWink
=aMPol
.nTextWink
;
723 ((SdrMeasureObj
*)this)->aGeo
.RecalcSinCos();
727 SdrMeasureObj
* SdrMeasureObj::Clone() const
729 return CloneHelper
< SdrMeasureObj
>();
732 void SdrMeasureObj::TakeObjNameSingul(XubString
& rName
) const
734 rName
=ImpGetResStr(STR_ObjNameSingulMEASURE
);
736 String
aName( GetName() );
739 rName
+= sal_Unicode(' ');
740 rName
+= sal_Unicode('\'');
742 rName
+= sal_Unicode('\'');
746 void SdrMeasureObj::TakeObjNamePlural(XubString
& rName
) const
748 rName
=ImpGetResStr(STR_ObjNamePluralMEASURE
);
751 basegfx::B2DPolyPolygon
SdrMeasureObj::TakeXorPoly() const
754 ImpMeasurePoly aMPol
;
756 ImpCalcGeometrics(aRec
,aMPol
);
757 return ImpCalcXPoly(aMPol
);
760 sal_uInt32
SdrMeasureObj::GetHdlCount() const
765 SdrHdl
* SdrMeasureObj::GetHdl(sal_uInt32 nHdlNum
) const
768 ImpMeasurePoly aMPol
;
770 aRec
.nHelplineDist
=0;
771 ImpCalcGeometrics(aRec
,aMPol
);
775 case 0: aPt
=aMPol
.aHelpline1
.aP1
; break;
776 case 1: aPt
=aMPol
.aHelpline2
.aP1
; break;
777 case 2: aPt
=aPt1
; break;
778 case 3: aPt
=aPt2
; break;
779 case 4: aPt
=aMPol
.aHelpline1
.aP2
; break;
780 case 5: aPt
=aMPol
.aHelpline2
.aP2
; break;
782 SdrHdl
* pHdl
=new ImpMeasureHdl(aPt
,HDL_USER
);
783 pHdl
->SetObjHdlNum(nHdlNum
);
784 pHdl
->SetDrehWink(aMPol
.nLineWink
);
788 ////////////////////////////////////////////////////////////////////////////////////////////////////
790 bool SdrMeasureObj::hasSpecialDrag() const
795 bool SdrMeasureObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
797 const SdrHdl
* pHdl
= rDrag
.GetHdl();
801 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
803 if(nHdlNum
!= 2 && nHdlNum
!= 3)
805 rDrag
.SetEndDragChangesAttributes(true);
814 bool SdrMeasureObj::applySpecialDrag(SdrDragStat
& rDrag
)
816 ImpMeasureRec aMeasureRec
;
817 const SdrHdl
* pHdl
= rDrag
.GetHdl();
818 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
820 ImpTakeAttr(aMeasureRec
);
821 ImpEvalDrag(aMeasureRec
, rDrag
);
827 aPt1
= aMeasureRec
.aPt1
;
833 aPt2
= aMeasureRec
.aPt2
;
844 ImpMeasureRec aOrigMeasureRec
;
845 ImpTakeAttr(aOrigMeasureRec
);
847 if(aMeasureRec
.nHelpline1Len
!= aOrigMeasureRec
.nHelpline1Len
)
849 SetObjectItem(SdrMeasureHelpline1LenItem(aMeasureRec
.nHelpline1Len
));
852 if(aMeasureRec
.nHelpline2Len
!= aOrigMeasureRec
.nHelpline2Len
)
854 SetObjectItem(SdrMeasureHelpline2LenItem(aMeasureRec
.nHelpline2Len
));
863 ImpMeasureRec aOrigMeasureRec
;
864 ImpTakeAttr(aOrigMeasureRec
);
866 if(aMeasureRec
.nLineDist
!= aOrigMeasureRec
.nLineDist
)
868 SetObjectItem(SdrMeasureLineDistItem(aMeasureRec
.nLineDist
));
871 if(aMeasureRec
.bBelowRefEdge
!= aOrigMeasureRec
.bBelowRefEdge
)
873 SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec
.bBelowRefEdge
));
886 String
SdrMeasureObj::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
892 void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec
& rRec
, const SdrDragStat
& rDrag
) const
894 long nLineWink
=GetAngle(rRec
.aPt2
-rRec
.aPt1
);
895 double a
=nLineWink
*nPi180
;
899 const SdrHdl
* pHdl
=rDrag
.GetHdl();
900 sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
901 bool bOrtho
=rDrag
.GetView()!=NULL
&& rDrag
.GetView()->IsOrtho();
902 bool bBigOrtho
=bOrtho
&& rDrag
.GetView()->IsBigOrtho();
903 bool bBelow
=rRec
.bBelowRefEdge
;
904 Point
aPt(rDrag
.GetNow());
908 RotatePoint(aPt
,aPt1
,nSin
,-nCos
);
909 rRec
.nHelpline1Len
=aPt1
.Y()-aPt
.Y();
910 if (bBelow
) rRec
.nHelpline1Len
=-rRec
.nHelpline1Len
;
911 if (bOrtho
) rRec
.nHelpline2Len
=rRec
.nHelpline1Len
;
914 RotatePoint(aPt
,aPt2
,nSin
,-nCos
);
915 rRec
.nHelpline2Len
=aPt2
.Y()-aPt
.Y();
916 if (bBelow
) rRec
.nHelpline2Len
=-rRec
.nHelpline2Len
;
917 if (bOrtho
) rRec
.nHelpline1Len
=rRec
.nHelpline2Len
;
920 bool bAnf
=nHdlNum
==2;
921 Point
& rMov
=bAnf
? rRec
.aPt1
: rRec
.aPt2
;
923 Point
aFix(bAnf
? rRec
.aPt2
: rRec
.aPt1
);
925 long ndx0
=aMov
.X()-aFix
.X();
926 long ndy0
=aMov
.Y()-aFix
.Y();
929 if (!bHLin
|| !bVLin
) { // else aPt1==aPt2
930 long ndx
=aPt
.X()-aFix
.X();
931 long ndy
=aPt
.Y()-aFix
.Y();
932 double nXFact
=0; if (!bVLin
) nXFact
=(double)ndx
/(double)ndx0
;
933 double nYFact
=0; if (!bHLin
) nYFact
=(double)ndy
/(double)ndy0
;
934 bool bHor
=bHLin
|| (!bVLin
&& (nXFact
>nYFact
) ==bBigOrtho
);
935 bool bVer
=bVLin
|| (!bHLin
&& (nXFact
<=nYFact
)==bBigOrtho
);
936 if (bHor
) ndy
=long(ndy0
*nXFact
);
937 if (bVer
) ndx
=long(ndx0
*nYFact
);
946 long nVal0
=rRec
.nLineDist
;
947 RotatePoint(aPt
,(nHdlNum
==4 ? aPt1
: aPt2
),nSin
,-nCos
);
948 rRec
.nLineDist
=aPt
.Y()- (nHdlNum
==4 ? aPt1
.Y() : aPt2
.Y());
949 if (bBelow
) rRec
.nLineDist
=-rRec
.nLineDist
;
950 if (rRec
.nLineDist
<0) {
951 rRec
.nLineDist
=-rRec
.nLineDist
;
952 rRec
.bBelowRefEdge
=!bBelow
;
954 rRec
.nLineDist
-=rRec
.nHelplineOverhang
;
955 if (bOrtho
) rRec
.nLineDist
=nVal0
;
960 ////////////////////////////////////////////////////////////////////////////////////////////////////
962 bool SdrMeasureObj::BegCreate(SdrDragStat
& rStat
)
964 rStat
.SetOrtho8Possible();
965 aPt1
=rStat
.GetStart();
971 bool SdrMeasureObj::MovCreate(SdrDragStat
& rStat
)
973 SdrView
* pView
=rStat
.GetView();
974 aPt1
=rStat
.GetStart();
976 if (pView
!=NULL
&& pView
->IsCreate1stPointAsCenter()) {
982 bSnapRectDirty
=sal_True
;
986 bool SdrMeasureObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
990 return (eCmd
==SDRCREATE_FORCEEND
|| rStat
.GetPointAnz()>=2);
993 bool SdrMeasureObj::BckCreate(SdrDragStat
& /*rStat*/)
998 void SdrMeasureObj::BrkCreate(SdrDragStat
& /*rStat*/)
1002 basegfx::B2DPolyPolygon
SdrMeasureObj::TakeCreatePoly(const SdrDragStat
& /*rDrag*/) const
1005 ImpMeasurePoly aMPol
;
1008 ImpCalcGeometrics(aRec
, aMPol
);
1010 return ImpCalcXPoly(aMPol
);
1013 Pointer
SdrMeasureObj::GetCreatePointer() const
1015 return Pointer(POINTER_CROSS
);
1018 void SdrMeasureObj::NbcMove(const Size
& rSiz
)
1020 SdrTextObj::NbcMove(rSiz
);
1021 MovePoint(aPt1
,rSiz
);
1022 MovePoint(aPt2
,rSiz
);
1025 void SdrMeasureObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
1027 SdrTextObj::NbcResize(rRef
,xFact
,yFact
);
1028 ResizePoint(aPt1
,rRef
,xFact
,yFact
);
1029 ResizePoint(aPt2
,rRef
,xFact
,yFact
);
1033 void SdrMeasureObj::NbcRotate(const Point
& rRef
, long nWink
, double sn
, double cs
)
1035 SdrTextObj::NbcRotate(rRef
,nWink
,sn
,cs
);
1036 long nLen0
=GetLen(aPt2
-aPt1
);
1037 RotatePoint(aPt1
,rRef
,sn
,cs
);
1038 RotatePoint(aPt2
,rRef
,sn
,cs
);
1039 long nLen1
=GetLen(aPt2
-aPt1
);
1040 if (nLen1
!=nLen0
) { // rounding error!
1041 long dx
=aPt2
.X()-aPt1
.X();
1042 long dy
=aPt2
.Y()-aPt1
.Y();
1043 dx
=BigMulDiv(dx
,nLen0
,nLen1
);
1044 dy
=BigMulDiv(dy
,nLen0
,nLen1
);
1046 aPt1
.X()=aPt2
.X()-dx
;
1047 aPt1
.Y()=aPt2
.Y()-dy
;
1049 aPt2
.X()=aPt1
.X()+dx
;
1050 aPt2
.Y()=aPt1
.Y()+dy
;
1056 void SdrMeasureObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
1058 SdrTextObj::NbcMirror(rRef1
,rRef2
);
1059 MirrorPoint(aPt1
,rRef1
,rRef2
);
1060 MirrorPoint(aPt2
,rRef1
,rRef2
);
1064 void SdrMeasureObj::NbcShear(const Point
& rRef
, long nWink
, double tn
, bool bVShear
)
1066 SdrTextObj::NbcShear(rRef
,nWink
,tn
,bVShear
);
1067 ShearPoint(aPt1
,rRef
,tn
,bVShear
);
1068 ShearPoint(aPt2
,rRef
,tn
,bVShear
);
1073 long SdrMeasureObj::GetRotateAngle() const
1075 return GetAngle(aPt2
-aPt1
);
1078 void SdrMeasureObj::RecalcSnapRect()
1081 ImpMeasurePoly aMPol
;
1085 ImpCalcGeometrics(aRec
, aMPol
);
1086 aXPP
= XPolyPolygon(ImpCalcXPoly(aMPol
));
1087 maSnapRect
= aXPP
.GetBoundRect();
1090 sal_uInt32
SdrMeasureObj::GetSnapPointCount() const
1095 Point
SdrMeasureObj::GetSnapPoint(sal_uInt32 i
) const
1097 if (i
==0) return aPt1
;
1101 sal_Bool
SdrMeasureObj::IsPolyObj() const
1106 sal_uInt32
SdrMeasureObj::GetPointCount() const
1111 Point
SdrMeasureObj::GetPoint(sal_uInt32 i
) const
1113 return (0L == i
) ? aPt1
: aPt2
;
1116 void SdrMeasureObj::NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
)
1126 SdrObjGeoData
* SdrMeasureObj::NewGeoData() const
1128 return new SdrMeasureObjGeoData
;
1131 void SdrMeasureObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
1133 SdrTextObj::SaveGeoData(rGeo
);
1134 SdrMeasureObjGeoData
& rMGeo
=(SdrMeasureObjGeoData
&)rGeo
;
1139 void SdrMeasureObj::RestGeoData(const SdrObjGeoData
& rGeo
)
1141 SdrTextObj::RestGeoData(rGeo
);
1142 SdrMeasureObjGeoData
& rMGeo
=(SdrMeasureObjGeoData
&)rGeo
;
1148 SdrObject
* SdrMeasureObj::DoConvertToPolyObj(sal_Bool bBezier
, bool bAddText
) const
1150 // get XOR Poly as base
1151 XPolyPolygon
aTmpPolyPolygon(TakeXorPoly());
1153 // get local ItemSet and StyleSheet
1154 SfxItemSet
aSet(GetObjectItemSet());
1155 SfxStyleSheet
* pStyleSheet
= GetStyleSheet();
1158 SdrObjGroup
* pGroup
= new SdrObjGroup
;
1159 pGroup
->SetModel(GetModel());
1161 // prepare parameters
1162 basegfx::B2DPolyPolygon aPolyPoly
;
1164 sal_uInt16
nCount(aTmpPolyPolygon
.Count());
1165 sal_uInt16
nLoopStart(0);
1169 // three lines, first one is the middle one
1171 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1173 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1174 pPath
->SetModel(GetModel());
1175 pPath
->SetMergedItemSet(aSet
);
1176 pPath
->SetStyleSheet(pStyleSheet
, true);
1177 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1178 aSet
.Put(XLineStartWidthItem(0L));
1179 aSet
.Put(XLineEndWidthItem(0L));
1182 else if(nCount
== 4)
1184 // four lines, middle line with gap, so there are two lines used
1185 // which have one arrow each
1186 sal_Int32 nEndWidth
= ((const XLineEndWidthItem
&)(aSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
1187 aSet
.Put(XLineEndWidthItem(0L));
1190 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1191 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1192 pPath
->SetModel(GetModel());
1193 pPath
->SetMergedItemSet(aSet
);
1194 pPath
->SetStyleSheet(pStyleSheet
, true);
1196 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1198 aSet
.Put(XLineEndWidthItem(nEndWidth
));
1199 aSet
.Put(XLineStartWidthItem(0L));
1202 aPolyPoly
.append(aTmpPolyPolygon
[1].getB2DPolygon());
1203 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1204 pPath
->SetModel(GetModel());
1205 pPath
->SetMergedItemSet(aSet
);
1206 pPath
->SetStyleSheet(pStyleSheet
, true);
1208 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1210 aSet
.Put(XLineEndWidthItem(0L));
1213 else if(nCount
== 5)
1215 // five lines, first two are the outer ones
1216 sal_Int32 nEndWidth
= ((const XLineEndWidthItem
&)(aSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
1218 aSet
.Put(XLineEndWidthItem(0L));
1221 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1222 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1223 pPath
->SetModel(GetModel());
1224 pPath
->SetMergedItemSet(aSet
);
1225 pPath
->SetStyleSheet(pStyleSheet
, true);
1227 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1229 aSet
.Put(XLineEndWidthItem(nEndWidth
));
1230 aSet
.Put(XLineStartWidthItem(0L));
1233 aPolyPoly
.append(aTmpPolyPolygon
[1].getB2DPolygon());
1234 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1235 pPath
->SetModel(GetModel());
1236 pPath
->SetMergedItemSet(aSet
);
1237 pPath
->SetStyleSheet(pStyleSheet
, true);
1239 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1241 aSet
.Put(XLineEndWidthItem(0L));
1245 for(;nLoopStart
<nCount
;nLoopStart
++)
1248 aPolyPoly
.append(aTmpPolyPolygon
[nLoopStart
].getB2DPolygon());
1249 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1250 pPath
->SetModel(GetModel());
1251 pPath
->SetMergedItemSet(aSet
);
1252 pPath
->SetStyleSheet(pStyleSheet
, true);
1254 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1259 return ImpConvertAddText(pGroup
, bBezier
);
1267 sal_Bool
SdrMeasureObj::BegTextEdit(SdrOutliner
& rOutl
)
1270 return SdrTextObj::BegTextEdit(rOutl
);
1273 const Size
& SdrMeasureObj::GetTextSize() const
1275 if (bTextDirty
) UndirtyText();
1276 return SdrTextObj::GetTextSize();
1279 OutlinerParaObject
* SdrMeasureObj::GetOutlinerParaObject() const
1283 return SdrTextObj::GetOutlinerParaObject();
1286 void SdrMeasureObj::NbcSetOutlinerParaObject(OutlinerParaObject
* pTextObject
)
1288 SdrTextObj::NbcSetOutlinerParaObject(pTextObject
);
1289 if(SdrTextObj::GetOutlinerParaObject())
1290 SetTextDirty(); // recalculate text
1293 void SdrMeasureObj::TakeTextRect( SdrOutliner
& rOutliner
, Rectangle
& rTextRect
, bool bNoEditText
,
1294 Rectangle
* pAnchorRect
, bool bLineWidth
) const
1296 if (bTextDirty
) UndirtyText();
1297 SdrTextObj::TakeTextRect( rOutliner
, rTextRect
, bNoEditText
, pAnchorRect
, bLineWidth
);
1300 void SdrMeasureObj::TakeTextAnchorRect(Rectangle
& rAnchorRect
) const
1302 if (bTextDirty
) UndirtyText();
1303 SdrTextObj::TakeTextAnchorRect(rAnchorRect
);
1306 void SdrMeasureObj::TakeTextEditArea(Size
* pPaperMin
, Size
* pPaperMax
, Rectangle
* pViewInit
, Rectangle
* pViewMin
) const
1308 if (bTextDirty
) UndirtyText();
1309 SdrTextObj::TakeTextEditArea(pPaperMin
,pPaperMax
,pViewInit
,pViewMin
);
1312 sal_uInt16
SdrMeasureObj::GetOutlinerViewAnchorMode() const
1314 if (bTextDirty
) UndirtyText();
1316 ImpMeasurePoly aMPol
;
1318 ImpCalcGeometrics(aRec
,aMPol
);
1320 SdrTextHorzAdjust eTH
=GetTextHorizontalAdjust();
1321 SdrTextVertAdjust eTV
=GetTextVerticalAdjust();
1322 SdrMeasureTextHPos eMH
=aMPol
.eUsedTextHPos
;
1323 SdrMeasureTextVPos eMV
=aMPol
.eUsedTextVPos
;
1324 bool bTextRota90
=aRec
.bTextRota90
;
1325 bool bBelowRefEdge
=aRec
.bBelowRefEdge
;
1327 // TODO: bTextUpsideDown should be interpreted here!
1329 if (eMH
==SDRMEASURE_TEXTLEFTOUTSIDE
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1330 if (eMH
==SDRMEASURE_TEXTRIGHTOUTSIDE
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1331 // at eMH==SDRMEASURE_TEXTINSIDE we can anchor horizontally
1332 if (eMV
==SDRMEASURE_ABOVE
) eTV
=SDRTEXTVERTADJUST_BOTTOM
;
1333 if (eMV
==SDRMEASURE_BELOW
) eTV
=SDRTEXTVERTADJUST_TOP
;
1334 if (eMV
==SDRMEASURETEXT_BREAKEDLINE
|| eMV
==SDRMEASURETEXT_VERTICALCENTERED
) eTV
=SDRTEXTVERTADJUST_CENTER
;
1336 if (eMH
==SDRMEASURE_TEXTLEFTOUTSIDE
) eTV
=SDRTEXTVERTADJUST_BOTTOM
;
1337 if (eMH
==SDRMEASURE_TEXTRIGHTOUTSIDE
) eTV
=SDRTEXTVERTADJUST_TOP
;
1338 // at eMH==SDRMEASURE_TEXTINSIDE we can anchor vertically
1339 if (!bBelowRefEdge
) {
1340 if (eMV
==SDRMEASURE_ABOVE
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1341 if (eMV
==SDRMEASURE_BELOW
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1343 if (eMV
==SDRMEASURE_ABOVE
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1344 if (eMV
==SDRMEASURE_BELOW
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1346 if (eMV
==SDRMEASURETEXT_BREAKEDLINE
|| eMV
==SDRMEASURETEXT_VERTICALCENTERED
) eTH
=SDRTEXTHORZADJUST_CENTER
;
1349 EVAnchorMode eRet
=ANCHOR_BOTTOM_HCENTER
;
1350 if (eTH
==SDRTEXTHORZADJUST_LEFT
) {
1351 if (eTV
==SDRTEXTVERTADJUST_TOP
) eRet
=ANCHOR_TOP_LEFT
;
1352 else if (eTV
==SDRTEXTVERTADJUST_BOTTOM
) eRet
=ANCHOR_BOTTOM_LEFT
;
1353 else eRet
=ANCHOR_VCENTER_LEFT
;
1354 } else if (eTH
==SDRTEXTHORZADJUST_RIGHT
) {
1355 if (eTV
==SDRTEXTVERTADJUST_TOP
) eRet
=ANCHOR_TOP_RIGHT
;
1356 else if (eTV
==SDRTEXTVERTADJUST_BOTTOM
) eRet
=ANCHOR_BOTTOM_RIGHT
;
1357 else eRet
=ANCHOR_VCENTER_RIGHT
;
1359 if (eTV
==SDRTEXTVERTADJUST_TOP
) eRet
=ANCHOR_TOP_HCENTER
;
1360 else if (eTV
==SDRTEXTVERTADJUST_BOTTOM
) eRet
=ANCHOR_BOTTOM_HCENTER
;
1361 else eRet
=ANCHOR_VCENTER_HCENTER
;
1363 return (sal_uInt16
)eRet
;
1366 //////////////////////////////////////////////////////////////////////////////
1368 // TRGetBaseGeometry/TRSetBaseGeometry needs to be based on two positions,
1369 // same as line geometry in SdrPathObj. Thus needs to be overloaded and
1370 // implemented since currently it is derived from SdrTextObj which uses
1371 // a functionality based on SnapRect which is not useful here
1373 sal_Bool
SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
1375 // handle the same as a simple line since the definition is based on two points
1376 const basegfx::B2DRange
aRange(aPt1
.X(), aPt1
.Y(), aPt2
.X(), aPt2
.Y());
1377 basegfx::B2DTuple
aScale(aRange
.getRange());
1378 basegfx::B2DTuple
aTranslate(aRange
.getMinimum());
1380 // position maybe relative to anchor position, convert
1381 if( pModel
->IsWriter() )
1383 if(GetAnchorPos().X() || GetAnchorPos().Y())
1385 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1389 // force MapUnit to 100th mm
1390 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
1391 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
1395 case SFX_MAPUNIT_TWIP
:
1398 aTranslate
.setX(ImplTwipsToMM(aTranslate
.getX()));
1399 aTranslate
.setY(ImplTwipsToMM(aTranslate
.getY()));
1402 aScale
.setX(ImplTwipsToMM(aScale
.getX()));
1403 aScale
.setY(ImplTwipsToMM(aScale
.getY()));
1409 OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1414 // build return value matrix
1415 rMatrix
= basegfx::tools::createScaleTranslateB2DHomMatrix(aScale
, aTranslate
);
1420 void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
1422 // use given transformation to derive the two defining points from unit line
1423 basegfx::B2DPoint
aPosA(rMatrix
* basegfx::B2DPoint(0.0, 0.0));
1424 basegfx::B2DPoint
aPosB(rMatrix
* basegfx::B2DPoint(1.0, 0.0));
1426 // force metric to pool metric
1427 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
1428 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
1432 case SFX_MAPUNIT_TWIP
:
1435 aPosA
.setX(ImplMMToTwips(aPosA
.getX()));
1436 aPosA
.setY(ImplMMToTwips(aPosA
.getY()));
1437 aPosB
.setX(ImplMMToTwips(aPosB
.getX()));
1438 aPosB
.setY(ImplMMToTwips(aPosB
.getY()));
1444 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1449 if( pModel
->IsWriter() )
1451 // if anchor is used, make position relative to it
1452 if(GetAnchorPos().X() || GetAnchorPos().Y())
1454 const basegfx::B2DVector
aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y());
1456 aPosA
+= aAnchorOffset
;
1457 aPosB
+= aAnchorOffset
;
1461 // derive new model data
1462 const Point
aNewPt1(basegfx::fround(aPosA
.getX()), basegfx::fround(aPosA
.getY()));
1463 const Point
aNewPt2(basegfx::fround(aPosB
.getX()), basegfx::fround(aPosB
.getY()));
1465 if(aNewPt1
!= aPt1
|| aNewPt2
!= aPt2
)
1467 // set model values and broadcast
1468 Rectangle aBoundRect0
; if (pUserCall
!=NULL
) aBoundRect0
=GetLastBoundRect();
1476 BroadcastObjectChange();
1477 SendUserCall(SDRUSERCALL_MOVEONLY
,aBoundRect0
);
1481 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */