1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svdomeas.cxx,v $
10 * $Revision: 1.35.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <svx/svdomeas.hxx>
36 #include "svditext.hxx" //
37 #include <svx/xpoly.hxx>
38 #include <svx/svdtrans.hxx>
39 #include <svx/svdhdl.hxx>
40 #include <svx/svdoutl.hxx>
41 #include <svx/svddrag.hxx>
42 #include <svx/svdpool.hxx>
43 #include <svx/svdattrx.hxx>
44 #include <svx/svdmodel.hxx>
45 #include <svx/svdview.hxx>
46 #include "svdglob.hxx" // StringCache
47 #include "svdstr.hrc" // Objektname
48 #include <svtools/style.hxx>
49 #include <svtools/smplhint.hxx>
50 #include <svx/eeitem.hxx>
51 #include <svx/xlnstit.hxx>
52 #include <svx/xlnstwit.hxx>
53 #include <svx/xlnedit.hxx>
54 #include <svx/xlnwtit.hxx>
55 #include <svx/xlnedwit.hxx>
56 #include <svx/xlnstcit.hxx>
57 #include <svx/xlnedcit.hxx>
58 #include <svx/outlobj.hxx>
59 #include <svx/outliner.hxx>
60 #include <svx/editobj.hxx>
61 #include <svx/svdfield.hxx>
62 #include <svx/flditem.hxx>
63 #include <svx/svdogrp.hxx>
64 #include <svx/svdopath.hxx>
65 #include <svx/svdpage.hxx>
66 #include <svtools/syslocale.hxx>
67 #include "svdoimp.hxx"
68 #include <svx/sdr/properties/measureproperties.hxx>
69 #include <svx/sdr/contact/viewcontactofsdrmeasureobj.hxx>
70 #include <basegfx/point/b2dpoint.hxx>
71 #include <basegfx/polygon/b2dpolygon.hxx>
72 #include <basegfx/polygon/b2dpolypolygon.hxx>
73 #include <basegfx/matrix/b2dhommatrix.hxx>
75 ////////////////////////////////////////////////////////////////////////////////////////////////////
77 SdrMeasureObjGeoData::SdrMeasureObjGeoData() {}
78 SdrMeasureObjGeoData::~SdrMeasureObjGeoData() {}
80 ////////////////////////////////////////////////////////////////////////////////////////////////////
82 SV_IMPL_PERSIST1(SdrMeasureField
,SvxFieldData
);
84 __EXPORT
SdrMeasureField::~SdrMeasureField()
88 SvxFieldData
* __EXPORT
SdrMeasureField::Clone() const
90 return new SdrMeasureField(*this);
93 int __EXPORT
SdrMeasureField::operator==(const SvxFieldData
& rSrc
) const
95 return eMeasureFieldKind
==((SdrMeasureField
&)rSrc
).GetMeasureFieldKind();
98 void __EXPORT
SdrMeasureField::Load(SvPersistStream
& rIn
)
102 eMeasureFieldKind
=(SdrMeasureFieldKind
)nFieldKind
;
105 void __EXPORT
SdrMeasureField::Save(SvPersistStream
& rOut
)
107 rOut
<<(UINT16
)eMeasureFieldKind
;
110 void SdrMeasureField::TakeRepresentation(const SdrMeasureObj
& rObj
, XubString
& rStr
) const
113 Fraction
aMeasureScale(1, 1);
114 BOOL
bTextRota90(FALSE
);
115 BOOL
bShowUnit(FALSE
);
116 FieldUnit
eMeasureUnit(FUNIT_NONE
);
117 FieldUnit
eModUIUnit(FUNIT_NONE
);
119 const SfxItemSet
& rSet
= rObj
.GetMergedItemSet();
120 bTextRota90
= ((SdrMeasureTextRota90Item
&)rSet
.Get(SDRATTR_MEASURETEXTROTA90
)).GetValue();
121 eMeasureUnit
= ((SdrMeasureUnitItem
&)rSet
.Get(SDRATTR_MEASUREUNIT
)).GetValue();
122 aMeasureScale
= ((SdrMeasureScaleItem
&)rSet
.Get(SDRATTR_MEASURESCALE
)).GetValue();
123 bShowUnit
= ((SdrMeasureShowUnitItem
&)rSet
.Get(SDRATTR_MEASURESHOWUNIT
)).GetValue();
124 sal_Int16 nNumDigits
= ((SdrMeasureDecimalPlacesItem
&)rSet
.Get(SDRATTR_MEASUREDECIMALPLACES
)).GetValue();
126 SdrModel
* pModel
= rObj
.pModel
;
128 switch(eMeasureFieldKind
)
130 case SDRMEASUREFIELD_VALUE
:
134 eModUIUnit
= pModel
->GetUIUnit();
136 if(eMeasureUnit
== FUNIT_NONE
)
137 eMeasureUnit
= eModUIUnit
;
139 INT32
nLen(GetLen(rObj
.aPt2
- rObj
.aPt1
));
142 if(eMeasureUnit
!= eModUIUnit
)
144 // Zur Umrechnung der Einheiten
145 aFact
*= GetMapFactor(eModUIUnit
, eMeasureUnit
).X();
148 if(aMeasureScale
.GetNumerator() != aMeasureScale
.GetDenominator())
150 aFact
*= aMeasureScale
;
153 if(aFact
.GetNumerator() != aFact
.GetDenominator())
155 // Scaling ueber BigInt, um Ueberlaeufe zu vermeiden
156 nLen
= BigMulDiv(nLen
, aFact
.GetNumerator(), aFact
.GetDenominator());
159 pModel
->TakeMetricStr(nLen
, rStr
, TRUE
, nNumDigits
);
164 rStr
+= sal_Unicode('?');
167 sal_Unicode
cDec(SvtSysLocale().GetLocaleData().getNumDecimalSep().GetChar(0));
169 if(rStr
.Search(cDec
) != STRING_NOTFOUND
)
171 xub_StrLen
nLen2(rStr
.Len() - 1);
173 while(rStr
.GetChar(nLen2
) == sal_Unicode('0'))
179 if(rStr
.GetChar(nLen2
) == cDec
)
186 rStr
+= sal_Unicode('0');
191 // falls kein Model da ... (z.B. Preview im Dialog)
193 rStr
.AppendAscii("4711");
198 case SDRMEASUREFIELD_UNIT
:
204 eModUIUnit
= pModel
->GetUIUnit();
206 if(eMeasureUnit
== FUNIT_NONE
)
207 eMeasureUnit
= eModUIUnit
;
210 pModel
->TakeUnitStr(eMeasureUnit
, rStr
);
216 case SDRMEASUREFIELD_ROTA90BLANCS
:
221 rStr
+= sal_Unicode(' ');
229 //////////////////////////////////////////////////////////////////////////////
230 // BaseProperties section
232 sdr::properties::BaseProperties
* SdrMeasureObj::CreateObjectSpecificProperties()
234 return new sdr::properties::MeasureProperties(*this);
237 //////////////////////////////////////////////////////////////////////////////
238 // DrawContact section
240 sdr::contact::ViewContact
* SdrMeasureObj::CreateObjectSpecificViewContact()
242 return new sdr::contact::ViewContactOfSdrMeasureObj(*this);
245 //////////////////////////////////////////////////////////////////////////////
247 TYPEINIT1(SdrMeasureObj
,SdrTextObj
);
249 SdrMeasureObj::SdrMeasureObj():
253 mbSupportTextIndentingOnLineWidthChange
= sal_False
;
256 SdrMeasureObj::SdrMeasureObj(const Point
& rPt1
, const Point
& rPt2
):
262 mbSupportTextIndentingOnLineWidthChange
= sal_False
;
265 SdrMeasureObj::~SdrMeasureObj()
269 void SdrMeasureObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
271 rInfo
.bSelectAllowed
=TRUE
;
272 rInfo
.bMoveAllowed
=TRUE
;
273 rInfo
.bResizeFreeAllowed
=TRUE
;
274 rInfo
.bResizePropAllowed
=TRUE
;
275 rInfo
.bRotateFreeAllowed
=TRUE
;
276 rInfo
.bRotate90Allowed
=TRUE
;
277 rInfo
.bMirrorFreeAllowed
=TRUE
;
278 rInfo
.bMirror45Allowed
=TRUE
;
279 rInfo
.bMirror90Allowed
=TRUE
;
280 rInfo
.bTransparenceAllowed
= FALSE
;
281 rInfo
.bGradientAllowed
= FALSE
;
282 rInfo
.bShearAllowed
=TRUE
;
283 rInfo
.bEdgeRadiusAllowed
=FALSE
;
284 rInfo
.bNoOrthoDesired
=TRUE
;
285 rInfo
.bNoContortion
=FALSE
;
286 rInfo
.bCanConvToPath
=FALSE
;
287 rInfo
.bCanConvToPoly
=TRUE
;
288 rInfo
.bCanConvToPathLineToArea
=FALSE
;
289 rInfo
.bCanConvToPolyLineToArea
=FALSE
;
290 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
293 UINT16
SdrMeasureObj::GetObjIdentifier() const
295 return (UINT16
)OBJ_MEASURE
;
298 struct ImpMeasureRec
: public SdrDragStatUserData
302 SdrMeasureKind eKind
;
303 SdrMeasureTextHPos eWantTextHPos
;
304 SdrMeasureTextVPos eWantTextVPos
;
306 long nHelplineOverhang
;
310 FASTBOOL bBelowRefEdge
;
311 FASTBOOL bTextRota90
;
312 FASTBOOL bTextUpsideDown
;
313 long nMeasureOverhang
;
314 FieldUnit eMeasureUnit
;
315 Fraction aMeasureScale
;
317 String aFormatString
;
318 FASTBOOL bTextAutoAngle
;
319 long nTextAutoAngleView
;
320 FASTBOOL bTextIsFixedAngle
;
321 long nTextFixedAngle
;
330 struct ImpMeasurePoly
332 ImpLineRec aMainline1
; // die mit dem 1. Pfeil
333 ImpLineRec aMainline2
; // die mit dem 2. Pfeil
334 ImpLineRec aMainline3
; // die dazwischen
335 ImpLineRec aHelpline1
;
336 ImpLineRec aHelpline2
;
348 SdrMeasureTextHPos eUsedTextHPos
;
349 SdrMeasureTextVPos eUsedTextVPos
;
350 long nLineWdt2
; // Halbe Strichstaerke
351 long nArrow1Len
; // Laenge des 1. Pfeils. Bei Center nur die Haelfte
352 long nArrow2Len
; // Laenge des 2. Pfeils. Bei Center nur die Haelfte
353 long nArrow1Wdt
; // Breite des 1. Pfeils
354 long nArrow2Wdt
; // Breite des 2. Pfeils
355 long nShortLineLen
; // Linienlaenge, wenn PfeileAussen
356 FASTBOOL bArrow1Center
; // Pfeil 1 zentriert?
357 FASTBOOL bArrow2Center
; // Pfeil 2 zentriert?
358 FASTBOOL bAutoUpsideDown
; // UpsideDown durch Automatik
359 FASTBOOL bPfeileAussen
;
360 FASTBOOL bBreakedLine
;
363 void SdrMeasureObj::ImpTakeAttr(ImpMeasureRec
& rRec
) const
368 const SfxItemSet
& rSet
= GetObjectItemSet();
369 rRec
.eKind
=((SdrMeasureKindItem
& )rSet
.Get(SDRATTR_MEASUREKIND
)).GetValue();
370 rRec
.eWantTextHPos
=((SdrMeasureTextHPosItem
& )rSet
.Get(SDRATTR_MEASURETEXTHPOS
)).GetValue();
371 rRec
.eWantTextVPos
=((SdrMeasureTextVPosItem
& )rSet
.Get(SDRATTR_MEASURETEXTVPOS
)).GetValue();
372 rRec
.nLineDist
=((SdrMeasureLineDistItem
& )rSet
.Get(SDRATTR_MEASURELINEDIST
)).GetValue();
373 rRec
.nHelplineOverhang
=((SdrMeasureHelplineOverhangItem
&)rSet
.Get(SDRATTR_MEASUREHELPLINEOVERHANG
)).GetValue();
374 rRec
.nHelplineDist
=((SdrMeasureHelplineDistItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINEDIST
)).GetValue();
375 rRec
.nHelpline1Len
=((SdrMeasureHelpline1LenItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINE1LEN
)).GetValue();
376 rRec
.nHelpline2Len
=((SdrMeasureHelpline2LenItem
& )rSet
.Get(SDRATTR_MEASUREHELPLINE2LEN
)).GetValue();
377 rRec
.bBelowRefEdge
=((SdrMeasureBelowRefEdgeItem
& )rSet
.Get(SDRATTR_MEASUREBELOWREFEDGE
)).GetValue();
378 rRec
.bTextRota90
=((SdrMeasureTextRota90Item
& )rSet
.Get(SDRATTR_MEASURETEXTROTA90
)).GetValue();
379 rRec
.bTextUpsideDown
=((SdrMeasureTextUpsideDownItem
& )rSet
.Get(SDRATTR_MEASURETEXTUPSIDEDOWN
)).GetValue();
380 rRec
.nMeasureOverhang
=((SdrMeasureOverhangItem
& )rSet
.Get(SDRATTR_MEASUREOVERHANG
)).GetValue();
381 rRec
.eMeasureUnit
=((SdrMeasureUnitItem
& )rSet
.Get(SDRATTR_MEASUREUNIT
)).GetValue();
382 rRec
.aMeasureScale
=((SdrMeasureScaleItem
& )rSet
.Get(SDRATTR_MEASURESCALE
)).GetValue();
383 rRec
.bShowUnit
=((SdrMeasureShowUnitItem
& )rSet
.Get(SDRATTR_MEASURESHOWUNIT
)).GetValue();
384 rRec
.aFormatString
=((SdrMeasureFormatStringItem
& )rSet
.Get(SDRATTR_MEASUREFORMATSTRING
)).GetValue();
385 rRec
.bTextAutoAngle
=((SdrMeasureTextAutoAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTAUTOANGLE
)).GetValue();
386 rRec
.nTextAutoAngleView
=((SdrMeasureTextAutoAngleViewItem
&)rSet
.Get(SDRATTR_MEASURETEXTAUTOANGLEVIEW
)).GetValue();
387 rRec
.bTextIsFixedAngle
=((SdrMeasureTextIsFixedAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTISFIXEDANGLE
)).GetValue();
388 rRec
.nTextFixedAngle
=((SdrMeasureTextFixedAngleItem
& )rSet
.Get(SDRATTR_MEASURETEXTFIXEDANGLE
)).GetValue();
391 long impGetLineStartEndDistance(const basegfx::B2DPolyPolygon
& rPolyPolygon
, long nNewWidth
, bool bCenter
)
393 const basegfx::B2DRange
aPolygonRange(rPolyPolygon
.getB2DRange());
394 const double fOldWidth(aPolygonRange
.getWidth() > 1.0 ? aPolygonRange
.getWidth() : 1.0);
395 const double fScale((double)nNewWidth
/ fOldWidth
);
396 long nHeight(basegfx::fround(aPolygonRange
.getHeight() * fScale
));
406 void SdrMeasureObj::ImpCalcGeometrics(const ImpMeasureRec
& rRec
, ImpMeasurePoly
& rPol
) const
408 Point
aP1(rRec
.aPt1
);
409 Point
aP2(rRec
.aPt2
);
410 Point
aDelt(aP2
); aDelt
-=aP1
;
412 rPol
.aTextSize
=GetTextSize();
413 rPol
.nLineLen
=GetLen(aDelt
);
416 long nArrow1Len
=0; bool bArrow1Center
=false;
417 long nArrow2Len
=0; bool bArrow2Center
=false;
424 FASTBOOL bPfeileAussen
=FALSE
;
426 const SfxItemSet
& rSet
= GetObjectItemSet();
427 sal_Int32 nLineWdt
= ((XLineWidthItem
&)(rSet
.Get(XATTR_LINEWIDTH
))).GetValue(); // Strichstaerke
428 rPol
.nLineWdt2
= (nLineWdt
+ 1) / 2;
430 nArrow1Wdt
= ((const XLineStartWidthItem
&)(rSet
.Get(XATTR_LINESTARTWIDTH
))).GetValue();
432 nArrow1Wdt
= -nLineWdt
* nArrow1Wdt
/ 100; // <0 = relativ
434 nArrow2Wdt
= ((const XLineEndWidthItem
&)(rSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
436 nArrow2Wdt
= -nLineWdt
* nArrow2Wdt
/ 100; // <0 = relativ
438 basegfx::B2DPolyPolygon
aPol1(((const XLineStartItem
&)(rSet
.Get(XATTR_LINESTART
))).GetLineStartValue());
439 basegfx::B2DPolyPolygon
aPol2(((const XLineEndItem
&)(rSet
.Get(XATTR_LINEEND
))).GetLineEndValue());
440 bArrow1Center
= ((const XLineStartCenterItem
&)(rSet
.Get(XATTR_LINESTARTCENTER
))).GetValue();
441 bArrow2Center
= ((const XLineEndCenterItem
&)(rSet
.Get(XATTR_LINEENDCENTER
))).GetValue();
442 nArrow1Len
= impGetLineStartEndDistance(aPol1
, nArrow1Wdt
, bArrow1Center
) - 1;
443 nArrow2Len
= impGetLineStartEndDistance(aPol2
, nArrow2Wdt
, bArrow2Center
) - 1;
445 // nArrowLen ist bei bCenter bereits halbiert
446 // Bei 2 Pfeilen a 4mm ist unter 10mm Schluss.
447 nArrowNeed
=nArrow1Len
+nArrow2Len
+(nArrow1Wdt
+nArrow2Wdt
)/2;
448 if (rPol
.nLineLen
<nArrowNeed
) bPfeileAussen
=TRUE
;
449 nShortLen
=(nArrow1Len
+nArrow1Wdt
+ nArrow2Len
+nArrow2Wdt
) /2;
451 rPol
.eUsedTextHPos
=rRec
.eWantTextHPos
;
452 rPol
.eUsedTextVPos
=rRec
.eWantTextVPos
;
453 if (rPol
.eUsedTextVPos
==SDRMEASURE_TEXTVAUTO
) rPol
.eUsedTextVPos
=SDRMEASURE_ABOVE
;
454 FASTBOOL bBrkLine
=rPol
.eUsedTextVPos
==SDRMEASURETEXT_BREAKEDLINE
;
455 if (rPol
.eUsedTextVPos
==SDRMEASURETEXT_VERTICALCENTERED
)
457 OutlinerParaObject
* pOutlinerParaObject
= SdrTextObj::GetOutlinerParaObject();
458 if (pOutlinerParaObject
!=NULL
&& pOutlinerParaObject
->GetTextObject().GetParagraphCount()==1)
460 bBrkLine
=TRUE
; // Unterbrochene Linie, wenn nur 1 Absatz.
463 rPol
.bBreakedLine
=bBrkLine
;
464 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTHAUTO
) { // bei zu breitem Text diesen eventuell nach aussen schieben
465 FASTBOOL bOutside
=FALSE
;
466 long nNeedSiz
=!rRec
.bTextRota90
? rPol
.aTextSize
.Width() : rPol
.aTextSize
.Height();
467 if (nNeedSiz
>rPol
.nLineLen
) bOutside
=TRUE
; // Text passt nicht in die Mitte
469 if (nNeedSiz
+nArrowNeed
>rPol
.nLineLen
) bPfeileAussen
=TRUE
; // Text passt in die Mitte, wenn die Pfeile nach aussen kommen
471 long nSmallNeed
=nArrow1Len
+nArrow2Len
+(nArrow1Wdt
+nArrow2Wdt
)/2/4;
472 if (nNeedSiz
+nSmallNeed
>rPol
.nLineLen
) bPfeileAussen
=TRUE
; // Text passt in die Mitte, wenn die Pfeile nach aussen kommen
474 rPol
.eUsedTextHPos
=bOutside
? SDRMEASURE_TEXTLEFTOUTSIDE
: SDRMEASURE_TEXTINSIDE
;
476 if (rPol
.eUsedTextHPos
!=SDRMEASURE_TEXTINSIDE
) bPfeileAussen
=TRUE
;
477 rPol
.nArrow1Wdt
=nArrow1Wdt
;
478 rPol
.nArrow2Wdt
=nArrow2Wdt
;
479 rPol
.nShortLineLen
=nShortLen
;
480 rPol
.bPfeileAussen
=bPfeileAussen
;
481 rPol
.nArrow1Len
=nArrow1Len
;
482 rPol
.bArrow1Center
=bArrow1Center
;
483 rPol
.nArrow2Len
=nArrow2Len
;
484 rPol
.bArrow2Center
=bArrow2Center
;
486 rPol
.nLineWink
=GetAngle(aDelt
);
487 double a
=rPol
.nLineWink
*nPi180
;
488 double nLineSin
=sin(a
);
489 double nLineCos
=cos(a
);
490 rPol
.nLineSin
=nLineSin
;
491 rPol
.nLineCos
=nLineCos
;
493 rPol
.nTextWink
=rPol
.nLineWink
;
494 if (rRec
.bTextRota90
) rPol
.nTextWink
+=9000;
496 rPol
.bAutoUpsideDown
=FALSE
;
497 if (rRec
.bTextAutoAngle
) {
498 long nTmpWink
=NormAngle360(rPol
.nTextWink
-rRec
.nTextAutoAngleView
);
499 if (nTmpWink
>=18000) {
500 rPol
.nTextWink
+=18000;
501 rPol
.bAutoUpsideDown
=TRUE
;
505 if (rRec
.bTextUpsideDown
) rPol
.nTextWink
+=18000;
506 rPol
.nTextWink
=NormAngle360(rPol
.nTextWink
);
507 rPol
.nHlpWink
=rPol
.nLineWink
+9000;
508 if (rRec
.bBelowRefEdge
) rPol
.nHlpWink
+=18000;
509 rPol
.nHlpWink
=NormAngle360(rPol
.nHlpWink
);
510 double nHlpSin
=nLineCos
;
511 double nHlpCos
=-nLineSin
;
512 if (rRec
.bBelowRefEdge
) {
516 rPol
.nHlpSin
=nHlpSin
;
517 rPol
.nHlpCos
=nHlpCos
;
519 long nLineDist
=rRec
.nLineDist
;
520 long nOverhang
=rRec
.nHelplineOverhang
;
521 long nHelplineDist
=rRec
.nHelplineDist
;
523 long dx
= Round(nLineDist
*nHlpCos
);
524 long dy
=-Round(nLineDist
*nHlpSin
);
525 long dxh1a
= Round((nHelplineDist
-rRec
.nHelpline1Len
)*nHlpCos
);
526 long dyh1a
=-Round((nHelplineDist
-rRec
.nHelpline1Len
)*nHlpSin
);
527 long dxh1b
= Round((nHelplineDist
-rRec
.nHelpline2Len
)*nHlpCos
);
528 long dyh1b
=-Round((nHelplineDist
-rRec
.nHelpline2Len
)*nHlpSin
);
529 long dxh2
= Round((nLineDist
+nOverhang
)*nHlpCos
);
530 long dyh2
=-Round((nLineDist
+nOverhang
)*nHlpSin
);
533 rPol
.aHelpline1
.aP1
=Point(aP1
.X()+dxh1a
,aP1
.Y()+dyh1a
);
534 rPol
.aHelpline1
.aP2
=Point(aP1
.X()+dxh2
,aP1
.Y()+dyh2
);
537 rPol
.aHelpline2
.aP1
=Point(aP2
.X()+dxh1b
,aP2
.Y()+dyh1b
);
538 rPol
.aHelpline2
.aP2
=Point(aP2
.X()+dxh2
,aP2
.Y()+dyh2
);
541 Point
aMainlinePt1(aP1
.X()+dx
,aP1
.Y()+dy
);
542 Point
aMainlinePt2(aP2
.X()+dx
,aP2
.Y()+dy
);
543 if (!bPfeileAussen
) {
544 rPol
.aMainline1
.aP1
=aMainlinePt1
;
545 rPol
.aMainline1
.aP2
=aMainlinePt2
;
546 rPol
.aMainline2
=rPol
.aMainline1
;
547 rPol
.aMainline3
=rPol
.aMainline1
;
550 long nNeedSiz
=!rRec
.bTextRota90
? rPol
.aTextSize
.Width() : rPol
.aTextSize
.Height();
551 long nHalfLen
=(rPol
.nLineLen
-nNeedSiz
-nArrow1Wdt
/4-nArrow2Wdt
/4) /2;
553 rPol
.aMainline1
.aP2
=aMainlinePt1
;
554 rPol
.aMainline1
.aP2
.X()+=nHalfLen
;
555 RotatePoint(rPol
.aMainline1
.aP2
,rPol
.aMainline1
.aP1
,nLineSin
,nLineCos
);
556 rPol
.aMainline2
.aP1
=aMainlinePt2
;
557 rPol
.aMainline2
.aP1
.X()-=nHalfLen
;
558 RotatePoint(rPol
.aMainline2
.aP1
,rPol
.aMainline2
.aP2
,nLineSin
,nLineCos
);
561 long nLen1
=nShortLen
; // Pfeilbreite als Linienlaenge ausserhalb des Pfeils
562 long nLen2
=nShortLen
;
563 long nTextWdt
=rRec
.bTextRota90
? rPol
.aTextSize
.Height() : rPol
.aTextSize
.Width();
565 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTLEFTOUTSIDE
) nLen1
=nArrow1Len
+nTextWdt
;
566 if (rPol
.eUsedTextHPos
==SDRMEASURE_TEXTRIGHTOUTSIDE
) nLen2
=nArrow2Len
+nTextWdt
;
568 rPol
.aMainline1
.aP1
=aMainlinePt1
;
569 rPol
.aMainline1
.aP2
=aMainlinePt1
; rPol
.aMainline1
.aP2
.X()-=nLen1
; RotatePoint(rPol
.aMainline1
.aP2
,aMainlinePt1
,nLineSin
,nLineCos
);
570 rPol
.aMainline2
.aP1
=aMainlinePt2
; rPol
.aMainline2
.aP1
.X()+=nLen2
; RotatePoint(rPol
.aMainline2
.aP1
,aMainlinePt2
,nLineSin
,nLineCos
);
571 rPol
.aMainline2
.aP2
=aMainlinePt2
;
572 rPol
.aMainline3
.aP1
=aMainlinePt1
;
573 rPol
.aMainline3
.aP2
=aMainlinePt2
;
575 if (bBrkLine
&& rPol
.eUsedTextHPos
==SDRMEASURE_TEXTINSIDE
) rPol
.nMainlineAnz
=2;
579 basegfx::B2DPolyPolygon
SdrMeasureObj::ImpCalcXPoly(const ImpMeasurePoly
& rPol
) const
581 basegfx::B2DPolyPolygon aRetval
;
582 basegfx::B2DPolygon aPartPolyA
;
583 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline1
.aP1
.X(), rPol
.aMainline1
.aP1
.Y()));
584 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline1
.aP2
.X(), rPol
.aMainline1
.aP2
.Y()));
585 aRetval
.append(aPartPolyA
);
587 if(rPol
.nMainlineAnz
> 1)
590 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline2
.aP1
.X(), rPol
.aMainline2
.aP1
.Y()));
591 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline2
.aP2
.X(), rPol
.aMainline2
.aP2
.Y()));
592 aRetval
.append(aPartPolyA
);
595 if(rPol
.nMainlineAnz
> 2)
598 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline3
.aP1
.X(), rPol
.aMainline3
.aP1
.Y()));
599 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aMainline3
.aP2
.X(), rPol
.aMainline3
.aP2
.Y()));
600 aRetval
.append(aPartPolyA
);
604 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline1
.aP1
.X(), rPol
.aHelpline1
.aP1
.Y()));
605 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline1
.aP2
.X(), rPol
.aHelpline1
.aP2
.Y()));
606 aRetval
.append(aPartPolyA
);
609 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline2
.aP1
.X(), rPol
.aHelpline2
.aP1
.Y()));
610 aPartPolyA
.append(basegfx::B2DPoint(rPol
.aHelpline2
.aP2
.X(), rPol
.aHelpline2
.aP2
.Y()));
611 aRetval
.append(aPartPolyA
);
616 FASTBOOL
SdrMeasureObj::CalcFieldValue(const SvxFieldItem
& rField
, USHORT nPara
, USHORT nPos
,
618 Color
*& rpTxtColor
, Color
*& rpFldColor
, XubString
& rRet
) const
620 const SvxFieldData
* pField
=rField
.GetField();
621 SdrMeasureField
* pMeasureField
=PTR_CAST(SdrMeasureField
,pField
);
622 if (pMeasureField
!=NULL
) {
623 pMeasureField
->TakeRepresentation(*this,rRet
);
624 if (rpFldColor
!=NULL
) {
633 return SdrTextObj::CalcFieldValue(rField
,nPara
,nPos
,bEdit
,rpTxtColor
,rpFldColor
,rRet
);
637 void SdrMeasureObj::UndirtyText() const
641 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
642 OutlinerParaObject
* pOutlinerParaObject
= SdrTextObj::GetOutlinerParaObject();
643 if(pOutlinerParaObject
==NULL
)
645 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS
), EE_FEATURE_FIELD
), ESelection(0,0));
646 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_VALUE
), EE_FEATURE_FIELD
),ESelection(0,1));
647 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_UNIT
), EE_FEATURE_FIELD
),ESelection(0,2));
648 rOutliner
.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS
), EE_FEATURE_FIELD
),ESelection(0,3));
651 rOutliner
.SetStyleSheet(0, GetStyleSheet());
653 rOutliner
.SetParaAttribs(0, GetObjectItemSet());
655 // casting auf nonconst
656 const_cast<SdrMeasureObj
*>(this)->NbcSetOutlinerParaObject( rOutliner
.CreateParaObject() );
660 rOutliner
.SetText(*pOutlinerParaObject
);
663 rOutliner
.SetUpdateMode(TRUE
);
664 rOutliner
.UpdateFields();
665 Size
aSiz(rOutliner
.CalcTextSize());
667 // 3x casting auf nonconst
668 ((SdrMeasureObj
*)this)->aTextSize
=aSiz
;
669 ((SdrMeasureObj
*)this)->bTextSizeDirty
=FALSE
;
670 ((SdrMeasureObj
*)this)->bTextDirty
=FALSE
;
674 void SdrMeasureObj::TakeUnrotatedSnapRect(Rectangle
& rRect
) const
676 if (bTextDirty
) UndirtyText();
678 ImpMeasurePoly aMPol
;
680 ImpCalcGeometrics(aRec
,aMPol
);
682 // TextSize ermitteln inkl. Textrahmenabstaende
683 Size
aTextSize2(aMPol
.aTextSize
);
684 if (aTextSize2
.Width()<1) aTextSize2
.Width()=1;
685 if (aTextSize2
.Height()<1) aTextSize2
.Height()=1;
686 aTextSize2
.Width()+=GetTextLeftDistance()+GetTextRightDistance();
687 aTextSize2
.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
689 Point
aPt1b(aMPol
.aMainline1
.aP1
);
690 long nLen
=aMPol
.nLineLen
;
691 long nLWdt
=aMPol
.nLineWdt2
;
692 long nArr1Len
=aMPol
.nArrow1Len
;
693 long nArr2Len
=aMPol
.nArrow2Len
;
694 if (aMPol
.bBreakedLine
) {
695 // Bei Unterbrochener Linie und Outside muss der Text nicht neben den
696 // Pfeil sondern neben die Linie an dem Pfeil plaziert werden
697 nArr1Len
=aMPol
.nShortLineLen
+aMPol
.nArrow1Wdt
/4;
698 nArr2Len
=aMPol
.nShortLineLen
+aMPol
.nArrow2Wdt
/4;
702 FASTBOOL bRota90
=aRec
.bTextRota90
;
703 FASTBOOL bUpsideDown
=aRec
.bTextUpsideDown
!=aMPol
.bAutoUpsideDown
;
704 FASTBOOL bBelowRefEdge
=aRec
.bBelowRefEdge
;
705 SdrMeasureTextHPos eMH
=aMPol
.eUsedTextHPos
;
706 SdrMeasureTextVPos eMV
=aMPol
.eUsedTextVPos
;
709 case SDRMEASURE_TEXTLEFTOUTSIDE
: aTextPos
.X()=aPt1b
.X()-aTextSize2
.Width()-nArr1Len
-nLWdt
; break;
710 case SDRMEASURE_TEXTRIGHTOUTSIDE
: aTextPos
.X()=aPt1b
.X()+nLen
+nArr2Len
+nLWdt
; break;
711 default: aTextPos
.X()=aPt1b
.X(); aTextSize2
.Width()=nLen
;
714 case SDRMEASURETEXT_VERTICALCENTERED
:
715 case SDRMEASURETEXT_BREAKEDLINE
: aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()/2; break;
716 case SDRMEASURE_BELOW
: {
717 if (!bUpsideDown
) aTextPos
.Y()=aPt1b
.Y()+nLWdt
;
718 else aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()-nLWdt
;
721 if (!bUpsideDown
) aTextPos
.Y()=aPt1b
.Y()-aTextSize2
.Height()-nLWdt
;
722 else aTextPos
.Y()=aPt1b
.Y()+nLWdt
;
726 aTextPos
.X()+=aTextSize2
.Width();
727 aTextPos
.Y()+=aTextSize2
.Height();
729 } else { // also wenn bTextRota90==TRUE
731 case SDRMEASURE_TEXTLEFTOUTSIDE
: aTextPos
.X()=aPt1b
.X()-aTextSize2
.Height()-nArr1Len
; break;
732 case SDRMEASURE_TEXTRIGHTOUTSIDE
: aTextPos
.X()=aPt1b
.X()+nLen
+nArr2Len
; break;
733 default: aTextPos
.X()=aPt1b
.X(); aTextSize2
.Height()=nLen
;
736 case SDRMEASURETEXT_VERTICALCENTERED
:
737 case SDRMEASURETEXT_BREAKEDLINE
: aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()/2; break;
738 case SDRMEASURE_BELOW
: {
739 if (!bBelowRefEdge
) aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()+nLWdt
;
740 else aTextPos
.Y()=aPt1b
.Y()-nLWdt
;
743 if (!bBelowRefEdge
) aTextPos
.Y()=aPt1b
.Y()-nLWdt
;
744 else aTextPos
.Y()=aPt1b
.Y()+aTextSize2
.Width()+nLWdt
;
748 aTextPos
.X()+=aTextSize2
.Height();
749 aTextPos
.Y()-=aTextSize2
.Width();
752 if (aMPol
.nTextWink
!=aGeo
.nDrehWink
) {
753 ((SdrMeasureObj
*)this)->aGeo
.nDrehWink
=aMPol
.nTextWink
;
754 ((SdrMeasureObj
*)this)->aGeo
.RecalcSinCos();
756 RotatePoint(aTextPos
,aPt1b
,aMPol
.nLineSin
,aMPol
.nLineCos
);
757 aTextSize2
.Width()++; aTextSize2
.Height()++; // wg. des komischen Verhaltens beim Rect-Ctor
758 rRect
=Rectangle(aTextPos
,aTextSize2
);
760 ((SdrMeasureObj
*)this)->aRect
=rRect
;
762 if (aMPol
.nTextWink
!=aGeo
.nDrehWink
) {
763 ((SdrMeasureObj
*)this)->aGeo
.nDrehWink
=aMPol
.nTextWink
;
764 ((SdrMeasureObj
*)this)->aGeo
.RecalcSinCos();
768 void SdrMeasureObj::operator=(const SdrObject
& rObj
)
770 SdrTextObj::operator=(rObj
);
771 aPt1
=((SdrMeasureObj
&)rObj
).aPt1
;
772 aPt2
=((SdrMeasureObj
&)rObj
).aPt2
;
773 bTextDirty
=((SdrMeasureObj
&)rObj
).bTextDirty
;
776 void SdrMeasureObj::TakeObjNameSingul(XubString
& rName
) const
778 rName
=ImpGetResStr(STR_ObjNameSingulMEASURE
);
780 String
aName( GetName() );
783 rName
+= sal_Unicode(' ');
784 rName
+= sal_Unicode('\'');
786 rName
+= sal_Unicode('\'');
790 void SdrMeasureObj::TakeObjNamePlural(XubString
& rName
) const
792 rName
=ImpGetResStr(STR_ObjNamePluralMEASURE
);
795 basegfx::B2DPolyPolygon
SdrMeasureObj::TakeXorPoly() const
798 ImpMeasurePoly aMPol
;
800 ImpCalcGeometrics(aRec
,aMPol
);
801 return ImpCalcXPoly(aMPol
);
804 sal_uInt32
SdrMeasureObj::GetHdlCount() const
809 SdrHdl
* SdrMeasureObj::GetHdl(sal_uInt32 nHdlNum
) const
812 ImpMeasurePoly aMPol
;
814 aRec
.nHelplineDist
=0;
815 ImpCalcGeometrics(aRec
,aMPol
);
817 //SdrHdlKind eHdl=HDL_POLY;
819 case 0: aPt
=aMPol
.aHelpline1
.aP1
; break;
820 case 1: aPt
=aMPol
.aHelpline2
.aP1
; break;
821 case 2: aPt
=aPt1
; break;
822 case 3: aPt
=aPt2
; break;
823 case 4: aPt
=aMPol
.aHelpline1
.aP2
; break;
824 case 5: aPt
=aMPol
.aHelpline2
.aP2
; break;
826 SdrHdl
* pHdl
=new ImpMeasureHdl(aPt
,HDL_USER
);
827 pHdl
->SetObjHdlNum(nHdlNum
);
828 pHdl
->SetDrehWink(aMPol
.nLineWink
);
832 ////////////////////////////////////////////////////////////////////////////////////////////////////
834 bool SdrMeasureObj::hasSpecialDrag() const
839 bool SdrMeasureObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
841 const SdrHdl
* pHdl
= rDrag
.GetHdl();
845 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
847 if(nHdlNum
!= 2 && nHdlNum
!= 3)
849 rDrag
.SetEndDragChangesAttributes(true);
858 bool SdrMeasureObj::applySpecialDrag(SdrDragStat
& rDrag
)
860 ImpMeasureRec aMeasureRec
;
861 const SdrHdl
* pHdl
= rDrag
.GetHdl();
862 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
864 ImpTakeAttr(aMeasureRec
);
865 ImpEvalDrag(aMeasureRec
, rDrag
);
871 aPt1
= aMeasureRec
.aPt1
;
877 aPt2
= aMeasureRec
.aPt2
;
888 ImpMeasureRec aOrigMeasureRec
;
889 ImpTakeAttr(aOrigMeasureRec
);
891 if(aMeasureRec
.nHelpline1Len
!= aOrigMeasureRec
.nHelpline1Len
)
893 SetObjectItem(SdrMeasureHelpline1LenItem(aMeasureRec
.nHelpline1Len
));
896 if(aMeasureRec
.nHelpline2Len
!= aOrigMeasureRec
.nHelpline2Len
)
898 SetObjectItem(SdrMeasureHelpline2LenItem(aMeasureRec
.nHelpline2Len
));
907 ImpMeasureRec aOrigMeasureRec
;
908 ImpTakeAttr(aOrigMeasureRec
);
910 if(aMeasureRec
.nLineDist
!= aOrigMeasureRec
.nLineDist
)
912 SetObjectItem(SdrMeasureLineDistItem(aMeasureRec
.nLineDist
));
915 if(aMeasureRec
.bBelowRefEdge
!= aOrigMeasureRec
.bBelowRefEdge
)
917 SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec
.bBelowRefEdge
));
930 String
SdrMeasureObj::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
936 void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec
& rRec
, const SdrDragStat
& rDrag
) const
938 long nLineWink
=GetAngle(rRec
.aPt2
-rRec
.aPt1
);
939 double a
=nLineWink
*nPi180
;
943 const SdrHdl
* pHdl
=rDrag
.GetHdl();
944 sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
945 FASTBOOL bOrtho
=rDrag
.GetView()!=NULL
&& rDrag
.GetView()->IsOrtho();
946 FASTBOOL bBigOrtho
=bOrtho
&& rDrag
.GetView()->IsBigOrtho();
947 FASTBOOL bBelow
=rRec
.bBelowRefEdge
;
948 Point
aPt(rDrag
.GetNow());
952 RotatePoint(aPt
,aPt1
,nSin
,-nCos
);
953 rRec
.nHelpline1Len
=aPt1
.Y()-aPt
.Y();
954 if (bBelow
) rRec
.nHelpline1Len
=-rRec
.nHelpline1Len
;
955 if (bOrtho
) rRec
.nHelpline2Len
=rRec
.nHelpline1Len
;
958 RotatePoint(aPt
,aPt2
,nSin
,-nCos
);
959 rRec
.nHelpline2Len
=aPt2
.Y()-aPt
.Y();
960 if (bBelow
) rRec
.nHelpline2Len
=-rRec
.nHelpline2Len
;
961 if (bOrtho
) rRec
.nHelpline1Len
=rRec
.nHelpline2Len
;
964 FASTBOOL bAnf
=nHdlNum
==2;
965 Point
& rMov
=bAnf
? rRec
.aPt1
: rRec
.aPt2
;
967 Point
aFix(bAnf
? rRec
.aPt2
: rRec
.aPt1
);
969 long ndx0
=aMov
.X()-aFix
.X();
970 long ndy0
=aMov
.Y()-aFix
.Y();
971 FASTBOOL bHLin
=ndy0
==0;
972 FASTBOOL bVLin
=ndx0
==0;
973 if (!bHLin
|| !bVLin
) { // sonst ist aPt1==aPt2
974 long ndx
=aPt
.X()-aFix
.X();
975 long ndy
=aPt
.Y()-aFix
.Y();
976 double nXFact
=0; if (!bVLin
) nXFact
=(double)ndx
/(double)ndx0
;
977 double nYFact
=0; if (!bHLin
) nYFact
=(double)ndy
/(double)ndy0
;
978 FASTBOOL bHor
=bHLin
|| (!bVLin
&& (nXFact
>nYFact
) ==bBigOrtho
);
979 FASTBOOL bVer
=bVLin
|| (!bHLin
&& (nXFact
<=nYFact
)==bBigOrtho
);
980 if (bHor
) ndy
=long(ndy0
*nXFact
);
981 if (bVer
) ndx
=long(ndx0
*nYFact
);
990 long nVal0
=rRec
.nLineDist
;
991 RotatePoint(aPt
,(nHdlNum
==4 ? aPt1
: aPt2
),nSin
,-nCos
);
992 rRec
.nLineDist
=aPt
.Y()- (nHdlNum
==4 ? aPt1
.Y() : aPt2
.Y());
993 if (bBelow
) rRec
.nLineDist
=-rRec
.nLineDist
;
994 if (rRec
.nLineDist
<0) {
995 rRec
.nLineDist
=-rRec
.nLineDist
;
996 rRec
.bBelowRefEdge
=!bBelow
;
998 rRec
.nLineDist
-=rRec
.nHelplineOverhang
;
999 if (bOrtho
) rRec
.nLineDist
=nVal0
;
1004 ////////////////////////////////////////////////////////////////////////////////////////////////////
1006 FASTBOOL
SdrMeasureObj::BegCreate(SdrDragStat
& rStat
)
1008 rStat
.SetOrtho8Possible();
1009 aPt1
=rStat
.GetStart();
1010 aPt2
=rStat
.GetNow();
1015 FASTBOOL
SdrMeasureObj::MovCreate(SdrDragStat
& rStat
)
1017 SdrView
* pView
=rStat
.GetView();
1018 aPt1
=rStat
.GetStart();
1019 aPt2
=rStat
.GetNow();
1020 if (pView
!=NULL
&& pView
->IsCreate1stPointAsCenter()) {
1025 SetBoundRectDirty();
1026 bSnapRectDirty
=TRUE
;
1030 FASTBOOL
SdrMeasureObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
1034 return (eCmd
==SDRCREATE_FORCEEND
|| rStat
.GetPointAnz()>=2);
1037 FASTBOOL
SdrMeasureObj::BckCreate(SdrDragStat
& /*rStat*/)
1042 void SdrMeasureObj::BrkCreate(SdrDragStat
& /*rStat*/)
1046 basegfx::B2DPolyPolygon
SdrMeasureObj::TakeCreatePoly(const SdrDragStat
& /*rDrag*/) const
1049 ImpMeasurePoly aMPol
;
1052 ImpCalcGeometrics(aRec
, aMPol
);
1054 return ImpCalcXPoly(aMPol
);
1057 Pointer
SdrMeasureObj::GetCreatePointer() const
1059 return Pointer(POINTER_CROSS
);
1062 void SdrMeasureObj::NbcMove(const Size
& rSiz
)
1064 SdrTextObj::NbcMove(rSiz
);
1065 MovePoint(aPt1
,rSiz
);
1066 MovePoint(aPt2
,rSiz
);
1069 void SdrMeasureObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
1071 SdrTextObj::NbcResize(rRef
,xFact
,yFact
);
1072 ResizePoint(aPt1
,rRef
,xFact
,yFact
);
1073 ResizePoint(aPt2
,rRef
,xFact
,yFact
);
1077 void SdrMeasureObj::NbcRotate(const Point
& rRef
, long nWink
, double sn
, double cs
)
1079 SdrTextObj::NbcRotate(rRef
,nWink
,sn
,cs
);
1080 long nLen0
=GetLen(aPt2
-aPt1
);
1081 RotatePoint(aPt1
,rRef
,sn
,cs
);
1082 RotatePoint(aPt2
,rRef
,sn
,cs
);
1083 long nLen1
=GetLen(aPt2
-aPt1
);
1084 if (nLen1
!=nLen0
) { // Aha, Rundungsfehler
1085 long dx
=aPt2
.X()-aPt1
.X();
1086 long dy
=aPt2
.Y()-aPt1
.Y();
1087 dx
=BigMulDiv(dx
,nLen0
,nLen1
);
1088 dy
=BigMulDiv(dy
,nLen0
,nLen1
);
1090 aPt1
.X()=aPt2
.X()-dx
;
1091 aPt1
.Y()=aPt2
.Y()-dy
;
1093 aPt2
.X()=aPt1
.X()+dx
;
1094 aPt2
.Y()=aPt1
.Y()+dy
;
1100 void SdrMeasureObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
1102 SdrTextObj::NbcMirror(rRef1
,rRef2
);
1103 MirrorPoint(aPt1
,rRef1
,rRef2
);
1104 MirrorPoint(aPt2
,rRef1
,rRef2
);
1108 void SdrMeasureObj::NbcShear(const Point
& rRef
, long nWink
, double tn
, FASTBOOL bVShear
)
1110 SdrTextObj::NbcShear(rRef
,nWink
,tn
,bVShear
);
1111 ShearPoint(aPt1
,rRef
,tn
,bVShear
);
1112 ShearPoint(aPt2
,rRef
,tn
,bVShear
);
1117 long SdrMeasureObj::GetRotateAngle() const
1119 return GetAngle(aPt2
-aPt1
);
1122 void SdrMeasureObj::RecalcSnapRect()
1124 // #94520# Added correct implementation here.
1126 ImpMeasurePoly aMPol
;
1130 ImpCalcGeometrics(aRec
, aMPol
);
1131 aXPP
= XPolyPolygon(ImpCalcXPoly(aMPol
));
1132 maSnapRect
= aXPP
.GetBoundRect();
1135 sal_uInt32
SdrMeasureObj::GetSnapPointCount() const
1140 Point
SdrMeasureObj::GetSnapPoint(sal_uInt32 i
) const
1142 if (i
==0) return aPt1
;
1146 sal_Bool
SdrMeasureObj::IsPolyObj() const
1151 sal_uInt32
SdrMeasureObj::GetPointCount() const
1156 Point
SdrMeasureObj::GetPoint(sal_uInt32 i
) const
1158 return (0L == i
) ? aPt1
: aPt2
;
1161 void SdrMeasureObj::NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
)
1171 SdrObjGeoData
* SdrMeasureObj::NewGeoData() const
1173 return new SdrMeasureObjGeoData
;
1176 void SdrMeasureObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
1178 SdrTextObj::SaveGeoData(rGeo
);
1179 SdrMeasureObjGeoData
& rMGeo
=(SdrMeasureObjGeoData
&)rGeo
;
1184 void SdrMeasureObj::RestGeoData(const SdrObjGeoData
& rGeo
)
1186 SdrTextObj::RestGeoData(rGeo
);
1187 SdrMeasureObjGeoData
& rMGeo
=(SdrMeasureObjGeoData
&)rGeo
;
1193 SdrObject
* SdrMeasureObj::DoConvertToPolyObj(BOOL bBezier
) const
1195 // get XOR Poly as base
1196 XPolyPolygon
aTmpPolyPolygon(TakeXorPoly());
1198 // get local ItemSet and StyleSheet
1199 SfxItemSet
aSet(GetObjectItemSet());
1200 SfxStyleSheet
* pStyleSheet
= GetStyleSheet();
1203 SdrObjGroup
* pGroup
= new SdrObjGroup
;
1204 pGroup
->SetModel(GetModel());
1206 // prepare parameters
1207 basegfx::B2DPolyPolygon aPolyPoly
;
1209 UINT16
nCount(aTmpPolyPolygon
.Count());
1210 UINT16
nLoopStart(0);
1214 // three lines, first one is the middle one
1216 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1218 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1219 pPath
->SetModel(GetModel());
1220 pPath
->SetMergedItemSet(aSet
);
1221 pPath
->SetStyleSheet(pStyleSheet
, true);
1222 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1223 aSet
.Put(XLineStartWidthItem(0L));
1224 aSet
.Put(XLineEndWidthItem(0L));
1227 else if(nCount
== 4)
1229 // four lines, middle line with gap, so there are two lines used
1230 // which have one arrow each
1231 //INT32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
1232 INT32 nEndWidth
= ((const XLineEndWidthItem
&)(aSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
1233 aSet
.Put(XLineEndWidthItem(0L));
1236 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1237 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1238 pPath
->SetModel(GetModel());
1239 pPath
->SetMergedItemSet(aSet
);
1240 pPath
->SetStyleSheet(pStyleSheet
, true);
1242 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1244 aSet
.Put(XLineEndWidthItem(nEndWidth
));
1245 aSet
.Put(XLineStartWidthItem(0L));
1248 aPolyPoly
.append(aTmpPolyPolygon
[1].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
);
1256 aSet
.Put(XLineEndWidthItem(0L));
1259 else if(nCount
== 5)
1261 // five lines, first two are the outer ones
1262 //INT32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
1263 INT32 nEndWidth
= ((const XLineEndWidthItem
&)(aSet
.Get(XATTR_LINEENDWIDTH
))).GetValue();
1265 aSet
.Put(XLineEndWidthItem(0L));
1268 aPolyPoly
.append(aTmpPolyPolygon
[0].getB2DPolygon());
1269 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1270 pPath
->SetModel(GetModel());
1271 pPath
->SetMergedItemSet(aSet
);
1272 pPath
->SetStyleSheet(pStyleSheet
, true);
1274 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1276 aSet
.Put(XLineEndWidthItem(nEndWidth
));
1277 aSet
.Put(XLineStartWidthItem(0L));
1280 aPolyPoly
.append(aTmpPolyPolygon
[1].getB2DPolygon());
1281 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1282 pPath
->SetModel(GetModel());
1283 pPath
->SetMergedItemSet(aSet
);
1284 pPath
->SetStyleSheet(pStyleSheet
, true);
1286 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1288 aSet
.Put(XLineEndWidthItem(0L));
1292 for(;nLoopStart
<nCount
;nLoopStart
++)
1295 aPolyPoly
.append(aTmpPolyPolygon
[nLoopStart
].getB2DPolygon());
1296 pPath
= new SdrPathObj(OBJ_PATHLINE
, aPolyPoly
);
1297 pPath
->SetModel(GetModel());
1298 pPath
->SetMergedItemSet(aSet
);
1299 pPath
->SetStyleSheet(pStyleSheet
, true);
1301 pGroup
->GetSubList()->NbcInsertObject(pPath
);
1304 return ImpConvertAddText(pGroup
, bBezier
);
1307 sal_Bool
SdrMeasureObj::BegTextEdit(SdrOutliner
& rOutl
)
1310 return SdrTextObj::BegTextEdit(rOutl
);
1313 const Size
& SdrMeasureObj::GetTextSize() const
1315 if (bTextDirty
) UndirtyText();
1316 return SdrTextObj::GetTextSize();
1319 OutlinerParaObject
* SdrMeasureObj::GetOutlinerParaObject() const
1323 return SdrTextObj::GetOutlinerParaObject();
1326 void SdrMeasureObj::NbcSetOutlinerParaObject(OutlinerParaObject
* pTextObject
)
1328 SdrTextObj::NbcSetOutlinerParaObject(pTextObject
);
1329 if(SdrTextObj::GetOutlinerParaObject())
1330 SetTextDirty(); // Text neu berechnen!
1333 void SdrMeasureObj::TakeTextRect( SdrOutliner
& rOutliner
, Rectangle
& rTextRect
, FASTBOOL bNoEditText
,
1334 Rectangle
* pAnchorRect
, BOOL bLineWidth
) const
1336 if (bTextDirty
) UndirtyText();
1337 SdrTextObj::TakeTextRect( rOutliner
, rTextRect
, bNoEditText
, pAnchorRect
, bLineWidth
);
1340 void SdrMeasureObj::TakeTextAnchorRect(Rectangle
& rAnchorRect
) const
1342 if (bTextDirty
) UndirtyText();
1343 SdrTextObj::TakeTextAnchorRect(rAnchorRect
);
1346 void SdrMeasureObj::TakeTextEditArea(Size
* pPaperMin
, Size
* pPaperMax
, Rectangle
* pViewInit
, Rectangle
* pViewMin
) const
1348 if (bTextDirty
) UndirtyText();
1349 SdrTextObj::TakeTextEditArea(pPaperMin
,pPaperMax
,pViewInit
,pViewMin
);
1352 USHORT
SdrMeasureObj::GetOutlinerViewAnchorMode() const
1354 if (bTextDirty
) UndirtyText();
1356 ImpMeasurePoly aMPol
;
1358 ImpCalcGeometrics(aRec
,aMPol
);
1360 SdrTextHorzAdjust eTH
=GetTextHorizontalAdjust();
1361 SdrTextVertAdjust eTV
=GetTextVerticalAdjust();
1362 SdrMeasureTextHPos eMH
=aMPol
.eUsedTextHPos
;
1363 SdrMeasureTextVPos eMV
=aMPol
.eUsedTextVPos
;
1364 FASTBOOL bTextRota90
=aRec
.bTextRota90
;
1365 //FASTBOOL bTextUpsideDown=aRec.bTextUpsideDown;
1366 FASTBOOL bBelowRefEdge
=aRec
.bBelowRefEdge
;
1368 // bTextUpsideDown muss hier noch ausgewertet werden!!!!
1370 if (eMH
==SDRMEASURE_TEXTLEFTOUTSIDE
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1371 if (eMH
==SDRMEASURE_TEXTRIGHTOUTSIDE
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1372 // bei eMH==SDRMEASURE_TEXTINSIDE kann horizontal geankert werden.
1373 if (eMV
==SDRMEASURE_ABOVE
) eTV
=SDRTEXTVERTADJUST_BOTTOM
;
1374 if (eMV
==SDRMEASURE_BELOW
) eTV
=SDRTEXTVERTADJUST_TOP
;
1375 if (eMV
==SDRMEASURETEXT_BREAKEDLINE
|| eMV
==SDRMEASURETEXT_VERTICALCENTERED
) eTV
=SDRTEXTVERTADJUST_CENTER
;
1377 if (eMH
==SDRMEASURE_TEXTLEFTOUTSIDE
) eTV
=SDRTEXTVERTADJUST_BOTTOM
;
1378 if (eMH
==SDRMEASURE_TEXTRIGHTOUTSIDE
) eTV
=SDRTEXTVERTADJUST_TOP
;
1379 // bei eMH==SDRMEASURE_TEXTINSIDE kann vertikal geankert werden.
1380 if (!bBelowRefEdge
) {
1381 if (eMV
==SDRMEASURE_ABOVE
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1382 if (eMV
==SDRMEASURE_BELOW
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1384 if (eMV
==SDRMEASURE_ABOVE
) eTH
=SDRTEXTHORZADJUST_RIGHT
;
1385 if (eMV
==SDRMEASURE_BELOW
) eTH
=SDRTEXTHORZADJUST_LEFT
;
1387 if (eMV
==SDRMEASURETEXT_BREAKEDLINE
|| eMV
==SDRMEASURETEXT_VERTICALCENTERED
) eTH
=SDRTEXTHORZADJUST_CENTER
;
1390 EVAnchorMode eRet
=ANCHOR_BOTTOM_HCENTER
;
1391 if (eTH
==SDRTEXTHORZADJUST_LEFT
) {
1392 if (eTV
==SDRTEXTVERTADJUST_TOP
) eRet
=ANCHOR_TOP_LEFT
;
1393 else if (eTV
==SDRTEXTVERTADJUST_BOTTOM
) eRet
=ANCHOR_BOTTOM_LEFT
;
1394 else eRet
=ANCHOR_VCENTER_LEFT
;
1395 } else if (eTH
==SDRTEXTHORZADJUST_RIGHT
) {
1396 if (eTV
==SDRTEXTVERTADJUST_TOP
) eRet
=ANCHOR_TOP_RIGHT
;
1397 else if (eTV
==SDRTEXTVERTADJUST_BOTTOM
) eRet
=ANCHOR_BOTTOM_RIGHT
;
1398 else eRet
=ANCHOR_VCENTER_RIGHT
;
1400 if (eTV
==SDRTEXTVERTADJUST_TOP
) eRet
=ANCHOR_TOP_HCENTER
;
1401 else if (eTV
==SDRTEXTVERTADJUST_BOTTOM
) eRet
=ANCHOR_BOTTOM_HCENTER
;
1402 else eRet
=ANCHOR_VCENTER_HCENTER
;
1404 return (USHORT
)eRet
;
1407 //////////////////////////////////////////////////////////////////////////////
1409 // TRGetBaseGeometry/TRSetBaseGeometry needs to be based on two positions,
1410 // same as line geometry in SdrPathObj. Thus needs to be overloaded and
1411 // implemented since currently it is derived from SdrTextObj which uses
1412 // a functionality based on SnapRect which is not useful here
1414 inline double ImplTwipsToMM(double fVal
) { return (fVal
* (127.0 / 72.0)); }
1415 inline double ImplMMToTwips(double fVal
) { return (fVal
* (72.0 / 127.0)); }
1417 sal_Bool
SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
1419 // handle the same as a simple line since the definition is based on two points
1420 const basegfx::B2DRange
aRange(aPt1
.X(), aPt1
.Y(), aPt2
.X(), aPt2
.Y());
1421 basegfx::B2DTuple
aScale(aRange
.getRange());
1422 basegfx::B2DTuple
aTranslate(aRange
.getMinimum());
1424 // position maybe relative to anchorpos, convert
1425 if( pModel
->IsWriter() )
1427 if(GetAnchorPos().X() || GetAnchorPos().Y())
1429 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1433 // force MapUnit to 100th mm
1434 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
1435 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
1439 case SFX_MAPUNIT_TWIP
:
1442 aTranslate
.setX(ImplTwipsToMM(aTranslate
.getX()));
1443 aTranslate
.setY(ImplTwipsToMM(aTranslate
.getY()));
1446 aScale
.setX(ImplTwipsToMM(aScale
.getX()));
1447 aScale
.setY(ImplTwipsToMM(aScale
.getY()));
1453 DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1458 // build return value matrix
1461 if(!basegfx::fTools::equal(aScale
.getX(), 1.0) || !basegfx::fTools::equal(aScale
.getY(), 1.0))
1463 rMatrix
.scale(aScale
.getX(), aScale
.getY());
1466 if(!aTranslate
.equalZero())
1468 rMatrix
.translate(aTranslate
.getX(), aTranslate
.getY());
1474 void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
1476 // use given transformation to derive the two defining points from unit line
1477 basegfx::B2DPoint
aPosA(rMatrix
* basegfx::B2DPoint(0.0, 0.0));
1478 basegfx::B2DPoint
aPosB(rMatrix
* basegfx::B2DPoint(1.0, 0.0));
1480 // force metric to pool metric
1481 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
1482 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
1486 case SFX_MAPUNIT_TWIP
:
1489 aPosA
.setX(ImplMMToTwips(aPosA
.getX()));
1490 aPosA
.setY(ImplMMToTwips(aPosA
.getY()));
1491 aPosB
.setX(ImplMMToTwips(aPosB
.getX()));
1492 aPosB
.setY(ImplMMToTwips(aPosB
.getY()));
1498 DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1503 if( pModel
->IsWriter() )
1505 // if anchor is used, make position relative to it
1506 if(GetAnchorPos().X() || GetAnchorPos().Y())
1508 const basegfx::B2DVector
aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y());
1510 aPosA
+= aAnchorOffset
;
1511 aPosB
+= aAnchorOffset
;
1515 // derive new model data
1516 const Point
aNewPt1(basegfx::fround(aPosA
.getX()), basegfx::fround(aPosA
.getY()));
1517 const Point
aNewPt2(basegfx::fround(aPosB
.getX()), basegfx::fround(aPosB
.getY()));
1519 if(aNewPt1
!= aPt1
|| aNewPt2
!= aPt2
)
1521 // set model values and broadcast
1522 Rectangle aBoundRect0
; if (pUserCall
!=NULL
) aBoundRect0
=GetLastBoundRect();
1530 BroadcastObjectChange();
1531 SendUserCall(SDRUSERCALL_MOVEONLY
,aBoundRect0
);
1535 //////////////////////////////////////////////////////////////////////////////