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.QuickInsertText(String(sal_Unicode(' ')), ESelection(0,2)); 612 rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_UNIT), EE_FEATURE_FIELD),ESelection(0,3)); 613 rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SDRMEASUREFIELD_ROTA90BLANCS), EE_FEATURE_FIELD),ESelection(0,4)); 614 615 if(GetStyleSheet()) 616 rOutliner.SetStyleSheet(0, GetStyleSheet()); 617 618 rOutliner.SetParaAttribs(0, GetObjectItemSet()); 619 620 // casting auf nonconst 621 const_cast<SdrMeasureObj*>(this)->NbcSetOutlinerParaObject( rOutliner.CreateParaObject() ); 622 } 623 else 624 { 625 rOutliner.SetText(*pOutlinerParaObject); 626 } 627 628 rOutliner.SetUpdateMode(sal_True); 629 rOutliner.UpdateFields(); 630 Size aSiz(rOutliner.CalcTextSize()); 631 rOutliner.Clear(); 632 // 3x casting auf nonconst 633 ((SdrMeasureObj*)this)->aTextSize=aSiz; 634 ((SdrMeasureObj*)this)->bTextSizeDirty=sal_False; 635 ((SdrMeasureObj*)this)->bTextDirty=sal_False; 636 } 637 } 638 639 void SdrMeasureObj::TakeUnrotatedSnapRect(Rectangle& rRect) const 640 { 641 if (bTextDirty) UndirtyText(); 642 ImpMeasureRec aRec; 643 ImpMeasurePoly aMPol; 644 ImpTakeAttr(aRec); 645 ImpCalcGeometrics(aRec,aMPol); 646 647 // TextSize ermitteln inkl. Textrahmenabstaende 648 Size aTextSize2(aMPol.aTextSize); 649 if (aTextSize2.Width()<1) aTextSize2.Width()=1; 650 if (aTextSize2.Height()<1) aTextSize2.Height()=1; 651 aTextSize2.Width()+=GetTextLeftDistance()+GetTextRightDistance(); 652 aTextSize2.Height()+=GetTextUpperDistance()+GetTextLowerDistance(); 653 654 Point aPt1b(aMPol.aMainline1.aP1); 655 long nLen=aMPol.nLineLen; 656 long nLWdt=aMPol.nLineWdt2; 657 long nArr1Len=aMPol.nArrow1Len; 658 long nArr2Len=aMPol.nArrow2Len; 659 if (aMPol.bBreakedLine) { 660 // Bei Unterbrochener Linie und Outside muss der Text nicht neben den 661 // Pfeil sondern neben die Linie an dem Pfeil plaziert werden 662 nArr1Len=aMPol.nShortLineLen+aMPol.nArrow1Wdt/4; 663 nArr2Len=aMPol.nShortLineLen+aMPol.nArrow2Wdt/4; 664 } 665 666 Point aTextPos; 667 FASTBOOL bRota90=aRec.bTextRota90; 668 FASTBOOL bUpsideDown=aRec.bTextUpsideDown!=aMPol.bAutoUpsideDown; 669 FASTBOOL bBelowRefEdge=aRec.bBelowRefEdge; 670 SdrMeasureTextHPos eMH=aMPol.eUsedTextHPos; 671 SdrMeasureTextVPos eMV=aMPol.eUsedTextVPos; 672 if (!bRota90) { 673 switch (eMH) { 674 case SDRMEASURE_TEXTLEFTOUTSIDE: aTextPos.X()=aPt1b.X()-aTextSize2.Width()-nArr1Len-nLWdt; break; 675 case SDRMEASURE_TEXTRIGHTOUTSIDE: aTextPos.X()=aPt1b.X()+nLen+nArr2Len+nLWdt; break; 676 default: aTextPos.X()=aPt1b.X(); aTextSize2.Width()=nLen; 677 } 678 switch (eMV) { 679 case SDRMEASURETEXT_VERTICALCENTERED: 680 case SDRMEASURETEXT_BREAKEDLINE: aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()/2; break; 681 case SDRMEASURE_BELOW: { 682 if (!bUpsideDown) aTextPos.Y()=aPt1b.Y()+nLWdt; 683 else aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()-nLWdt; 684 } break; 685 default: { 686 if (!bUpsideDown) aTextPos.Y()=aPt1b.Y()-aTextSize2.Height()-nLWdt; 687 else aTextPos.Y()=aPt1b.Y()+nLWdt; 688 } 689 } 690 if (bUpsideDown) { 691 aTextPos.X()+=aTextSize2.Width(); 692 aTextPos.Y()+=aTextSize2.Height(); 693 } 694 } else { // also wenn bTextRota90==TRUE 695 switch (eMH) { 696 case SDRMEASURE_TEXTLEFTOUTSIDE: aTextPos.X()=aPt1b.X()-aTextSize2.Height()-nArr1Len; break; 697 case SDRMEASURE_TEXTRIGHTOUTSIDE: aTextPos.X()=aPt1b.X()+nLen+nArr2Len; break; 698 default: aTextPos.X()=aPt1b.X(); aTextSize2.Height()=nLen; 699 } 700 switch (eMV) { 701 case SDRMEASURETEXT_VERTICALCENTERED: 702 case SDRMEASURETEXT_BREAKEDLINE: aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()/2; break; 703 case SDRMEASURE_BELOW: { 704 if (!bBelowRefEdge) aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()+nLWdt; 705 else aTextPos.Y()=aPt1b.Y()-nLWdt; 706 } break; 707 default: { 708 if (!bBelowRefEdge) aTextPos.Y()=aPt1b.Y()-nLWdt; 709 else aTextPos.Y()=aPt1b.Y()+aTextSize2.Width()+nLWdt; 710 } 711 } 712 if (bUpsideDown) { 713 aTextPos.X()+=aTextSize2.Height(); 714 aTextPos.Y()-=aTextSize2.Width(); 715 } 716 } 717 if (aMPol.nTextWink!=aGeo.nDrehWink) { 718 ((SdrMeasureObj*)this)->aGeo.nDrehWink=aMPol.nTextWink; 719 ((SdrMeasureObj*)this)->aGeo.RecalcSinCos(); 720 } 721 RotatePoint(aTextPos,aPt1b,aMPol.nLineSin,aMPol.nLineCos); 722 aTextSize2.Width()++; aTextSize2.Height()++; // wg. des komischen Verhaltens beim Rect-Ctor 723 rRect=Rectangle(aTextPos,aTextSize2); 724 rRect.Justify(); 725 ((SdrMeasureObj*)this)->aRect=rRect; 726 727 if (aMPol.nTextWink!=aGeo.nDrehWink) { 728 ((SdrMeasureObj*)this)->aGeo.nDrehWink=aMPol.nTextWink; 729 ((SdrMeasureObj*)this)->aGeo.RecalcSinCos(); 730 } 731 } 732 733 void SdrMeasureObj::operator=(const SdrObject& rObj) 734 { 735 SdrTextObj::operator=(rObj); 736 aPt1=((SdrMeasureObj&)rObj).aPt1; 737 aPt2=((SdrMeasureObj&)rObj).aPt2; 738 bTextDirty=((SdrMeasureObj&)rObj).bTextDirty; 739 } 740 741 void SdrMeasureObj::TakeObjNameSingul(XubString& rName) const 742 { 743 rName=ImpGetResStr(STR_ObjNameSingulMEASURE); 744 745 String aName( GetName() ); 746 if(aName.Len()) 747 { 748 rName += sal_Unicode(' '); 749 rName += sal_Unicode('\''); 750 rName += aName; 751 rName += sal_Unicode('\''); 752 } 753 } 754 755 void SdrMeasureObj::TakeObjNamePlural(XubString& rName) const 756 { 757 rName=ImpGetResStr(STR_ObjNamePluralMEASURE); 758 } 759 760 basegfx::B2DPolyPolygon SdrMeasureObj::TakeXorPoly() const 761 { 762 ImpMeasureRec aRec; 763 ImpMeasurePoly aMPol; 764 ImpTakeAttr(aRec); 765 ImpCalcGeometrics(aRec,aMPol); 766 return ImpCalcXPoly(aMPol); 767 } 768 769 sal_uInt32 SdrMeasureObj::GetHdlCount() const 770 { 771 return 6L; 772 } 773 774 SdrHdl* SdrMeasureObj::GetHdl(sal_uInt32 nHdlNum) const 775 { 776 ImpMeasureRec aRec; 777 ImpMeasurePoly aMPol; 778 ImpTakeAttr(aRec); 779 aRec.nHelplineDist=0; 780 ImpCalcGeometrics(aRec,aMPol); 781 Point aPt; 782 //SdrHdlKind eHdl=HDL_POLY; 783 switch (nHdlNum) { 784 case 0: aPt=aMPol.aHelpline1.aP1; break; 785 case 1: aPt=aMPol.aHelpline2.aP1; break; 786 case 2: aPt=aPt1; break; 787 case 3: aPt=aPt2; break; 788 case 4: aPt=aMPol.aHelpline1.aP2; break; 789 case 5: aPt=aMPol.aHelpline2.aP2; break; 790 } // switch 791 SdrHdl* pHdl=new ImpMeasureHdl(aPt,HDL_USER); 792 pHdl->SetObjHdlNum(nHdlNum); 793 pHdl->SetDrehWink(aMPol.nLineWink); 794 return pHdl; 795 } 796 797 //////////////////////////////////////////////////////////////////////////////////////////////////// 798 799 bool SdrMeasureObj::hasSpecialDrag() const 800 { 801 return true; 802 } 803 804 bool SdrMeasureObj::beginSpecialDrag(SdrDragStat& rDrag) const 805 { 806 const SdrHdl* pHdl = rDrag.GetHdl(); 807 808 if(pHdl) 809 { 810 const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); 811 812 if(nHdlNum != 2 && nHdlNum != 3) 813 { 814 rDrag.SetEndDragChangesAttributes(true); 815 } 816 817 return true; 818 } 819 820 return false; 821 } 822 823 bool SdrMeasureObj::applySpecialDrag(SdrDragStat& rDrag) 824 { 825 ImpMeasureRec aMeasureRec; 826 const SdrHdl* pHdl = rDrag.GetHdl(); 827 const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); 828 829 ImpTakeAttr(aMeasureRec); 830 ImpEvalDrag(aMeasureRec, rDrag); 831 832 switch (nHdlNum) 833 { 834 case 2: 835 { 836 aPt1 = aMeasureRec.aPt1; 837 SetTextDirty(); 838 break; 839 } 840 case 3: 841 { 842 aPt2 = aMeasureRec.aPt2; 843 SetTextDirty(); 844 break; 845 } 846 default: 847 { 848 switch(nHdlNum) 849 { 850 case 0: 851 case 1: 852 { 853 ImpMeasureRec aOrigMeasureRec; 854 ImpTakeAttr(aOrigMeasureRec); 855 856 if(aMeasureRec.nHelpline1Len != aOrigMeasureRec.nHelpline1Len) 857 { 858 SetObjectItem(SdrMeasureHelpline1LenItem(aMeasureRec.nHelpline1Len)); 859 } 860 861 if(aMeasureRec.nHelpline2Len != aOrigMeasureRec.nHelpline2Len) 862 { 863 SetObjectItem(SdrMeasureHelpline2LenItem(aMeasureRec.nHelpline2Len)); 864 } 865 866 break; 867 } 868 869 case 4: 870 case 5: 871 { 872 ImpMeasureRec aOrigMeasureRec; 873 ImpTakeAttr(aOrigMeasureRec); 874 875 if(aMeasureRec.nLineDist != aOrigMeasureRec.nLineDist) 876 { 877 SetObjectItem(SdrMeasureLineDistItem(aMeasureRec.nLineDist)); 878 } 879 880 if(aMeasureRec.bBelowRefEdge != aOrigMeasureRec.bBelowRefEdge) 881 { 882 SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec.bBelowRefEdge)); 883 } 884 } 885 } 886 } 887 } // switch 888 889 SetRectsDirty(); 890 SetChanged(); 891 892 return true; 893 } 894 895 String SdrMeasureObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const 896 { 897 XubString aStr; 898 return aStr; 899 } 900 901 void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec& rRec, const SdrDragStat& rDrag) const 902 { 903 long nLineWink=GetAngle(rRec.aPt2-rRec.aPt1); 904 double a=nLineWink*nPi180; 905 double nSin=sin(a); 906 double nCos=cos(a); 907 908 const SdrHdl* pHdl=rDrag.GetHdl(); 909 sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); 910 FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho(); 911 FASTBOOL bBigOrtho=bOrtho && rDrag.GetView()->IsBigOrtho(); 912 FASTBOOL bBelow=rRec.bBelowRefEdge; 913 Point aPt(rDrag.GetNow()); 914 915 switch (nHdlNum) { 916 case 0: { 917 RotatePoint(aPt,aPt1,nSin,-nCos); 918 rRec.nHelpline1Len=aPt1.Y()-aPt.Y(); 919 if (bBelow) rRec.nHelpline1Len=-rRec.nHelpline1Len; 920 if (bOrtho) rRec.nHelpline2Len=rRec.nHelpline1Len; 921 } break; 922 case 1: { 923 RotatePoint(aPt,aPt2,nSin,-nCos); 924 rRec.nHelpline2Len=aPt2.Y()-aPt.Y(); 925 if (bBelow) rRec.nHelpline2Len=-rRec.nHelpline2Len; 926 if (bOrtho) rRec.nHelpline1Len=rRec.nHelpline2Len; 927 } break; 928 case 2: case 3: { 929 FASTBOOL bAnf=nHdlNum==2; 930 Point& rMov=bAnf ? rRec.aPt1 : rRec.aPt2; 931 Point aMov(rMov); 932 Point aFix(bAnf ? rRec.aPt2 : rRec.aPt1); 933 if (bOrtho) { 934 long ndx0=aMov.X()-aFix.X(); 935 long ndy0=aMov.Y()-aFix.Y(); 936 FASTBOOL bHLin=ndy0==0; 937 FASTBOOL bVLin=ndx0==0; 938 if (!bHLin || !bVLin) { // sonst ist aPt1==aPt2 939 long ndx=aPt.X()-aFix.X(); 940 long ndy=aPt.Y()-aFix.Y(); 941 double nXFact=0; if (!bVLin) nXFact=(double)ndx/(double)ndx0; 942 double nYFact=0; if (!bHLin) nYFact=(double)ndy/(double)ndy0; 943 FASTBOOL bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho); 944 FASTBOOL bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho); 945 if (bHor) ndy=long(ndy0*nXFact); 946 if (bVer) ndx=long(ndx0*nYFact); 947 aPt=aFix; 948 aPt.X()+=ndx; 949 aPt.Y()+=ndy; 950 } // else Ortho8 951 } 952 rMov=aPt; 953 } break; 954 case 4: case 5: { 955 long nVal0=rRec.nLineDist; 956 RotatePoint(aPt,(nHdlNum==4 ? aPt1 : aPt2),nSin,-nCos); 957 rRec.nLineDist=aPt.Y()- (nHdlNum==4 ? aPt1.Y() : aPt2.Y()); 958 if (bBelow) rRec.nLineDist=-rRec.nLineDist; 959 if (rRec.nLineDist<0) { 960 rRec.nLineDist=-rRec.nLineDist; 961 rRec.bBelowRefEdge=!bBelow; 962 } 963 rRec.nLineDist-=rRec.nHelplineOverhang; 964 if (bOrtho) rRec.nLineDist=nVal0; 965 } break; 966 } // switch 967 } 968 969 //////////////////////////////////////////////////////////////////////////////////////////////////// 970 971 FASTBOOL SdrMeasureObj::BegCreate(SdrDragStat& rStat) 972 { 973 rStat.SetOrtho8Possible(); 974 aPt1=rStat.GetStart(); 975 aPt2=rStat.GetNow(); 976 SetTextDirty(); 977 return sal_True; 978 } 979 980 FASTBOOL SdrMeasureObj::MovCreate(SdrDragStat& rStat) 981 { 982 SdrView* pView=rStat.GetView(); 983 aPt1=rStat.GetStart(); 984 aPt2=rStat.GetNow(); 985 if (pView!=NULL && pView->IsCreate1stPointAsCenter()) { 986 aPt1+=aPt1; 987 aPt1-=rStat.Now(); 988 } 989 SetTextDirty(); 990 SetBoundRectDirty(); 991 bSnapRectDirty=sal_True; 992 return sal_True; 993 } 994 995 FASTBOOL SdrMeasureObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) 996 { 997 SetTextDirty(); 998 SetRectsDirty(); 999 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); 1000 } 1001 1002 FASTBOOL SdrMeasureObj::BckCreate(SdrDragStat& /*rStat*/) 1003 { 1004 return sal_False; 1005 } 1006 1007 void SdrMeasureObj::BrkCreate(SdrDragStat& /*rStat*/) 1008 { 1009 } 1010 1011 basegfx::B2DPolyPolygon SdrMeasureObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const 1012 { 1013 ImpMeasureRec aRec; 1014 ImpMeasurePoly aMPol; 1015 1016 ImpTakeAttr(aRec); 1017 ImpCalcGeometrics(aRec, aMPol); 1018 1019 return ImpCalcXPoly(aMPol); 1020 } 1021 1022 Pointer SdrMeasureObj::GetCreatePointer() const 1023 { 1024 return Pointer(POINTER_CROSS); 1025 } 1026 1027 void SdrMeasureObj::NbcMove(const Size& rSiz) 1028 { 1029 SdrTextObj::NbcMove(rSiz); 1030 MovePoint(aPt1,rSiz); 1031 MovePoint(aPt2,rSiz); 1032 } 1033 1034 void SdrMeasureObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) 1035 { 1036 SdrTextObj::NbcResize(rRef,xFact,yFact); 1037 ResizePoint(aPt1,rRef,xFact,yFact); 1038 ResizePoint(aPt2,rRef,xFact,yFact); 1039 SetTextDirty(); 1040 } 1041 1042 void SdrMeasureObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) 1043 { 1044 SdrTextObj::NbcRotate(rRef,nWink,sn,cs); 1045 long nLen0=GetLen(aPt2-aPt1); 1046 RotatePoint(aPt1,rRef,sn,cs); 1047 RotatePoint(aPt2,rRef,sn,cs); 1048 long nLen1=GetLen(aPt2-aPt1); 1049 if (nLen1!=nLen0) { // Aha, Rundungsfehler 1050 long dx=aPt2.X()-aPt1.X(); 1051 long dy=aPt2.Y()-aPt1.Y(); 1052 dx=BigMulDiv(dx,nLen0,nLen1); 1053 dy=BigMulDiv(dy,nLen0,nLen1); 1054 if (rRef==aPt2) { 1055 aPt1.X()=aPt2.X()-dx; 1056 aPt1.Y()=aPt2.Y()-dy; 1057 } else { 1058 aPt2.X()=aPt1.X()+dx; 1059 aPt2.Y()=aPt1.Y()+dy; 1060 } 1061 } 1062 SetRectsDirty(); 1063 } 1064 1065 void SdrMeasureObj::NbcMirror(const Point& rRef1, const Point& rRef2) 1066 { 1067 SdrTextObj::NbcMirror(rRef1,rRef2); 1068 MirrorPoint(aPt1,rRef1,rRef2); 1069 MirrorPoint(aPt2,rRef1,rRef2); 1070 SetRectsDirty(); 1071 } 1072 1073 void SdrMeasureObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) 1074 { 1075 SdrTextObj::NbcShear(rRef,nWink,tn,bVShear); 1076 ShearPoint(aPt1,rRef,tn,bVShear); 1077 ShearPoint(aPt2,rRef,tn,bVShear); 1078 SetRectsDirty(); 1079 SetTextDirty(); 1080 } 1081 1082 long SdrMeasureObj::GetRotateAngle() const 1083 { 1084 return GetAngle(aPt2-aPt1); 1085 } 1086 1087 void SdrMeasureObj::RecalcSnapRect() 1088 { 1089 // #94520# Added correct implementation here. 1090 ImpMeasureRec aRec; 1091 ImpMeasurePoly aMPol; 1092 XPolyPolygon aXPP; 1093 1094 ImpTakeAttr(aRec); 1095 ImpCalcGeometrics(aRec, aMPol); 1096 aXPP = XPolyPolygon(ImpCalcXPoly(aMPol)); 1097 maSnapRect = aXPP.GetBoundRect(); 1098 } 1099 1100 sal_uInt32 SdrMeasureObj::GetSnapPointCount() const 1101 { 1102 return 2L; 1103 } 1104 1105 Point SdrMeasureObj::GetSnapPoint(sal_uInt32 i) const 1106 { 1107 if (i==0) return aPt1; 1108 else return aPt2; 1109 } 1110 1111 sal_Bool SdrMeasureObj::IsPolyObj() const 1112 { 1113 return sal_True; 1114 } 1115 1116 sal_uInt32 SdrMeasureObj::GetPointCount() const 1117 { 1118 return 2L; 1119 } 1120 1121 Point SdrMeasureObj::GetPoint(sal_uInt32 i) const 1122 { 1123 return (0L == i) ? aPt1 : aPt2; 1124 } 1125 1126 void SdrMeasureObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i) 1127 { 1128 if (0L == i) 1129 aPt1=rPnt; 1130 if (1L == i) 1131 aPt2=rPnt; 1132 SetRectsDirty(); 1133 SetTextDirty(); 1134 } 1135 1136 SdrObjGeoData* SdrMeasureObj::NewGeoData() const 1137 { 1138 return new SdrMeasureObjGeoData; 1139 } 1140 1141 void SdrMeasureObj::SaveGeoData(SdrObjGeoData& rGeo) const 1142 { 1143 SdrTextObj::SaveGeoData(rGeo); 1144 SdrMeasureObjGeoData& rMGeo=(SdrMeasureObjGeoData&)rGeo; 1145 rMGeo.aPt1=aPt1; 1146 rMGeo.aPt2=aPt2; 1147 } 1148 1149 void SdrMeasureObj::RestGeoData(const SdrObjGeoData& rGeo) 1150 { 1151 SdrTextObj::RestGeoData(rGeo); 1152 SdrMeasureObjGeoData& rMGeo=(SdrMeasureObjGeoData&)rGeo; 1153 aPt1=rMGeo.aPt1; 1154 aPt2=rMGeo.aPt2; 1155 SetTextDirty(); 1156 } 1157 1158 SdrObject* SdrMeasureObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const 1159 { 1160 // get XOR Poly as base 1161 XPolyPolygon aTmpPolyPolygon(TakeXorPoly()); 1162 1163 // get local ItemSet and StyleSheet 1164 SfxItemSet aSet(GetObjectItemSet()); 1165 SfxStyleSheet* pStyleSheet = GetStyleSheet(); 1166 1167 // prepare group 1168 SdrObjGroup* pGroup = new SdrObjGroup; 1169 pGroup->SetModel(GetModel()); 1170 1171 // prepare parameters 1172 basegfx::B2DPolyPolygon aPolyPoly; 1173 SdrPathObj* pPath; 1174 sal_uInt16 nCount(aTmpPolyPolygon.Count()); 1175 sal_uInt16 nLoopStart(0); 1176 1177 if(nCount == 3) 1178 { 1179 // three lines, first one is the middle one 1180 aPolyPoly.clear(); 1181 aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); 1182 1183 pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); 1184 pPath->SetModel(GetModel()); 1185 pPath->SetMergedItemSet(aSet); 1186 pPath->SetStyleSheet(pStyleSheet, true); 1187 pGroup->GetSubList()->NbcInsertObject(pPath); 1188 aSet.Put(XLineStartWidthItem(0L)); 1189 aSet.Put(XLineEndWidthItem(0L)); 1190 nLoopStart = 1; 1191 } 1192 else if(nCount == 4) 1193 { 1194 // four lines, middle line with gap, so there are two lines used 1195 // which have one arrow each 1196 //sal_Int32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue(); 1197 sal_Int32 nEndWidth = ((const XLineEndWidthItem&)(aSet.Get(XATTR_LINEENDWIDTH))).GetValue(); 1198 aSet.Put(XLineEndWidthItem(0L)); 1199 1200 aPolyPoly.clear(); 1201 aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); 1202 pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); 1203 pPath->SetModel(GetModel()); 1204 pPath->SetMergedItemSet(aSet); 1205 pPath->SetStyleSheet(pStyleSheet, true); 1206 1207 pGroup->GetSubList()->NbcInsertObject(pPath); 1208 1209 aSet.Put(XLineEndWidthItem(nEndWidth)); 1210 aSet.Put(XLineStartWidthItem(0L)); 1211 1212 aPolyPoly.clear(); 1213 aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon()); 1214 pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); 1215 pPath->SetModel(GetModel()); 1216 pPath->SetMergedItemSet(aSet); 1217 pPath->SetStyleSheet(pStyleSheet, true); 1218 1219 pGroup->GetSubList()->NbcInsertObject(pPath); 1220 1221 aSet.Put(XLineEndWidthItem(0L)); 1222 nLoopStart = 2; 1223 } 1224 else if(nCount == 5) 1225 { 1226 // five lines, first two are the outer ones 1227 //sal_Int32 nStartWidth = ((const XLineStartWidthItem&)(aSet.Get(XATTR_LINESTARTWIDTH))).GetValue(); 1228 sal_Int32 nEndWidth = ((const XLineEndWidthItem&)(aSet.Get(XATTR_LINEENDWIDTH))).GetValue(); 1229 1230 aSet.Put(XLineEndWidthItem(0L)); 1231 1232 aPolyPoly.clear(); 1233 aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon()); 1234 pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); 1235 pPath->SetModel(GetModel()); 1236 pPath->SetMergedItemSet(aSet); 1237 pPath->SetStyleSheet(pStyleSheet, true); 1238 1239 pGroup->GetSubList()->NbcInsertObject(pPath); 1240 1241 aSet.Put(XLineEndWidthItem(nEndWidth)); 1242 aSet.Put(XLineStartWidthItem(0L)); 1243 1244 aPolyPoly.clear(); 1245 aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon()); 1246 pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); 1247 pPath->SetModel(GetModel()); 1248 pPath->SetMergedItemSet(aSet); 1249 pPath->SetStyleSheet(pStyleSheet, true); 1250 1251 pGroup->GetSubList()->NbcInsertObject(pPath); 1252 1253 aSet.Put(XLineEndWidthItem(0L)); 1254 nLoopStart = 2; 1255 } 1256 1257 for(;nLoopStart<nCount;nLoopStart++) 1258 { 1259 aPolyPoly.clear(); 1260 aPolyPoly.append(aTmpPolyPolygon[nLoopStart].getB2DPolygon()); 1261 pPath = new SdrPathObj(OBJ_PATHLINE, aPolyPoly); 1262 pPath->SetModel(GetModel()); 1263 pPath->SetMergedItemSet(aSet); 1264 pPath->SetStyleSheet(pStyleSheet, true); 1265 1266 pGroup->GetSubList()->NbcInsertObject(pPath); 1267 } 1268 1269 if(bAddText) 1270 { 1271 return ImpConvertAddText(pGroup, bBezier); 1272 } 1273 else 1274 { 1275 return pGroup; 1276 } 1277 } 1278 1279 sal_Bool SdrMeasureObj::BegTextEdit(SdrOutliner& rOutl) 1280 { 1281 UndirtyText(); 1282 return SdrTextObj::BegTextEdit(rOutl); 1283 } 1284 1285 const Size& SdrMeasureObj::GetTextSize() const 1286 { 1287 if (bTextDirty) UndirtyText(); 1288 return SdrTextObj::GetTextSize(); 1289 } 1290 1291 OutlinerParaObject* SdrMeasureObj::GetOutlinerParaObject() const 1292 { 1293 if(bTextDirty) 1294 UndirtyText(); 1295 return SdrTextObj::GetOutlinerParaObject(); 1296 } 1297 1298 void SdrMeasureObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject) 1299 { 1300 SdrTextObj::NbcSetOutlinerParaObject(pTextObject); 1301 if(SdrTextObj::GetOutlinerParaObject()) 1302 SetTextDirty(); // Text neu berechnen! 1303 } 1304 1305 void SdrMeasureObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, 1306 Rectangle* pAnchorRect, sal_Bool bLineWidth ) const 1307 { 1308 if (bTextDirty) UndirtyText(); 1309 SdrTextObj::TakeTextRect( rOutliner, rTextRect, bNoEditText, pAnchorRect, bLineWidth ); 1310 } 1311 1312 void SdrMeasureObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const 1313 { 1314 if (bTextDirty) UndirtyText(); 1315 SdrTextObj::TakeTextAnchorRect(rAnchorRect); 1316 } 1317 1318 void SdrMeasureObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const 1319 { 1320 if (bTextDirty) UndirtyText(); 1321 SdrTextObj::TakeTextEditArea(pPaperMin,pPaperMax,pViewInit,pViewMin); 1322 } 1323 1324 sal_uInt16 SdrMeasureObj::GetOutlinerViewAnchorMode() const 1325 { 1326 if (bTextDirty) UndirtyText(); 1327 ImpMeasureRec aRec; 1328 ImpMeasurePoly aMPol; 1329 ImpTakeAttr(aRec); 1330 ImpCalcGeometrics(aRec,aMPol); 1331 1332 SdrTextHorzAdjust eTH=GetTextHorizontalAdjust(); 1333 SdrTextVertAdjust eTV=GetTextVerticalAdjust(); 1334 SdrMeasureTextHPos eMH=aMPol.eUsedTextHPos; 1335 SdrMeasureTextVPos eMV=aMPol.eUsedTextVPos; 1336 FASTBOOL bTextRota90=aRec.bTextRota90; 1337 //int bTextUpsideDown=aRec.bTextUpsideDown; 1338 FASTBOOL bBelowRefEdge=aRec.bBelowRefEdge; 1339 1340 // bTextUpsideDown muss hier noch ausgewertet werden!!!! 1341 if (!bTextRota90) { 1342 if (eMH==SDRMEASURE_TEXTLEFTOUTSIDE) eTH=SDRTEXTHORZADJUST_RIGHT; 1343 if (eMH==SDRMEASURE_TEXTRIGHTOUTSIDE) eTH=SDRTEXTHORZADJUST_LEFT; 1344 // bei eMH==SDRMEASURE_TEXTINSIDE kann horizontal geankert werden. 1345 if (eMV==SDRMEASURE_ABOVE) eTV=SDRTEXTVERTADJUST_BOTTOM; 1346 if (eMV==SDRMEASURE_BELOW) eTV=SDRTEXTVERTADJUST_TOP; 1347 if (eMV==SDRMEASURETEXT_BREAKEDLINE || eMV==SDRMEASURETEXT_VERTICALCENTERED) eTV=SDRTEXTVERTADJUST_CENTER; 1348 } else { 1349 if (eMH==SDRMEASURE_TEXTLEFTOUTSIDE) eTV=SDRTEXTVERTADJUST_BOTTOM; 1350 if (eMH==SDRMEASURE_TEXTRIGHTOUTSIDE) eTV=SDRTEXTVERTADJUST_TOP; 1351 // bei eMH==SDRMEASURE_TEXTINSIDE kann vertikal geankert werden. 1352 if (!bBelowRefEdge) { 1353 if (eMV==SDRMEASURE_ABOVE) eTH=SDRTEXTHORZADJUST_LEFT; 1354 if (eMV==SDRMEASURE_BELOW) eTH=SDRTEXTHORZADJUST_RIGHT; 1355 } else { 1356 if (eMV==SDRMEASURE_ABOVE) eTH=SDRTEXTHORZADJUST_RIGHT; 1357 if (eMV==SDRMEASURE_BELOW) eTH=SDRTEXTHORZADJUST_LEFT; 1358 } 1359 if (eMV==SDRMEASURETEXT_BREAKEDLINE || eMV==SDRMEASURETEXT_VERTICALCENTERED) eTH=SDRTEXTHORZADJUST_CENTER; 1360 } 1361 1362 EVAnchorMode eRet=ANCHOR_BOTTOM_HCENTER; 1363 if (eTH==SDRTEXTHORZADJUST_LEFT) { 1364 if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_LEFT; 1365 else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_LEFT; 1366 else eRet=ANCHOR_VCENTER_LEFT; 1367 } else if (eTH==SDRTEXTHORZADJUST_RIGHT) { 1368 if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_RIGHT; 1369 else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_RIGHT; 1370 else eRet=ANCHOR_VCENTER_RIGHT; 1371 } else { 1372 if (eTV==SDRTEXTVERTADJUST_TOP) eRet=ANCHOR_TOP_HCENTER; 1373 else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=ANCHOR_BOTTOM_HCENTER; 1374 else eRet=ANCHOR_VCENTER_HCENTER; 1375 } 1376 return (sal_uInt16)eRet; 1377 } 1378 1379 ////////////////////////////////////////////////////////////////////////////// 1380 // #i97878# 1381 // TRGetBaseGeometry/TRSetBaseGeometry needs to be based on two positions, 1382 // same as line geometry in SdrPathObj. Thus needs to be overloaded and 1383 // implemented since currently it is derived from SdrTextObj which uses 1384 // a functionality based on SnapRect which is not useful here 1385 1386 inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } 1387 inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } 1388 1389 sal_Bool SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const 1390 { 1391 // handle the same as a simple line since the definition is based on two points 1392 const basegfx::B2DRange aRange(aPt1.X(), aPt1.Y(), aPt2.X(), aPt2.Y()); 1393 basegfx::B2DTuple aScale(aRange.getRange()); 1394 basegfx::B2DTuple aTranslate(aRange.getMinimum()); 1395 1396 // position maybe relative to anchorpos, convert 1397 if( pModel->IsWriter() ) 1398 { 1399 if(GetAnchorPos().X() || GetAnchorPos().Y()) 1400 { 1401 aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); 1402 } 1403 } 1404 1405 // force MapUnit to 100th mm 1406 SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); 1407 if(eMapUnit != SFX_MAPUNIT_100TH_MM) 1408 { 1409 switch(eMapUnit) 1410 { 1411 case SFX_MAPUNIT_TWIP : 1412 { 1413 // postion 1414 aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); 1415 aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); 1416 1417 // size 1418 aScale.setX(ImplTwipsToMM(aScale.getX())); 1419 aScale.setY(ImplTwipsToMM(aScale.getY())); 1420 1421 break; 1422 } 1423 default: 1424 { 1425 DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); 1426 } 1427 } 1428 } 1429 1430 // build return value matrix 1431 rMatrix = basegfx::tools::createScaleTranslateB2DHomMatrix(aScale, aTranslate); 1432 1433 return sal_True; 1434 } 1435 1436 void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) 1437 { 1438 // use given transformation to derive the two defining points from unit line 1439 basegfx::B2DPoint aPosA(rMatrix * basegfx::B2DPoint(0.0, 0.0)); 1440 basegfx::B2DPoint aPosB(rMatrix * basegfx::B2DPoint(1.0, 0.0)); 1441 1442 // force metric to pool metric 1443 SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); 1444 if(eMapUnit != SFX_MAPUNIT_100TH_MM) 1445 { 1446 switch(eMapUnit) 1447 { 1448 case SFX_MAPUNIT_TWIP : 1449 { 1450 // position 1451 aPosA.setX(ImplMMToTwips(aPosA.getX())); 1452 aPosA.setY(ImplMMToTwips(aPosA.getY())); 1453 aPosB.setX(ImplMMToTwips(aPosB.getX())); 1454 aPosB.setY(ImplMMToTwips(aPosB.getY())); 1455 1456 break; 1457 } 1458 default: 1459 { 1460 DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); 1461 } 1462 } 1463 } 1464 1465 if( pModel->IsWriter() ) 1466 { 1467 // if anchor is used, make position relative to it 1468 if(GetAnchorPos().X() || GetAnchorPos().Y()) 1469 { 1470 const basegfx::B2DVector aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y()); 1471 1472 aPosA += aAnchorOffset; 1473 aPosB += aAnchorOffset; 1474 } 1475 } 1476 1477 // derive new model data 1478 const Point aNewPt1(basegfx::fround(aPosA.getX()), basegfx::fround(aPosA.getY())); 1479 const Point aNewPt2(basegfx::fround(aPosB.getX()), basegfx::fround(aPosB.getY())); 1480 1481 if(aNewPt1 != aPt1 || aNewPt2 != aPt2) 1482 { 1483 // set model values and broadcast 1484 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); 1485 1486 aPt1 = aNewPt1; 1487 aPt2 = aNewPt2; 1488 1489 SetTextDirty(); 1490 ActionChanged(); 1491 SetChanged(); 1492 BroadcastObjectChange(); 1493 SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); 1494 } 1495 } 1496 1497 ////////////////////////////////////////////////////////////////////////////// 1498 // eof 1499