Update ooo320-m1
[ooovba.git] / svx / source / svdraw / svdomeas.cxx
blob975d5dea92a7617a149c39ebfd3a2f24461c1941
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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>
35 #include <math.h>
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)
100 UINT16 nFieldKind;
101 rIn>>nFieldKind;
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
112 rStr.Erase();
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:
132 if(pModel)
134 eModUIUnit = pModel->GetUIUnit();
136 if(eMeasureUnit == FUNIT_NONE)
137 eMeasureUnit = eModUIUnit;
139 INT32 nLen(GetLen(rObj.aPt2 - rObj.aPt1));
140 Fraction aFact(1,1);
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);
161 if(!aFact.IsValid())
163 rStr = String();
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'))
175 rStr.Erase(nLen2);
176 nLen2--;
179 if(rStr.GetChar(nLen2) == cDec)
181 rStr.Erase(nLen2);
182 nLen2--;
185 if(!rStr.Len())
186 rStr += sal_Unicode('0');
189 else
191 // falls kein Model da ... (z.B. Preview im Dialog)
192 rStr = String();
193 rStr.AppendAscii("4711");
196 break;
198 case SDRMEASUREFIELD_UNIT:
200 if(bShowUnit)
202 if(rObj.pModel)
204 eModUIUnit = pModel->GetUIUnit();
206 if(eMeasureUnit == FUNIT_NONE)
207 eMeasureUnit = eModUIUnit;
209 if(bShowUnit)
210 pModel->TakeUnitStr(eMeasureUnit, rStr);
214 break;
216 case SDRMEASUREFIELD_ROTA90BLANCS:
218 if(bTextRota90)
220 rStr = String();
221 rStr += sal_Unicode(' ');
224 break;
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():
250 bTextDirty(FALSE)
252 // #i25616#
253 mbSupportTextIndentingOnLineWidthChange = sal_False;
256 SdrMeasureObj::SdrMeasureObj(const Point& rPt1, const Point& rPt2):
257 aPt1(rPt1),
258 aPt2(rPt2),
259 bTextDirty(FALSE)
261 // #i25616#
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
300 Point aPt1;
301 Point aPt2;
302 SdrMeasureKind eKind;
303 SdrMeasureTextHPos eWantTextHPos;
304 SdrMeasureTextVPos eWantTextVPos;
305 long nLineDist;
306 long nHelplineOverhang;
307 long nHelplineDist;
308 long nHelpline1Len;
309 long nHelpline2Len;
310 FASTBOOL bBelowRefEdge;
311 FASTBOOL bTextRota90;
312 FASTBOOL bTextUpsideDown;
313 long nMeasureOverhang;
314 FieldUnit eMeasureUnit;
315 Fraction aMeasureScale;
316 FASTBOOL bShowUnit;
317 String aFormatString;
318 FASTBOOL bTextAutoAngle;
319 long nTextAutoAngleView;
320 FASTBOOL bTextIsFixedAngle;
321 long nTextFixedAngle;
324 struct ImpLineRec
326 Point aP1;
327 Point aP2;
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;
337 Rectangle aTextRect;
338 Size aTextSize;
339 long nLineLen;
340 long nLineWink;
341 long nTextWink;
342 long nHlpWink;
343 double nLineSin;
344 double nLineCos;
345 double nHlpSin;
346 double nHlpCos;
347 USHORT nMainlineAnz;
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
365 rRec.aPt1 = aPt1;
366 rRec.aPt2 = aPt2;
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));
398 if(bCenter)
400 nHeight /= 2L;
403 return nHeight;
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);
415 rPol.nLineWdt2=0;
416 long nArrow1Len=0; bool bArrow1Center=false;
417 long nArrow2Len=0; bool bArrow2Center=false;
418 long nArrow1Wdt=0;
419 long nArrow2Wdt=0;
420 rPol.nArrow1Wdt=0;
421 rPol.nArrow2Wdt=0;
422 long nArrowNeed=0;
423 long nShortLen=0;
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();
431 if(nArrow1Wdt < 0)
432 nArrow1Wdt = -nLineWdt * nArrow1Wdt / 100; // <0 = relativ
434 nArrow2Wdt = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue();
435 if(nArrow2Wdt < 0)
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
468 if (bBrkLine) {
469 if (nNeedSiz+nArrowNeed>rPol.nLineLen) bPfeileAussen=TRUE; // Text passt in die Mitte, wenn die Pfeile nach aussen kommen
470 } else {
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) {
513 nHlpSin=-nHlpSin;
514 nHlpCos=-nHlpCos;
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);
532 // Masshilfslinie 1
533 rPol.aHelpline1.aP1=Point(aP1.X()+dxh1a,aP1.Y()+dyh1a);
534 rPol.aHelpline1.aP2=Point(aP1.X()+dxh2,aP1.Y()+dyh2);
536 // Masshilfslinie 2
537 rPol.aHelpline2.aP1=Point(aP2.X()+dxh1b,aP2.Y()+dyh1b);
538 rPol.aHelpline2.aP2=Point(aP2.X()+dxh2,aP2.Y()+dyh2);
540 // Masslinie(n)
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;
548 rPol.nMainlineAnz=1;
549 if (bBrkLine) {
550 long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height();
551 long nHalfLen=(rPol.nLineLen-nNeedSiz-nArrow1Wdt/4-nArrow2Wdt/4) /2;
552 rPol.nMainlineAnz=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);
560 } else {
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();
564 if (!bBrkLine) {
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;
574 rPol.nMainlineAnz=3;
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)
589 aPartPolyA.clear();
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)
597 aPartPolyA.clear();
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);
603 aPartPolyA.clear();
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);
608 aPartPolyA.clear();
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);
613 return aRetval;
616 FASTBOOL SdrMeasureObj::CalcFieldValue(const SvxFieldItem& rField, USHORT nPara, USHORT nPos,
617 FASTBOOL bEdit,
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) {
625 if (!bEdit)
627 delete rpFldColor;
628 rpFldColor=NULL;
631 return TRUE;
632 } else {
633 return SdrTextObj::CalcFieldValue(rField,nPara,nPos,bEdit,rpTxtColor,rpFldColor,rRet);
637 void SdrMeasureObj::UndirtyText() const
639 if (bTextDirty)
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));
650 if(GetStyleSheet())
651 rOutliner.SetStyleSheet(0, GetStyleSheet());
653 rOutliner.SetParaAttribs(0, GetObjectItemSet());
655 // casting auf nonconst
656 const_cast<SdrMeasureObj*>(this)->NbcSetOutlinerParaObject( rOutliner.CreateParaObject() );
658 else
660 rOutliner.SetText(*pOutlinerParaObject);
663 rOutliner.SetUpdateMode(TRUE);
664 rOutliner.UpdateFields();
665 Size aSiz(rOutliner.CalcTextSize());
666 rOutliner.Clear();
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();
677 ImpMeasureRec aRec;
678 ImpMeasurePoly aMPol;
679 ImpTakeAttr(aRec);
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;
701 Point aTextPos;
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;
707 if (!bRota90) {
708 switch (eMH) {
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;
713 switch (eMV) {
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;
719 } break;
720 default: {
721 if (!bUpsideDown) aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()-nLWdt;
722 else aTextPos.Y()=aPt1b.Y()+nLWdt;
725 if (bUpsideDown) {
726 aTextPos.X()+=aTextSize2.Width();
727 aTextPos.Y()+=aTextSize2.Height();
729 } else { // also wenn bTextRota90==TRUE
730 switch (eMH) {
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;
735 switch (eMV) {
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;
741 } break;
742 default: {
743 if (!bBelowRefEdge) aTextPos.Y()=aPt1b.Y()-nLWdt;
744 else aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()+nLWdt;
747 if (bUpsideDown) {
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);
759 rRect.Justify();
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() );
781 if(aName.Len())
783 rName += sal_Unicode(' ');
784 rName += sal_Unicode('\'');
785 rName += aName;
786 rName += sal_Unicode('\'');
790 void SdrMeasureObj::TakeObjNamePlural(XubString& rName) const
792 rName=ImpGetResStr(STR_ObjNamePluralMEASURE);
795 basegfx::B2DPolyPolygon SdrMeasureObj::TakeXorPoly() const
797 ImpMeasureRec aRec;
798 ImpMeasurePoly aMPol;
799 ImpTakeAttr(aRec);
800 ImpCalcGeometrics(aRec,aMPol);
801 return ImpCalcXPoly(aMPol);
804 sal_uInt32 SdrMeasureObj::GetHdlCount() const
806 return 6L;
809 SdrHdl* SdrMeasureObj::GetHdl(sal_uInt32 nHdlNum) const
811 ImpMeasureRec aRec;
812 ImpMeasurePoly aMPol;
813 ImpTakeAttr(aRec);
814 aRec.nHelplineDist=0;
815 ImpCalcGeometrics(aRec,aMPol);
816 Point aPt;
817 //SdrHdlKind eHdl=HDL_POLY;
818 switch (nHdlNum) {
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;
825 } // switch
826 SdrHdl* pHdl=new ImpMeasureHdl(aPt,HDL_USER);
827 pHdl->SetObjHdlNum(nHdlNum);
828 pHdl->SetDrehWink(aMPol.nLineWink);
829 return pHdl;
832 ////////////////////////////////////////////////////////////////////////////////////////////////////
834 bool SdrMeasureObj::hasSpecialDrag() const
836 return true;
839 bool SdrMeasureObj::beginSpecialDrag(SdrDragStat& rDrag) const
841 const SdrHdl* pHdl = rDrag.GetHdl();
843 if(pHdl)
845 const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
847 if(nHdlNum != 2 && nHdlNum != 3)
849 rDrag.SetEndDragChangesAttributes(true);
852 return true;
855 return false;
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);
867 switch (nHdlNum)
869 case 2:
871 aPt1 = aMeasureRec.aPt1;
872 SetTextDirty();
873 break;
875 case 3:
877 aPt2 = aMeasureRec.aPt2;
878 SetTextDirty();
879 break;
881 default:
883 switch(nHdlNum)
885 case 0:
886 case 1:
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));
901 break;
904 case 4:
905 case 5:
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));
922 } // switch
924 SetRectsDirty();
925 SetChanged();
927 return true;
930 String SdrMeasureObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const
932 XubString aStr;
933 return aStr;
936 void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec& rRec, const SdrDragStat& rDrag) const
938 long nLineWink=GetAngle(rRec.aPt2-rRec.aPt1);
939 double a=nLineWink*nPi180;
940 double nSin=sin(a);
941 double nCos=cos(a);
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());
950 switch (nHdlNum) {
951 case 0: {
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;
956 } break;
957 case 1: {
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;
962 } break;
963 case 2: case 3: {
964 FASTBOOL bAnf=nHdlNum==2;
965 Point& rMov=bAnf ? rRec.aPt1 : rRec.aPt2;
966 Point aMov(rMov);
967 Point aFix(bAnf ? rRec.aPt2 : rRec.aPt1);
968 if (bOrtho) {
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);
982 aPt=aFix;
983 aPt.X()+=ndx;
984 aPt.Y()+=ndy;
985 } // else Ortho8
987 rMov=aPt;
988 } break;
989 case 4: case 5: {
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;
1000 } break;
1001 } // switch
1004 ////////////////////////////////////////////////////////////////////////////////////////////////////
1006 FASTBOOL SdrMeasureObj::BegCreate(SdrDragStat& rStat)
1008 rStat.SetOrtho8Possible();
1009 aPt1=rStat.GetStart();
1010 aPt2=rStat.GetNow();
1011 SetTextDirty();
1012 return TRUE;
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()) {
1021 aPt1+=aPt1;
1022 aPt1-=rStat.Now();
1024 SetTextDirty();
1025 SetBoundRectDirty();
1026 bSnapRectDirty=TRUE;
1027 return TRUE;
1030 FASTBOOL SdrMeasureObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
1032 SetTextDirty();
1033 SetRectsDirty();
1034 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
1037 FASTBOOL SdrMeasureObj::BckCreate(SdrDragStat& /*rStat*/)
1039 return FALSE;
1042 void SdrMeasureObj::BrkCreate(SdrDragStat& /*rStat*/)
1046 basegfx::B2DPolyPolygon SdrMeasureObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
1048 ImpMeasureRec aRec;
1049 ImpMeasurePoly aMPol;
1051 ImpTakeAttr(aRec);
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);
1074 SetTextDirty();
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);
1089 if (rRef==aPt2) {
1090 aPt1.X()=aPt2.X()-dx;
1091 aPt1.Y()=aPt2.Y()-dy;
1092 } else {
1093 aPt2.X()=aPt1.X()+dx;
1094 aPt2.Y()=aPt1.Y()+dy;
1097 SetRectsDirty();
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);
1105 SetRectsDirty();
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);
1113 SetRectsDirty();
1114 SetTextDirty();
1117 long SdrMeasureObj::GetRotateAngle() const
1119 return GetAngle(aPt2-aPt1);
1122 void SdrMeasureObj::RecalcSnapRect()
1124 // #94520# Added correct implementation here.
1125 ImpMeasureRec aRec;
1126 ImpMeasurePoly aMPol;
1127 XPolyPolygon aXPP;
1129 ImpTakeAttr(aRec);
1130 ImpCalcGeometrics(aRec, aMPol);
1131 aXPP = XPolyPolygon(ImpCalcXPoly(aMPol));
1132 maSnapRect = aXPP.GetBoundRect();
1135 sal_uInt32 SdrMeasureObj::GetSnapPointCount() const
1137 return 2L;
1140 Point SdrMeasureObj::GetSnapPoint(sal_uInt32 i) const
1142 if (i==0) return aPt1;
1143 else return aPt2;
1146 sal_Bool SdrMeasureObj::IsPolyObj() const
1148 return sal_True;
1151 sal_uInt32 SdrMeasureObj::GetPointCount() const
1153 return 2L;
1156 Point SdrMeasureObj::GetPoint(sal_uInt32 i) const
1158 return (0L == i) ? aPt1 : aPt2;
1161 void SdrMeasureObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
1163 if (0L == i)
1164 aPt1=rPnt;
1165 if (1L == i)
1166 aPt2=rPnt;
1167 SetRectsDirty();
1168 SetTextDirty();
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;
1180 rMGeo.aPt1=aPt1;
1181 rMGeo.aPt2=aPt2;
1184 void SdrMeasureObj::RestGeoData(const SdrObjGeoData& rGeo)
1186 SdrTextObj::RestGeoData(rGeo);
1187 SdrMeasureObjGeoData& rMGeo=(SdrMeasureObjGeoData&)rGeo;
1188 aPt1=rMGeo.aPt1;
1189 aPt2=rMGeo.aPt2;
1190 SetTextDirty();
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();
1202 // prepare group
1203 SdrObjGroup* pGroup = new SdrObjGroup;
1204 pGroup->SetModel(GetModel());
1206 // prepare parameters
1207 basegfx::B2DPolyPolygon aPolyPoly;
1208 SdrPathObj* pPath;
1209 UINT16 nCount(aTmpPolyPolygon.Count());
1210 UINT16 nLoopStart(0);
1212 if(nCount == 3)
1214 // three lines, first one is the middle one
1215 aPolyPoly.clear();
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));
1225 nLoopStart = 1;
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));
1235 aPolyPoly.clear();
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));
1247 aPolyPoly.clear();
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));
1257 nLoopStart = 2;
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));
1267 aPolyPoly.clear();
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));
1279 aPolyPoly.clear();
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));
1289 nLoopStart = 2;
1292 for(;nLoopStart<nCount;nLoopStart++)
1294 aPolyPoly.clear();
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)
1309 UndirtyText();
1310 return SdrTextObj::BegTextEdit(rOutl);
1313 const Size& SdrMeasureObj::GetTextSize() const
1315 if (bTextDirty) UndirtyText();
1316 return SdrTextObj::GetTextSize();
1319 OutlinerParaObject* SdrMeasureObj::GetOutlinerParaObject() const
1321 if(bTextDirty)
1322 UndirtyText();
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();
1355 ImpMeasureRec aRec;
1356 ImpMeasurePoly aMPol;
1357 ImpTakeAttr(aRec);
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!!!!
1369 if (!bTextRota90) {
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;
1376 } else {
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;
1383 } else {
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;
1399 } else {
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 //////////////////////////////////////////////////////////////////////////////
1408 // #i97878#
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)
1437 switch(eMapUnit)
1439 case SFX_MAPUNIT_TWIP :
1441 // postion
1442 aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
1443 aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
1445 // size
1446 aScale.setX(ImplTwipsToMM(aScale.getX()));
1447 aScale.setY(ImplTwipsToMM(aScale.getY()));
1449 break;
1451 default:
1453 DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1458 // build return value matrix
1459 rMatrix.identity();
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());
1471 return sal_True;
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)
1484 switch(eMapUnit)
1486 case SFX_MAPUNIT_TWIP :
1488 // position
1489 aPosA.setX(ImplMMToTwips(aPosA.getX()));
1490 aPosA.setY(ImplMMToTwips(aPosA.getY()));
1491 aPosB.setX(ImplMMToTwips(aPosB.getX()));
1492 aPosB.setY(ImplMMToTwips(aPosB.getY()));
1494 break;
1496 default:
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();
1524 aPt1 = aNewPt1;
1525 aPt2 = aNewPt2;
1527 SetTextDirty();
1528 ActionChanged();
1529 SetChanged();
1530 BroadcastObjectChange();
1531 SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
1535 //////////////////////////////////////////////////////////////////////////////
1536 // eof