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 .
20 #include "svdconv.hxx"
21 #include "svdglob.hxx"
22 #include "svx/svdstr.hrc"
24 #include <basegfx/matrix/b2dhommatrix.hxx>
25 #include <basegfx/matrix/b2dhommatrixtools.hxx>
26 #include <basegfx/point/b2dpoint.hxx>
27 #include <basegfx/polygon/b2dpolygon.hxx>
28 #include <basegfx/polygon/b2dpolypolygon.hxx>
29 #include <editeng/editdata.hxx>
30 #include <editeng/editobj.hxx>
31 #include <editeng/eeitem.hxx>
32 #include <editeng/flditem.hxx>
33 #include <editeng/measfld.hxx>
34 #include <editeng/outliner.hxx>
35 #include <editeng/outlobj.hxx>
37 #include <svl/smplhint.hxx>
38 #include <svl/style.hxx>
40 #include <sdr/contact/viewcontactofsdrmeasureobj.hxx>
41 #include <sdr/properties/measureproperties.hxx>
42 #include <svx/svddrag.hxx>
43 #include <svx/svdhdl.hxx>
44 #include <svx/svdmodel.hxx>
45 #include <svx/svdogrp.hxx>
46 #include <svx/svdomeas.hxx>
47 #include <svx/svdopath.hxx>
48 #include <svx/svdoutl.hxx>
49 #include <svx/svdpage.hxx>
50 #include <svx/svdpool.hxx>
51 #include <svx/svdtrans.hxx>
52 #include <svx/svdview.hxx>
53 #include <svx/sxmbritm.hxx>
54 #include <svx/sxmfsitm.hxx>
55 #include <sxmkitm.hxx>
56 #include <svx/sxmlhitm.hxx>
57 #include <sxmoitm.hxx>
58 #include <sxmsitm.hxx>
59 #include <svx/sxmsuitm.hxx>
60 #include <sxmtaitm.hxx>
61 #include <svx/sxmtfitm.hxx>
62 #include <svx/sxmtpitm.hxx>
63 #include <svx/sxmtritm.hxx>
64 #include <svx/sxmuitm.hxx>
65 #include <svx/xlnedcit.hxx>
66 #include <svx/xlnedit.hxx>
67 #include <svx/xlnedwit.hxx>
68 #include <svx/xlnstcit.hxx>
69 #include <svx/xlnstit.hxx>
70 #include <svx/xlnstwit.hxx>
71 #include <svx/xlnwtit.hxx>
72 #include <svx/xpoly.hxx>
73 #include <unotools/syslocale.hxx>
77 SdrMeasureObjGeoData::SdrMeasureObjGeoData() {}
78 SdrMeasureObjGeoData::~SdrMeasureObjGeoData() {}
80 OUString
SdrMeasureObj::TakeRepresentation(SdrMeasureFieldKind eMeasureFieldKind
) const
83 Fraction
aMeasureScale(1, 1);
84 bool bTextRota90(false);
85 bool bShowUnit(false);
86 FieldUnit
eMeasureUnit(FUNIT_NONE
);
87 FieldUnit
eModUIUnit(FUNIT_NONE
);
89 const SfxItemSet
& rSet
= GetMergedItemSet();
90 bTextRota90
= ((SdrMeasureTextRota90Item
&)rSet
.Get(SDRATTR_MEASURETEXTROTA90
)).GetValue();
91 eMeasureUnit
= ((SdrMeasureUnitItem
&)rSet
.Get(SDRATTR_MEASUREUNIT
)).GetValue();
92 aMeasureScale
= ((SdrMeasureScaleItem
&)rSet
.Get(SDRATTR_MEASURESCALE
)).GetValue();
93 bShowUnit
= ((SdrMeasureShowUnitItem
&)rSet
.Get(SDRATTR_MEASURESHOWUNIT
)).GetValue();
94 sal_Int16 nNumDigits
= ((SdrMeasureDecimalPlacesItem
&)rSet
.Get(SDRATTR_MEASUREDECIMALPLACES
)).GetValue();
96 switch(eMeasureFieldKind
)
98 case SDRMEASUREFIELD_VALUE
:
102 eModUIUnit
= pModel
->GetUIUnit();
104 if(eMeasureUnit
== FUNIT_NONE
)
105 eMeasureUnit
= eModUIUnit
;
107 sal_Int32
nLen(GetLen(aPt2
- aPt1
));
110 if(eMeasureUnit
!= eModUIUnit
)
112 // for the unit conversion
113 aFact
*= GetMapFactor(eModUIUnit
, eMeasureUnit
).X();
116 if(aMeasureScale
.GetNumerator() != aMeasureScale
.GetDenominator())
118 aFact
*= aMeasureScale
;
121 if(aFact
.GetNumerator() != aFact
.GetDenominator())
123 // scale via BigInt, to avoid overruns
124 nLen
= BigMulDiv(nLen
, aFact
.GetNumerator(), aFact
.GetDenominator());
128 pModel
->TakeMetricStr(nLen
, aTmp
, true, nNumDigits
);
137 sal_Unicode
cDec(SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]);
139 if(aStr
.indexOf(cDec
) != -1)
141 sal_Int32
nLen2(aStr
.getLength() - 1);
143 while(aStr
[nLen2
] == '0')
145 aStr
= aStr
.copy(0, nLen2
);
149 if(aStr
[nLen2
] == cDec
)
151 aStr
= aStr
.copy(0, nLen2
);
161 // if there's no Model ... (e. g. preview in dialog)
167 case SDRMEASUREFIELD_UNIT
:
173 eModUIUnit
= pModel
->GetUIUnit();
175 if(eMeasureUnit
== FUNIT_NONE
)
176 eMeasureUnit
= eModUIUnit
;
179 pModel
->TakeUnitStr(eMeasureUnit
, aStr
);
185 case SDRMEASUREFIELD_ROTA90BLANCS
:
199 // BaseProperties section
201 sdr::properties::BaseProperties
* SdrMeasureObj::CreateObjectSpecificProperties()
203 return new sdr::properties::MeasureProperties(*this);
207 // DrawContact section
209 sdr::contact::ViewContact
* SdrMeasureObj::CreateObjectSpecificViewContact()
211 return new sdr::contact::ViewContactOfSdrMeasureObj(*this);
216 TYPEINIT1(SdrMeasureObj
,SdrTextObj
);
218 SdrMeasureObj::SdrMeasureObj():
222 mbSupportTextIndentingOnLineWidthChange
= false;
225 SdrMeasureObj::SdrMeasureObj(const Point
& rPt1
, const Point
& rPt2
):
231 mbSupportTextIndentingOnLineWidthChange
= false;
234 SdrMeasureObj::~SdrMeasureObj()
238 void SdrMeasureObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
240 rInfo
.bSelectAllowed
=true;
241 rInfo
.bMoveAllowed
=true;
242 rInfo
.bResizeFreeAllowed
=true;
243 rInfo
.bResizePropAllowed
=true;
244 rInfo
.bRotateFreeAllowed
=true;
245 rInfo
.bRotate90Allowed
=true;
246 rInfo
.bMirrorFreeAllowed
=true;
247 rInfo
.bMirror45Allowed
=true;
248 rInfo
.bMirror90Allowed
=true;
249 rInfo
.bTransparenceAllowed
= false;
250 rInfo
.bGradientAllowed
= false;
251 rInfo
.bShearAllowed
=true;
252 rInfo
.bEdgeRadiusAllowed
=false;
253 rInfo
.bNoOrthoDesired
=true;
254 rInfo
.bNoContortion
=false;
255 rInfo
.bCanConvToPath
=false;
256 rInfo
.bCanConvToPoly
=true;
257 rInfo
.bCanConvToPathLineToArea
=false;
258 rInfo
.bCanConvToPolyLineToArea
=false;
259 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
262 sal_uInt16
SdrMeasureObj::GetObjIdentifier() const
264 return (sal_uInt16
)OBJ_MEASURE
;
267 struct ImpMeasureRec
: public SdrDragStatUserData
271 SdrMeasureKind eKind
;
272 SdrMeasureTextHPos eWantTextHPos
;
273 SdrMeasureTextVPos eWantTextVPos
;
275 long nHelplineOverhang
;
281 bool bTextUpsideDown
;
282 long nMeasureOverhang
;
283 FieldUnit eMeasureUnit
;
284 Fraction aMeasureScale
;
286 OUString aFormatString
;
288 long nTextAutoAngleView
;
289 bool bTextIsFixedAngle
;
290 long nTextFixedAngle
;
299 struct ImpMeasurePoly
301 ImpLineRec aMainline1
; // those with the 1st arrowhead
302 ImpLineRec aMainline2
; // those with the 2nd arrowhead
303 ImpLineRec aMainline3
; // those in between
304 ImpLineRec aHelpline1
;
305 ImpLineRec aHelpline2
;
316 sal_uInt16 nMainlineAnz
;
317 SdrMeasureTextHPos eUsedTextHPos
;
318 SdrMeasureTextVPos eUsedTextVPos
;
319 long nLineWdt2
; // half the line width
320 long nArrow1Len
; // length of 1st arrowhead; for Center, use only half
321 long nArrow2Len
; // length of 2nd arrowhead; for Center, use only half
322 long nArrow1Wdt
; // width of 1st arrow
323 long nArrow2Wdt
; // width of 2nd arrow
324 long nShortLineLen
; // line length, if PfeileAussen (arrowheads on the outside)
325 bool bArrow1Center
; // arrowhead 1 centered?
326 bool bArrow2Center
; // arrowhead 2 centered?
327 bool bAutoUpsideDown
; // UpsideDown via automation
328 bool bPfeileAussen
; // arrowheads on the outside
332 void SdrMeasureObj::ImpTakeAttr(ImpMeasureRec
& rRec
) const
337 const SfxItemSet
& rSet
= GetObjectItemSet();
338 rRec
.eKind
=((SdrMeasureKindItem
& )rSet
.Get(SDRATTR_MEASUREKIND
)).GetValue();
339 rRec
.eWantTextHPos
=((SdrMeasureTextHPosItem
& )rSet
.Get(SDRATTR_MEASURETEXTHPOS
)).GetValue();
340 rRec
.eWantTextVPos
=((SdrMeasureTextVPosItem
& )rSet
.Get(SDRATTR_MEASURETEXTVPOS
)).GetValue();
341 rRec
.nLineDist
=((SdrMeasureLineDistItem
& )rSet
.Get(SDRATTR_MEASURELINEDIST
)).GetValue();
342 rRec
.nHelplineOverhang
=((SdrMeasureHelplineOverhangItem
&)rSet
.Get(SDRATTR_MEASUREHELPLINEOVERHANG
)).GetValue();
343 rRec
.nHelplineDist
=((SdrMeasureHelplineDistItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINEDIST
)).GetValue();
344 rRec
.nHelpline1Len
=((SdrMeasureHelpline1LenItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINE1LEN
)).GetValue();
345 rRec
.nHelpline2Len
=((SdrMeasureHelpline2LenItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINE2LEN
)).GetValue();
346 rRec
.bBelowRefEdge
=((SdrMeasureBelowRefEdgeItem
& )rSet
.Get(SDRATTR_MEASUREBELOWREFEDGE
)).GetValue();
347 rRec
.bTextRota90
=((SdrMeasureTextRota90Item
& )rSet
.Get(SDRATTR_MEASURETEXTROTA90
)).GetValue();
348 rRec
.bTextUpsideDown
=((SdrMeasureTextUpsideDownItem
& )rSet
.Get(SDRATTR_MEASURETEXTUPSIDEDOWN
)).GetValue();
349 rRec
.nMeasureOverhang
=((SdrMeasureOverhangItem
& )rSet
.Get(SDRATTR_MEASUREOVERHANG
)).GetValue();
350 rRec
.eMeasureUnit
=((SdrMeasureUnitItem
& )rSet
.Get(SDRATTR_MEASUREUNIT
)).GetValue();
351 rRec
.aMeasureScale
=((SdrMeasureScaleItem
& )rSet
.Get(SDRATTR_MEASURESCALE
)).GetValue();
352 rRec
.bShowUnit
=((SdrMeasureShowUnitItem
& )rSet
.Get(SDRATTR_MEASURESHOWUNIT
)).GetValue();
353 rRec
.aFormatString
=((SdrMeasureFormatStringItem
& )rSet
.Get(SDRATTR_MEASUREFORMATSTRING
)).GetValue();
354 rRec
.bTextAutoAngle
=((SdrMeasureTextAutoAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTAUTOANGLE
)).GetValue();
355 rRec
.nTextAutoAngleView
=((SdrMeasureTextAutoAngleViewItem
&)rSet
.Get(SDRATTR_MEASURETEXTAUTOANGLEVIEW
)).GetValue();
356 rRec
.bTextIsFixedAngle
=((SdrMeasureTextIsFixedAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTISFIXEDANGLE
)).GetValue();
357 rRec
.nTextFixedAngle
=((SdrMeasureTextFixedAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTFIXEDANGLE
)).GetValue();
360 long impGetLineStartEndDistance(const basegfx::B2DPolyPolygon
& rPolyPolygon
, long nNewWidth
, bool bCenter
)
362 const basegfx::B2DRange
aPolygonRange(rPolyPolygon
.getB2DRange());
363 const double fOldWidth(aPolygonRange
.getWidth() > 1.0 ? aPolygonRange
.getWidth() : 1.0);
364 const double fScale((double)nNewWidth
/ fOldWidth
);
365 long nHeight(basegfx::fround(aPolygonRange
.getHeight() * fScale
));
375 void SdrMeasureObj::ImpCalcGeometrics(const ImpMeasureRec
& rRec
, ImpMeasurePoly
& rPol
) const
377 Point
aP1(rRec
.aPt1
);
378 Point
aP2(rRec
.aPt2
);
379 Point
aDelt(aP2
); aDelt
-=aP1
;
381 rPol
.aTextSize
=GetTextSize();
382 rPol
.nLineLen
=GetLen(aDelt
);
385 long nArrow1Len
=0; bool bArrow1Center
=false;
386 long nArrow2Len
=0; bool bArrow2Center
=false;
393 bool bPfeileAussen
= false;
395 const SfxItemSet
& rSet
= GetObjectItemSet();
396 sal_Int32 nLineWdt
= ((XLineWidthItem
&)(rSet
.Get(XATTR_LINEWIDTH
))).GetValue(); // line width
397 rPol
.nLineWdt2
= (nLineWdt
+ 1) / 2;
399 nArrow1Wdt
= ((const XLineStartWidthItem
&)(rSet
.Get(XATTR_LINESTARTWIDTH
))).GetValue();
401 nArrow1Wdt
= -nLineWdt
* nArrow1Wdt
/ 100; // <0 = relativ
403 nArrow2Wdt
= ((const XLineEndWidthItem
&)(rSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
405 nArrow2Wdt
= -nLineWdt
* nArrow2Wdt
/ 100; // <0 = relativ
407 basegfx::B2DPolyPolygon
aPol1(((const XLineStartItem
&)(rSet
.Get(XATTR_LINESTART
))).GetLineStartValue());
408 basegfx::B2DPolyPolygon
aPol2(((const XLineEndItem
&)(rSet
.Get(XATTR_LINEEND
))).GetLineEndValue());
409 bArrow1Center
= ((const XLineStartCenterItem
&)(rSet
.Get(XATTR_LINESTARTCENTER
))).GetValue();
410 bArrow2Center
= ((const XLineEndCenterItem
&)(rSet
.Get(XATTR_LINEENDCENTER
))).GetValue();
411 nArrow1Len
= impGetLineStartEndDistance(aPol1
, nArrow1Wdt
, bArrow1Center
) - 1;
412 nArrow2Len
= impGetLineStartEndDistance(aPol2
, nArrow2Wdt
, bArrow2Center
) - 1;
414 // nArrowLen is already halved at bCenter.
415 // In the case of 2 arrowheads each 4mm long, we can't go below 10mm.
416 nArrowNeed
=nArrow1Len
+nArrow2Len
+(nArrow1Wdt
+nArrow2Wdt
)/2;
417 if (rPol
.nLineLen
<nArrowNeed
) bPfeileAussen
= true;
418 nShortLen
=(nArrow1Len
+nArrow1Wdt
+ nArrow2Len
+nArrow2Wdt
) /2;
420 rPol
.eUsedTextHPos
=rRec
.eWantTextHPos
;
421 rPol
.eUsedTextVPos
=rRec
.eWantTextVPos
;
422 if (rPol
.eUsedTextVPos
==SDRMEASURE_TEXTVAUTO
) rPol
.eUsedTextVPos
=SDRMEASURE_ABOVE
;
423 bool bBrkLine
=rPol
.eUsedTextVPos
==SDRMEASURETEXT_BREAKEDLINE
;
424 if (rPol
.eUsedTextVPos
==SDRMEASURETEXT_VERTICALCENTERED
)
426 OutlinerParaObject
* pOutlinerParaObject
= SdrTextObj::GetOutlinerParaObject();
427 if (pOutlinerParaObject
!=NULL
&& pOutlinerParaObject
->GetTextObject().GetParagraphCount()==1)
429 bBrkLine
=true; // dashed line if there's only on paragraph.
432 rPol
.bBreakedLine
=bBrkLine
;
433 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTHAUTO
) { // if text is too wide, push it outside
434 bool bOutside
= false;
435 long nNeedSiz
=!rRec
.bTextRota90
? rPol
.aTextSize
.Width() : rPol
.aTextSize
.Height();
436 if (nNeedSiz
>rPol
.nLineLen
) bOutside
= true; // text doesn't fit in between
438 if (nNeedSiz
+nArrowNeed
>rPol
.nLineLen
) bPfeileAussen
= true; // text fits in between, if arrowheads are on the outside
440 long nSmallNeed
=nArrow1Len
+nArrow2Len
+(nArrow1Wdt
+nArrow2Wdt
)/2/4;
441 if (nNeedSiz
+nSmallNeed
>rPol
.nLineLen
) bPfeileAussen
= true; // text fits in between, if arrowheads are on the outside
443 rPol
.eUsedTextHPos
=bOutside
? SDRMEASURE_TEXTLEFTOUTSIDE
: SDRMEASURE_TEXTINSIDE
;
445 if (rPol
.eUsedTextHPos
!=SDRMEASURE_TEXTINSIDE
) bPfeileAussen
= true;
446 rPol
.nArrow1Wdt
=nArrow1Wdt
;
447 rPol
.nArrow2Wdt
=nArrow2Wdt
;
448 rPol
.nShortLineLen
=nShortLen
;
449 rPol
.bPfeileAussen
=bPfeileAussen
;
450 rPol
.nArrow1Len
=nArrow1Len
;
451 rPol
.bArrow1Center
=bArrow1Center
;
452 rPol
.nArrow2Len
=nArrow2Len
;
453 rPol
.bArrow2Center
=bArrow2Center
;
455 rPol
.nLineWink
=GetAngle(aDelt
);
456 double a
=rPol
.nLineWink
*nPi180
;
457 double nLineSin
=sin(a
);
458 double nLineCos
=cos(a
);
459 rPol
.nLineSin
=nLineSin
;
460 rPol
.nLineCos
=nLineCos
;
462 rPol
.nTextWink
=rPol
.nLineWink
;
463 if (rRec
.bTextRota90
) rPol
.nTextWink
+=9000;
465 rPol
.bAutoUpsideDown
=false;
466 if (rRec
.bTextAutoAngle
) {
467 long nTmpWink
=NormAngle360(rPol
.nTextWink
-rRec
.nTextAutoAngleView
);
468 if (nTmpWink
>=18000) {
469 rPol
.nTextWink
+=18000;
470 rPol
.bAutoUpsideDown
=true;
474 if (rRec
.bTextUpsideDown
) rPol
.nTextWink
+=18000;
475 rPol
.nTextWink
=NormAngle360(rPol
.nTextWink
);
476 rPol
.nHlpWink
=rPol
.nLineWink
+9000;
477 if (rRec
.bBelowRefEdge
) rPol
.nHlpWink
+=18000;
478 rPol
.nHlpWink
=NormAngle360(rPol
.nHlpWink
);
479 double nHlpSin
=nLineCos
;
480 double nHlpCos
=-nLineSin
;
481 if (rRec
.bBelowRefEdge
) {
485 rPol
.nHlpSin
=nHlpSin
;
486 rPol
.nHlpCos
=nHlpCos
;
488 long nLineDist
=rRec
.nLineDist
;
489 long nOverhang
=rRec
.nHelplineOverhang
;
490 long nHelplineDist
=rRec
.nHelplineDist
;
492 long dx
= Round(nLineDist
*nHlpCos
);
493 long dy
=-Round(nLineDist
*nHlpSin
);
494 long dxh1a
= Round((nHelplineDist
-rRec
.nHelpline1Len
)*nHlpCos
);
495 long dyh1a
=-Round((nHelplineDist
-rRec
.nHelpline1Len
)*nHlpSin
);
496 long dxh1b
= Round((nHelplineDist
-rRec
.nHelpline2Len
)*nHlpCos
);
497 long dyh1b
=-Round((nHelplineDist
-rRec
.nHelpline2Len
)*nHlpSin
);
498 long dxh2
= Round((nLineDist
+nOverhang
)*nHlpCos
);
499 long dyh2
=-Round((nLineDist
+nOverhang
)*nHlpSin
);
502 rPol
.aHelpline1
.aP1
=Point(aP1
.X()+dxh1a
,aP1
.Y()+dyh1a
);
503 rPol
.aHelpline1
.aP2
=Point(aP1
.X()+dxh2
,aP1
.Y()+dyh2
);
506 rPol
.aHelpline2
.aP1
=Point(aP2
.X()+dxh1b
,aP2
.Y()+dyh1b
);
507 rPol
.aHelpline2
.aP2
=Point(aP2
.X()+dxh2
,aP2
.Y()+dyh2
);
510 Point
aMainlinePt1(aP1
.X()+dx
,aP1
.Y()+dy
);
511 Point
aMainlinePt2(aP2
.X()+dx
,aP2
.Y()+dy
);
512 if (!bPfeileAussen
) {
513 rPol
.aMainline1
.aP1
=aMainlinePt1
;
514 rPol
.aMainline1
.aP2
=aMainlinePt2
;
515 rPol
.aMainline2
=rPol
.aMainline1
;
516 rPol
.aMainline3
=rPol
.aMainline1
;
519 long nNeedSiz
=!rRec
.bTextRota90
? rPol
.aTextSize
.Width() : rPol
.aTextSize
.Height();
520 long nHalfLen
=(rPol
.nLineLen
-nNeedSiz
-nArrow1Wdt
/4-nArrow2Wdt
/4) /2;
522 rPol
.aMainline1
.aP2
=aMainlinePt1
;
523 rPol
.aMainline1
.aP2
.X()+=nHalfLen
;
524 RotatePoint(rPol
.aMainline1
.aP2
,rPol
.aMainline1
.aP1
,nLineSin
,nLineCos
);
525 rPol
.aMainline2
.aP1
=aMainlinePt2
;
526 rPol
.aMainline2
.aP1
.X()-=nHalfLen
;
527 RotatePoint(rPol
.aMainline2
.aP1
,rPol
.aMainline2
.aP2
,nLineSin
,nLineCos
);
530 long nLen1
=nShortLen
; // arrowhead's width as line length outside of the arrowhead
531 long nLen2
=nShortLen
;
532 long nTextWdt
=rRec
.bTextRota90
? rPol
.aTextSize
.Height() : rPol
.aTextSize
.Width();
534 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTLEFTOUTSIDE
) nLen1
=nArrow1Len
+nTextWdt
;
535 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTRIGHTOUTSIDE
) nLen2
=nArrow2Len
+nTextWdt
;
537 rPol
.aMainline1
.aP1
=aMainlinePt1
;
538 rPol
.aMainline1
.aP2
=aMainlinePt1
; rPol
.aMainline1
.aP2
.X()-=nLen1
; RotatePoint(rPol
.aMainline1
.aP2
,aMainlinePt1
,nLineSin
,nLineCos
);
539 rPol
.aMainline2
.aP1
=aMainlinePt2
; rPol
.aMainline2
.aP1
.X()+=nLen2
; RotatePoint(rPol
.aMainline2
.aP1
,aMainlinePt2
,nLineSin
,nLineCos
);
540 rPol
.aMainline2
.aP2
=aMainlinePt2
;
541 rPol
.aMainline3
.aP1
=aMainlinePt1
;
542 rPol
.aMainline3
.aP2
=aMainlinePt2
;
544 if (bBrkLine
&& rPol
.eUsedTextHPos
==SDRMEASURE_TEXTINSIDE
) rPol
.nMainlineAnz
=2;
548 basegfx::B2DPolyPolygon
SdrMeasureObj::ImpCalcXPoly(const ImpMeasurePoly
& rPol
) const
550 basegfx::B2DPolyPolygon aRetval
;
551 basegfx::B2DPolygon aPartPolyA
;
552 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline1
.aP1
.X(), rPol
.aMainline1
.aP1
.Y()));
553 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline1
.aP2
.X(), rPol
.aMainline1
.aP2
.Y()));
554 aRetval
.append(aPartPolyA
);
556 if(rPol
.nMainlineAnz
> 1)
559 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline2
.aP1
.X(), rPol
.aMainline2
.aP1
.Y()));
560 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline2
.aP2
.X(), rPol
.aMainline2
.aP2
.Y()));
561 aRetval
.append(aPartPolyA
);
564 if(rPol
.nMainlineAnz
> 2)
567 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline3
.aP1
.X(), rPol
.aMainline3
.aP1
.Y()));
568 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline3
.aP2
.X(), rPol
.aMainline3
.aP2
.Y()));
569 aRetval
.append(aPartPolyA
);
573 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline1
.aP1
.X(), rPol
.aHelpline1
.aP1
.Y()));
574 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline1
.aP2
.X(), rPol
.aHelpline1
.aP2
.Y()));
575 aRetval
.append(aPartPolyA
);
578 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline2
.aP1
.X(), rPol
.aHelpline2
.aP1
.Y()));
579 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline2
.aP2
.X(), rPol
.aHelpline2
.aP2
.Y()));
580 aRetval
.append(aPartPolyA
);
585 bool SdrMeasureObj::CalcFieldValue(const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_uInt16 nPos
,
587 Color
*& rpTxtColor
, Color
*& rpFldColor
, OUString
& rRet
) const
589 const SvxFieldData
* pField
=rField
.GetField();
590 SdrMeasureField
* pMeasureField
=PTR_CAST(SdrMeasureField
,pField
);
591 if (pMeasureField
!=NULL
) {
592 rRet
= TakeRepresentation(pMeasureField
->GetMeasureFieldKind());
593 if (rpFldColor
!=NULL
) {
602 return SdrTextObj::CalcFieldValue(rField
,nPara
,nPos
,bEdit
,rpTxtColor
,rpFldColor
,rRet
);
606 void SdrMeasureObj::UndirtyText() const
610 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
611 OutlinerParaObject
* pOutlinerParaObject
= SdrTextObj::GetOutlinerParaObject();
612 if(pOutlinerParaObject
==NULL
)
614 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS
), EE_FEATURE_FIELD
), ESelection(0,0));
615 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_VALUE
), EE_FEATURE_FIELD
),ESelection(0,1));
616 rOutliner
.QuickInsertText(" ", ESelection(0,2));
617 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_UNIT
), EE_FEATURE_FIELD
),ESelection(0,3));
618 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS
), EE_FEATURE_FIELD
),ESelection(0,4));
621 rOutliner
.SetStyleSheet(0, GetStyleSheet());
623 rOutliner
.SetParaAttribs(0, GetObjectItemSet());
626 const_cast<SdrMeasureObj
*>(this)->NbcSetOutlinerParaObject( rOutliner
.CreateParaObject() );
630 rOutliner
.SetText(*pOutlinerParaObject
);
633 rOutliner
.SetUpdateMode(true);
634 rOutliner
.UpdateFields();
635 Size
aSiz(rOutliner
.CalcTextSize());
637 // cast to nonconst three times
638 ((SdrMeasureObj
*)this)->aTextSize
=aSiz
;
639 ((SdrMeasureObj
*)this)->bTextSizeDirty
=false;
640 ((SdrMeasureObj
*)this)->bTextDirty
=false;
644 void SdrMeasureObj::TakeUnrotatedSnapRect(Rectangle
& rRect
) const
646 if (bTextDirty
) UndirtyText();
648 ImpMeasurePoly aMPol
;
650 ImpCalcGeometrics(aRec
,aMPol
);
652 // determine TextSize including text frame margins
653 Size
aTextSize2(aMPol
.aTextSize
);
654 if (aTextSize2
.Width()<1) aTextSize2
.Width()=1;
655 if (aTextSize2
.Height()<1) aTextSize2
.Height()=1;
656 aTextSize2
.Width()+=GetTextLeftDistance()+GetTextRightDistance();
657 aTextSize2
.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
659 Point
aPt1b(aMPol
.aMainline1
.aP1
);
660 long nLen
=aMPol
.nLineLen
;
661 long nLWdt
=aMPol
.nLineWdt2
;
662 long nArr1Len
=aMPol
.nArrow1Len
;
663 long nArr2Len
=aMPol
.nArrow2Len
;
664 if (aMPol
.bBreakedLine
) {
665 // In the case of a dashed line and Outside, the text should be
666 // placed next to the line at the arrowhead instead of directly
668 nArr1Len
=aMPol
.nShortLineLen
+aMPol
.nArrow1Wdt
/4;
669 nArr2Len
=aMPol
.nShortLineLen
+aMPol
.nArrow2Wdt
/4;
673 bool bRota90
=aRec
.bTextRota90
;
674 bool bUpsideDown
=aRec
.bTextUpsideDown
!=aMPol
.bAutoUpsideDown
;
675 bool bBelowRefEdge
=aRec
.bBelowRefEdge
;
676 SdrMeasureTextHPos eMH
=aMPol
.eUsedTextHPos
;
677 SdrMeasureTextVPos eMV
=aMPol
.eUsedTextVPos
;
680 case SDRMEASURE_TEXTLEFTOUTSIDE
: aTextPos
.X()=aPt1b
.X()-aTextSize2
.Width()-nArr1Len
-nLWdt
; break;
681 case SDRMEASURE_TEXTRIGHTOUTSIDE
: aTextPos
.X()=aPt1b
.X()+nLen
+nArr2Len
+nLWdt
; break;
682 default: aTextPos
.X()=aPt1b
.X(); aTextSize2
.Width()=nLen
;
685 case SDRMEASURETEXT_VERTICALCENTERED
:
686 case SDRMEASURETEXT_BREAKEDLINE
: aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()/2; break;
687 case SDRMEASURE_BELOW
: {
688 if (!bUpsideDown
) aTextPos
.Y()=aPt1b
.Y()+nLWdt
;
689 else aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()-nLWdt
;
692 if (!bUpsideDown
) aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()-nLWdt
;
693 else aTextPos
.Y()=aPt1b
.Y()+nLWdt
;
697 aTextPos
.X()+=aTextSize2
.Width();
698 aTextPos
.Y()+=aTextSize2
.Height();
700 } else { // also if bTextRota90==TRUE
702 case SDRMEASURE_TEXTLEFTOUTSIDE
: aTextPos
.X()=aPt1b
.X()-aTextSize2
.Height()-nArr1Len
; break;
703 case SDRMEASURE_TEXTRIGHTOUTSIDE
: aTextPos
.X()=aPt1b
.X()+nLen
+nArr2Len
; break;
704 default: aTextPos
.X()=aPt1b
.X(); aTextSize2
.Height()=nLen
;
707 case SDRMEASURETEXT_VERTICALCENTERED
:
708 case SDRMEASURETEXT_BREAKEDLINE
: aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()/2; break;
709 case SDRMEASURE_BELOW
: {
710 if (!bBelowRefEdge
) aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()+nLWdt
;
711 else aTextPos
.Y()=aPt1b
.Y()-nLWdt
;
714 if (!bBelowRefEdge
) aTextPos
.Y()=aPt1b
.Y()-nLWdt
;
715 else aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()+nLWdt
;
719 aTextPos
.X()+=aTextSize2
.Height();
720 aTextPos
.Y()-=aTextSize2
.Width();
723 if (aMPol
.nTextWink
!=aGeo
.nDrehWink
) {
724 ((SdrMeasureObj
*)this)->aGeo
.nDrehWink
=aMPol
.nTextWink
;
725 ((SdrMeasureObj
*)this)->aGeo
.RecalcSinCos();
727 RotatePoint(aTextPos
,aPt1b
,aMPol
.nLineSin
,aMPol
.nLineCos
);
728 aTextSize2
.Width()++; aTextSize2
.Height()++; // because of the Rect-Ctor's odd behavior
729 rRect
=Rectangle(aTextPos
,aTextSize2
);
731 ((SdrMeasureObj
*)this)->aRect
=rRect
;
733 if (aMPol
.nTextWink
!=aGeo
.nDrehWink
) {
734 ((SdrMeasureObj
*)this)->aGeo
.nDrehWink
=aMPol
.nTextWink
;
735 ((SdrMeasureObj
*)this)->aGeo
.RecalcSinCos();
739 SdrMeasureObj
* SdrMeasureObj::Clone() const
741 return CloneHelper
< SdrMeasureObj
>();
744 OUString
SdrMeasureObj::TakeObjNameSingul() const
746 OUStringBuffer
sName(ImpGetResStr(STR_ObjNameSingulMEASURE
));
748 OUString
aName( GetName() );
749 if (!aName
.isEmpty())
757 return sName
.makeStringAndClear();
760 OUString
SdrMeasureObj::TakeObjNamePlural() const
762 return ImpGetResStr(STR_ObjNamePluralMEASURE
);
765 basegfx::B2DPolyPolygon
SdrMeasureObj::TakeXorPoly() const
768 ImpMeasurePoly aMPol
;
770 ImpCalcGeometrics(aRec
,aMPol
);
771 return ImpCalcXPoly(aMPol
);
774 sal_uInt32
SdrMeasureObj::GetHdlCount() const
779 SdrHdl
* SdrMeasureObj::GetHdl(sal_uInt32 nHdlNum
) const
782 ImpMeasurePoly aMPol
;
784 aRec
.nHelplineDist
=0;
785 ImpCalcGeometrics(aRec
,aMPol
);
789 case 0: aPt
=aMPol
.aHelpline1
.aP1
; break;
790 case 1: aPt
=aMPol
.aHelpline2
.aP1
; break;
791 case 2: aPt
=aPt1
; break;
792 case 3: aPt
=aPt2
; break;
793 case 4: aPt
=aMPol
.aHelpline1
.aP2
; break;
794 case 5: aPt
=aMPol
.aHelpline2
.aP2
; break;
796 SdrHdl
* pHdl
=new ImpMeasureHdl(aPt
,HDL_USER
);
797 pHdl
->SetObjHdlNum(nHdlNum
);
798 pHdl
->SetDrehWink(aMPol
.nLineWink
);
804 bool SdrMeasureObj::hasSpecialDrag() const
809 bool SdrMeasureObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
811 const SdrHdl
* pHdl
= rDrag
.GetHdl();
815 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
817 if(nHdlNum
!= 2 && nHdlNum
!= 3)
819 rDrag
.SetEndDragChangesAttributes(true);
828 bool SdrMeasureObj::applySpecialDrag(SdrDragStat
& rDrag
)
830 ImpMeasureRec aMeasureRec
;
831 const SdrHdl
* pHdl
= rDrag
.GetHdl();
832 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
834 ImpTakeAttr(aMeasureRec
);
835 ImpEvalDrag(aMeasureRec
, rDrag
);
841 aPt1
= aMeasureRec
.aPt1
;
847 aPt2
= aMeasureRec
.aPt2
;
858 ImpMeasureRec aOrigMeasureRec
;
859 ImpTakeAttr(aOrigMeasureRec
);
861 if(aMeasureRec
.nHelpline1Len
!= aOrigMeasureRec
.nHelpline1Len
)
863 SetObjectItem(SdrMeasureHelpline1LenItem(aMeasureRec
.nHelpline1Len
));
866 if(aMeasureRec
.nHelpline2Len
!= aOrigMeasureRec
.nHelpline2Len
)
868 SetObjectItem(SdrMeasureHelpline2LenItem(aMeasureRec
.nHelpline2Len
));
877 ImpMeasureRec aOrigMeasureRec
;
878 ImpTakeAttr(aOrigMeasureRec
);
880 if(aMeasureRec
.nLineDist
!= aOrigMeasureRec
.nLineDist
)
882 SetObjectItem(SdrMeasureLineDistItem(aMeasureRec
.nLineDist
));
885 if(aMeasureRec
.bBelowRefEdge
!= aOrigMeasureRec
.bBelowRefEdge
)
887 SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec
.bBelowRefEdge
));
900 OUString
SdrMeasureObj::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
905 void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec
& rRec
, const SdrDragStat
& rDrag
) const
907 long nLineWink
=GetAngle(rRec
.aPt2
-rRec
.aPt1
);
908 double a
=nLineWink
*nPi180
;
912 const SdrHdl
* pHdl
=rDrag
.GetHdl();
913 sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
914 bool bOrtho
=rDrag
.GetView()!=NULL
&& rDrag
.GetView()->IsOrtho();
915 bool bBigOrtho
=bOrtho
&& rDrag
.GetView()->IsBigOrtho();
916 bool bBelow
=rRec
.bBelowRefEdge
;
917 Point
aPt(rDrag
.GetNow());
921 RotatePoint(aPt
,aPt1
,nSin
,-nCos
);
922 rRec
.nHelpline1Len
=aPt1
.Y()-aPt
.Y();
923 if (bBelow
) rRec
.nHelpline1Len
=-rRec
.nHelpline1Len
;
924 if (bOrtho
) rRec
.nHelpline2Len
=rRec
.nHelpline1Len
;
927 RotatePoint(aPt
,aPt2
,nSin
,-nCos
);
928 rRec
.nHelpline2Len
=aPt2
.Y()-aPt
.Y();
929 if (bBelow
) rRec
.nHelpline2Len
=-rRec
.nHelpline2Len
;
930 if (bOrtho
) rRec
.nHelpline1Len
=rRec
.nHelpline2Len
;
933 bool bAnf
=nHdlNum
==2;
934 Point
& rMov
=bAnf
? rRec
.aPt1
: rRec
.aPt2
;
936 Point
aFix(bAnf
? rRec
.aPt2
: rRec
.aPt1
);
938 long ndx0
=aMov
.X()-aFix
.X();
939 long ndy0
=aMov
.Y()-aFix
.Y();
942 if (!bHLin
|| !bVLin
) { // else aPt1==aPt2
943 long ndx
=aPt
.X()-aFix
.X();
944 long ndy
=aPt
.Y()-aFix
.Y();
945 double nXFact
=0; if (!bVLin
) nXFact
=(double)ndx
/(double)ndx0
;
946 double nYFact
=0; if (!bHLin
) nYFact
=(double)ndy
/(double)ndy0
;
947 bool bHor
=bHLin
|| (!bVLin
&& (nXFact
>nYFact
) ==bBigOrtho
);
948 bool bVer
=bVLin
|| (!bHLin
&& (nXFact
<=nYFact
)==bBigOrtho
);
949 if (bHor
) ndy
=long(ndy0
*nXFact
);
950 if (bVer
) ndx
=long(ndx0
*nYFact
);
959 long nVal0
=rRec
.nLineDist
;
960 RotatePoint(aPt
,(nHdlNum
==4 ? aPt1
: aPt2
),nSin
,-nCos
);
961 rRec
.nLineDist
=aPt
.Y()- (nHdlNum
==4 ? aPt1
.Y() : aPt2
.Y());
962 if (bBelow
) rRec
.nLineDist
=-rRec
.nLineDist
;
963 if (rRec
.nLineDist
<0) {
964 rRec
.nLineDist
=-rRec
.nLineDist
;
965 rRec
.bBelowRefEdge
=!bBelow
;
967 rRec
.nLineDist
-=rRec
.nHelplineOverhang
;
968 if (bOrtho
) rRec
.nLineDist
=nVal0
;
975 bool SdrMeasureObj::BegCreate(SdrDragStat
& rStat
)
977 rStat
.SetOrtho8Possible();
978 aPt1
=rStat
.GetStart();
984 bool SdrMeasureObj::MovCreate(SdrDragStat
& rStat
)
986 SdrView
* pView
=rStat
.GetView();
987 aPt1
=rStat
.GetStart();
989 if (pView
!=NULL
&& pView
->IsCreate1stPointAsCenter()) {
999 bool SdrMeasureObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
1003 return (eCmd
==SDRCREATE_FORCEEND
|| rStat
.GetPointAnz()>=2);
1006 bool SdrMeasureObj::BckCreate(SdrDragStat
& /*rStat*/)
1011 void SdrMeasureObj::BrkCreate(SdrDragStat
& /*rStat*/)
1015 basegfx::B2DPolyPolygon
SdrMeasureObj::TakeCreatePoly(const SdrDragStat
& /*rDrag*/) const
1018 ImpMeasurePoly aMPol
;
1021 ImpCalcGeometrics(aRec
, aMPol
);
1023 return ImpCalcXPoly(aMPol
);
1026 Pointer
SdrMeasureObj::GetCreatePointer() const
1028 return Pointer(POINTER_CROSS
);
1031 void SdrMeasureObj::NbcMove(const Size
& rSiz
)
1033 SdrTextObj::NbcMove(rSiz
);
1034 MovePoint(aPt1
,rSiz
);
1035 MovePoint(aPt2
,rSiz
);
1038 void SdrMeasureObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
1040 SdrTextObj::NbcResize(rRef
,xFact
,yFact
);
1041 ResizePoint(aPt1
,rRef
,xFact
,yFact
);
1042 ResizePoint(aPt2
,rRef
,xFact
,yFact
);
1046 void SdrMeasureObj::NbcRotate(const Point
& rRef
, long nWink
, double sn
, double cs
)
1048 SdrTextObj::NbcRotate(rRef
,nWink
,sn
,cs
);
1049 long nLen0
=GetLen(aPt2
-aPt1
);
1050 RotatePoint(aPt1
,rRef
,sn
,cs
);
1051 RotatePoint(aPt2
,rRef
,sn
,cs
);
1052 long nLen1
=GetLen(aPt2
-aPt1
);
1053 if (nLen1
!=nLen0
) { // rounding error!
1054 long dx
=aPt2
.X()-aPt1
.X();
1055 long dy
=aPt2
.Y()-aPt1
.Y();
1056 dx
=BigMulDiv(dx
,nLen0
,nLen1
);
1057 dy
=BigMulDiv(dy
,nLen0
,nLen1
);
1059 aPt1
.X()=aPt2
.X()-dx
;
1060 aPt1
.Y()=aPt2
.Y()-dy
;
1062 aPt2
.X()=aPt1
.X()+dx
;
1063 aPt2
.Y()=aPt1
.Y()+dy
;
1069 void SdrMeasureObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
1071 SdrTextObj::NbcMirror(rRef1
,rRef2
);
1072 MirrorPoint(aPt1
,rRef1
,rRef2
);
1073 MirrorPoint(aPt2
,rRef1
,rRef2
);
1077 void SdrMeasureObj::NbcShear(const Point
& rRef
, long nWink
, double tn
, bool bVShear
)
1079 SdrTextObj::NbcShear(rRef
,nWink
,tn
,bVShear
);
1080 ShearPoint(aPt1
,rRef
,tn
,bVShear
);
1081 ShearPoint(aPt2
,rRef
,tn
,bVShear
);
1086 long SdrMeasureObj::GetRotateAngle() const
1088 return GetAngle(aPt2
-aPt1
);
1091 void SdrMeasureObj::RecalcSnapRect()
1094 ImpMeasurePoly aMPol
;
1098 ImpCalcGeometrics(aRec
, aMPol
);
1099 aXPP
= XPolyPolygon(ImpCalcXPoly(aMPol
));
1100 maSnapRect
= aXPP
.GetBoundRect();
1103 sal_uInt32
SdrMeasureObj::GetSnapPointCount() const
1108 Point
SdrMeasureObj::GetSnapPoint(sal_uInt32 i
) const
1110 if (i
==0) return aPt1
;
1114 bool SdrMeasureObj::IsPolyObj() const
1119 sal_uInt32
SdrMeasureObj::GetPointCount() const
1124 Point
SdrMeasureObj::GetPoint(sal_uInt32 i
) const
1126 return (0L == i
) ? aPt1
: aPt2
;
1129 void SdrMeasureObj::NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
)
1139 SdrObjGeoData
* SdrMeasureObj::NewGeoData() const
1141 return new SdrMeasureObjGeoData
;
1144 void SdrMeasureObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
1146 SdrTextObj::SaveGeoData(rGeo
);
1147 SdrMeasureObjGeoData
& rMGeo
=(SdrMeasureObjGeoData
&)rGeo
;
1152 void SdrMeasureObj::RestGeoData(const SdrObjGeoData
& rGeo
)
1154 SdrTextObj::RestGeoData(rGeo
);
1155 SdrMeasureObjGeoData
& rMGeo
=(SdrMeasureObjGeoData
&)rGeo
;
1161 SdrObject
* SdrMeasureObj::DoConvertToPolyObj(bool bBezier
, bool bAddText
) const
1163 // get XOR Poly as base
1164 XPolyPolygon
aTmpPolyPolygon(TakeXorPoly());
1166 // get local ItemSet and StyleSheet
1167 SfxItemSet
aSet(GetObjectItemSet());
1168 SfxStyleSheet
* pStyleSheet
= GetStyleSheet();
1171 SdrObjGroup
* pGroup
= new SdrObjGroup
;
1172 pGroup
->SetModel(GetModel());
1174 // prepare parameters
1175 basegfx::B2DPolyPolygon aPolyPoly
;
1177 sal_uInt16
nCount(aTmpPolyPolygon
.Count());
1178 sal_uInt16
nLoopStart(0);
1182 // three lines, first one is the middle one
1184 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1186 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1187 pPath
->SetModel(GetModel());
1188 pPath
->SetMergedItemSet(aSet
);
1189 pPath
->SetStyleSheet(pStyleSheet
, true);
1190 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1191 aSet
.Put(XLineStartWidthItem(0L));
1192 aSet
.Put(XLineEndWidthItem(0L));
1195 else if(nCount
== 4)
1197 // four lines, middle line with gap, so there are two lines used
1198 // which have one arrow each
1199 sal_Int32 nEndWidth
= ((const XLineEndWidthItem
&)(aSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
1200 aSet
.Put(XLineEndWidthItem(0L));
1203 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1204 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1205 pPath
->SetModel(GetModel());
1206 pPath
->SetMergedItemSet(aSet
);
1207 pPath
->SetStyleSheet(pStyleSheet
, true);
1209 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1211 aSet
.Put(XLineEndWidthItem(nEndWidth
));
1212 aSet
.Put(XLineStartWidthItem(0L));
1215 aPolyPoly
.append(aTmpPolyPolygon
[1].getB2DPolygon());
1216 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1217 pPath
->SetModel(GetModel());
1218 pPath
->SetMergedItemSet(aSet
);
1219 pPath
->SetStyleSheet(pStyleSheet
, true);
1221 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1223 aSet
.Put(XLineEndWidthItem(0L));
1226 else if(nCount
== 5)
1228 // five lines, first two are the outer ones
1229 sal_Int32 nEndWidth
= ((const XLineEndWidthItem
&)(aSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
1231 aSet
.Put(XLineEndWidthItem(0L));
1234 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1235 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1236 pPath
->SetModel(GetModel());
1237 pPath
->SetMergedItemSet(aSet
);
1238 pPath
->SetStyleSheet(pStyleSheet
, true);
1240 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1242 aSet
.Put(XLineEndWidthItem(nEndWidth
));
1243 aSet
.Put(XLineStartWidthItem(0L));
1246 aPolyPoly
.append(aTmpPolyPolygon
[1].getB2DPolygon());
1247 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1248 pPath
->SetModel(GetModel());
1249 pPath
->SetMergedItemSet(aSet
);
1250 pPath
->SetStyleSheet(pStyleSheet
, true);
1252 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1254 aSet
.Put(XLineEndWidthItem(0L));
1258 for(;nLoopStart
<nCount
;nLoopStart
++)
1261 aPolyPoly
.append(aTmpPolyPolygon
[nLoopStart
].getB2DPolygon());
1262 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1263 pPath
->SetModel(GetModel());
1264 pPath
->SetMergedItemSet(aSet
);
1265 pPath
->SetStyleSheet(pStyleSheet
, true);
1267 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1272 return ImpConvertAddText(pGroup
, bBezier
);
1280 bool SdrMeasureObj::BegTextEdit(SdrOutliner
& rOutl
)
1283 return SdrTextObj::BegTextEdit(rOutl
);
1286 const Size
& SdrMeasureObj::GetTextSize() const
1288 if (bTextDirty
) UndirtyText();
1289 return SdrTextObj::GetTextSize();
1292 OutlinerParaObject
* SdrMeasureObj::GetOutlinerParaObject() const
1296 return SdrTextObj::GetOutlinerParaObject();
1299 void SdrMeasureObj::NbcSetOutlinerParaObject(OutlinerParaObject
* pTextObject
)
1301 SdrTextObj::NbcSetOutlinerParaObject(pTextObject
);
1302 if(SdrTextObj::GetOutlinerParaObject())
1303 SetTextDirty(); // recalculate text
1306 void SdrMeasureObj::TakeTextRect( SdrOutliner
& rOutliner
, Rectangle
& rTextRect
, bool bNoEditText
,
1307 Rectangle
* pAnchorRect
, bool bLineWidth
) const
1309 if (bTextDirty
) UndirtyText();
1310 SdrTextObj::TakeTextRect( rOutliner
, rTextRect
, bNoEditText
, pAnchorRect
, bLineWidth
);
1313 void SdrMeasureObj::TakeTextAnchorRect(Rectangle
& rAnchorRect
) const
1315 if (bTextDirty
) UndirtyText();
1316 SdrTextObj::TakeTextAnchorRect(rAnchorRect
);
1319 void SdrMeasureObj::TakeTextEditArea(Size
* pPaperMin
, Size
* pPaperMax
, Rectangle
* pViewInit
, Rectangle
* pViewMin
) const
1321 if (bTextDirty
) UndirtyText();
1322 SdrTextObj::TakeTextEditArea(pPaperMin
,pPaperMax
,pViewInit
,pViewMin
);
1325 sal_uInt16
SdrMeasureObj::GetOutlinerViewAnchorMode() const
1327 if (bTextDirty
) UndirtyText();
1329 ImpMeasurePoly aMPol
;
1331 ImpCalcGeometrics(aRec
,aMPol
);
1333 SdrTextHorzAdjust eTH
=GetTextHorizontalAdjust();
1334 SdrTextVertAdjust eTV
=GetTextVerticalAdjust();
1335 SdrMeasureTextHPos eMH
=aMPol
.eUsedTextHPos
;
1336 SdrMeasureTextVPos eMV
=aMPol
.eUsedTextVPos
;
1337 bool bTextRota90
=aRec
.bTextRota90
;
1338 bool bBelowRefEdge
=aRec
.bBelowRefEdge
;
1340 // TODO: bTextUpsideDown should be interpreted here!
1342 if (eMH
==SDRMEASURE_TEXTLEFTOUTSIDE
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1343 if (eMH
==SDRMEASURE_TEXTRIGHTOUTSIDE
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1344 // at eMH==SDRMEASURE_TEXTINSIDE we can anchor horizontally
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
;
1349 if (eMH
==SDRMEASURE_TEXTLEFTOUTSIDE
) eTV
=SDRTEXTVERTADJUST_BOTTOM
;
1350 if (eMH
==SDRMEASURE_TEXTRIGHTOUTSIDE
) eTV
=SDRTEXTVERTADJUST_TOP
;
1351 // at eMH==SDRMEASURE_TEXTINSIDE we can anchor vertically
1352 if (!bBelowRefEdge
) {
1353 if (eMV
==SDRMEASURE_ABOVE
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1354 if (eMV
==SDRMEASURE_BELOW
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1356 if (eMV
==SDRMEASURE_ABOVE
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1357 if (eMV
==SDRMEASURE_BELOW
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1359 if (eMV
==SDRMEASURETEXT_BREAKEDLINE
|| eMV
==SDRMEASURETEXT_VERTICALCENTERED
) eTH
=SDRTEXTHORZADJUST_CENTER
;
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
;
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
;
1376 return (sal_uInt16
)eRet
;
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
1386 bool SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
1388 // handle the same as a simple line since the definition is based on two points
1389 const basegfx::B2DRange
aRange(aPt1
.X(), aPt1
.Y(), aPt2
.X(), aPt2
.Y());
1390 basegfx::B2DTuple
aScale(aRange
.getRange());
1391 basegfx::B2DTuple
aTranslate(aRange
.getMinimum());
1393 // position maybe relative to anchor position, convert
1394 if( pModel
->IsWriter() )
1396 if(GetAnchorPos().X() || GetAnchorPos().Y())
1398 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1402 // force MapUnit to 100th mm
1403 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
1404 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
1408 case SFX_MAPUNIT_TWIP
:
1411 aTranslate
.setX(ImplTwipsToMM(aTranslate
.getX()));
1412 aTranslate
.setY(ImplTwipsToMM(aTranslate
.getY()));
1415 aScale
.setX(ImplTwipsToMM(aScale
.getX()));
1416 aScale
.setY(ImplTwipsToMM(aScale
.getY()));
1422 OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1427 // build return value matrix
1428 rMatrix
= basegfx::tools::createScaleTranslateB2DHomMatrix(aScale
, aTranslate
);
1433 void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
1435 // use given transformation to derive the two defining points from unit line
1436 basegfx::B2DPoint
aPosA(rMatrix
* basegfx::B2DPoint(0.0, 0.0));
1437 basegfx::B2DPoint
aPosB(rMatrix
* basegfx::B2DPoint(1.0, 0.0));
1439 // force metric to pool metric
1440 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
1441 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
1445 case SFX_MAPUNIT_TWIP
:
1448 aPosA
.setX(ImplMMToTwips(aPosA
.getX()));
1449 aPosA
.setY(ImplMMToTwips(aPosA
.getY()));
1450 aPosB
.setX(ImplMMToTwips(aPosB
.getX()));
1451 aPosB
.setY(ImplMMToTwips(aPosB
.getY()));
1457 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1462 if( pModel
->IsWriter() )
1464 // if anchor is used, make position relative to it
1465 if(GetAnchorPos().X() || GetAnchorPos().Y())
1467 const basegfx::B2DVector
aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y());
1469 aPosA
+= aAnchorOffset
;
1470 aPosB
+= aAnchorOffset
;
1474 // derive new model data
1475 const Point
aNewPt1(basegfx::fround(aPosA
.getX()), basegfx::fround(aPosA
.getY()));
1476 const Point
aNewPt2(basegfx::fround(aPosB
.getX()), basegfx::fround(aPosB
.getY()));
1478 if(aNewPt1
!= aPt1
|| aNewPt2
!= aPt2
)
1480 // set model values and broadcast
1481 Rectangle aBoundRect0
; if (pUserCall
!=NULL
) aBoundRect0
=GetLastBoundRect();
1489 BroadcastObjectChange();
1490 SendUserCall(SDRUSERCALL_MOVEONLY
,aBoundRect0
);
1494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */