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