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