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 #include <tools/bigint.hxx> 27 #include <svx/xlnwtit.hxx> 28 #include <svl/style.hxx> 29 #include <svx/svdocapt.hxx> 30 #include <svx/xpool.hxx> 31 #include <svx/xpoly.hxx> 32 #include <svx/svdattrx.hxx> 33 #include <svx/svdpool.hxx> 34 #include <svx/svdetc.hxx> 35 #include <svx/svdtrans.hxx> 36 #include <svx/svdhdl.hxx> 37 #include <svx/svddrag.hxx> 38 #include <svx/svdmodel.hxx> 39 #include <svx/svdview.hxx> // fuer RectSnap 40 #include "svx/svdglob.hxx" // StringCache 41 #include "svx/svdstr.hrc" // Objektname 42 #include <svx/svdogrp.hxx> 43 #include <svx/svdpage.hxx> 44 #include <svx/xflhtit.hxx> 45 #include <svx/xflclit.hxx> 46 #include <svx/xfltrit.hxx> 47 #include <editeng/eeitem.hxx> 48 #include <svx/sdr/properties/captionproperties.hxx> 49 #include <vcl/salbtype.hxx> // FRound 50 #include <svx/sdr/contact/viewcontactofsdrcaptionobj.hxx> 51 #include <basegfx/tuple/b2dtuple.hxx> 52 #include <basegfx/matrix/b2dhommatrix.hxx> 53 #include <basegfx/polygon/b2dpolygon.hxx> 54 #include <basegfx/range/b2drange.hxx> 55 #include <basegfx/polygon/b2dpolygontools.hxx> 56 #include <svx/sdrhittesthelper.hxx> 57 58 // #i32599# 59 inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } 60 inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } 61 62 //////////////////////////////////////////////////////////////////////////////////////////////////// 63 64 enum EscDir {LKS,RTS,OBN,UNT}; 65 66 class ImpCaptParams 67 { 68 public: 69 SdrCaptionType eType; 70 long nAngle; 71 long nGap; 72 long nEscRel; 73 long nEscAbs; 74 long nLineLen; 75 SdrCaptionEscDir eEscDir; 76 FASTBOOL bFitLineLen; 77 FASTBOOL bEscRel; 78 FASTBOOL bFixedAngle; 79 80 public: 81 ImpCaptParams() 82 { 83 eType =SDRCAPT_TYPE3; 84 bFixedAngle=sal_False; 85 nAngle =4500; 86 nGap =0; 87 eEscDir =SDRCAPT_ESCHORIZONTAL; 88 bEscRel =sal_True; 89 nEscRel =5000; 90 nEscAbs =0; 91 nLineLen =0; 92 bFitLineLen=sal_True; 93 } 94 void CalcEscPos(const Point& rTail, const Rectangle& rRect, Point& rPt, EscDir& rDir) const; 95 }; 96 97 void ImpCaptParams::CalcEscPos(const Point& rTailPt, const Rectangle& rRect, Point& rPt, EscDir& rDir) const 98 { 99 Point aTl(rTailPt); // lokal kopieren wg. Performance 100 long nX,nY; 101 if (bEscRel) { 102 nX=rRect.Right()-rRect.Left(); 103 nX=BigMulDiv(nX,nEscRel,10000); 104 nY=rRect.Bottom()-rRect.Top(); 105 nY=BigMulDiv(nY,nEscRel,10000); 106 } else { 107 nX=nEscAbs; 108 nY=nEscAbs; 109 } 110 nX+=rRect.Left(); 111 nY+=rRect.Top(); 112 Point aBestPt; 113 EscDir eBestDir=LKS; 114 FASTBOOL bTryH=eEscDir==SDRCAPT_ESCBESTFIT; 115 if (!bTryH) { 116 if (eType!=SDRCAPT_TYPE1) { 117 bTryH=eEscDir==SDRCAPT_ESCHORIZONTAL; 118 } else { 119 bTryH=eEscDir==SDRCAPT_ESCVERTICAL; 120 } 121 } 122 FASTBOOL bTryV=eEscDir==SDRCAPT_ESCBESTFIT; 123 if (!bTryV) { 124 if (eType!=SDRCAPT_TYPE1) { 125 bTryV=eEscDir==SDRCAPT_ESCVERTICAL; 126 } else { 127 bTryV=eEscDir==SDRCAPT_ESCHORIZONTAL; 128 } 129 } 130 131 if (bTryH) { 132 Point aLft(rRect.Left()-nGap,nY); 133 Point aRgt(rRect.Right()+nGap,nY); 134 FASTBOOL bLft=(aTl.X()-aLft.X()<aRgt.X()-aTl.X()); 135 if (bLft) { 136 eBestDir=LKS; 137 aBestPt=aLft; 138 } else { 139 eBestDir=RTS; 140 aBestPt=aRgt; 141 } 142 } 143 if (bTryV) { 144 Point aTop(nX,rRect.Top()-nGap); 145 Point aBtm(nX,rRect.Bottom()+nGap); 146 FASTBOOL bTop=(aTl.Y()-aTop.Y()<aBtm.Y()-aTl.Y()); 147 Point aBest2; 148 EscDir eBest2; 149 if (bTop) { 150 eBest2=OBN; 151 aBest2=aTop; 152 } else { 153 eBest2=UNT; 154 aBest2=aBtm; 155 } 156 FASTBOOL bTakeIt=eEscDir!=SDRCAPT_ESCBESTFIT; 157 if (!bTakeIt) { 158 BigInt aHorX(aBestPt.X()-aTl.X()); aHorX*=aHorX; 159 BigInt aHorY(aBestPt.Y()-aTl.Y()); aHorY*=aHorY; 160 BigInt aVerX(aBest2.X()-aTl.X()); aVerX*=aVerX; 161 BigInt aVerY(aBest2.Y()-aTl.Y()); aVerY*=aVerY; 162 if (eType!=SDRCAPT_TYPE1) { 163 bTakeIt=aVerX+aVerY<aHorX+aHorY; 164 } else { 165 bTakeIt=aVerX+aVerY>=aHorX+aHorY; 166 } 167 } 168 if (bTakeIt) { 169 aBestPt=aBest2; 170 eBestDir=eBest2; 171 } 172 } 173 rPt=aBestPt; 174 rDir=eBestDir; 175 } 176 177 ////////////////////////////////////////////////////////////////////////////// 178 // BaseProperties section 179 180 sdr::properties::BaseProperties* SdrCaptionObj::CreateObjectSpecificProperties() 181 { 182 return new sdr::properties::CaptionProperties(*this); 183 } 184 185 ////////////////////////////////////////////////////////////////////////////// 186 // DrawContact section 187 188 sdr::contact::ViewContact* SdrCaptionObj::CreateObjectSpecificViewContact() 189 { 190 return new sdr::contact::ViewContactOfSdrCaptionObj(*this); 191 } 192 193 ////////////////////////////////////////////////////////////////////////////// 194 195 TYPEINIT1(SdrCaptionObj,SdrRectObj); 196 197 SdrCaptionObj::SdrCaptionObj(): 198 SdrRectObj(OBJ_TEXT), 199 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien 200 mbSpecialTextBoxShadow(sal_False), 201 mbFixedTail(sal_False) 202 { 203 } 204 205 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect): 206 SdrRectObj(OBJ_TEXT,rRect), 207 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien 208 mbSpecialTextBoxShadow(sal_False), 209 mbFixedTail(sal_False) 210 { 211 } 212 213 SdrCaptionObj::SdrCaptionObj(const Rectangle& rRect, const Point& rTail): 214 SdrRectObj(OBJ_TEXT,rRect), 215 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien 216 mbSpecialTextBoxShadow(sal_False), 217 mbFixedTail(sal_False) 218 { 219 aTailPoly[0]=maFixedTailPos=rTail; 220 } 221 222 SdrCaptionObj::~SdrCaptionObj() 223 { 224 } 225 226 void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const 227 { 228 rInfo.bRotateFreeAllowed=sal_False; 229 rInfo.bRotate90Allowed =sal_False; 230 rInfo.bMirrorFreeAllowed=sal_False; 231 rInfo.bMirror45Allowed =sal_False; 232 rInfo.bMirror90Allowed =sal_False; 233 rInfo.bTransparenceAllowed = sal_False; 234 rInfo.bGradientAllowed = sal_False; 235 rInfo.bShearAllowed =sal_False; 236 rInfo.bEdgeRadiusAllowed=sal_False; 237 rInfo.bCanConvToPath =sal_True; 238 rInfo.bCanConvToPoly =sal_True; 239 rInfo.bCanConvToPathLineToArea=sal_False; 240 rInfo.bCanConvToPolyLineToArea=sal_False; 241 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); 242 } 243 244 sal_uInt16 SdrCaptionObj::GetObjIdentifier() const 245 { 246 return sal_uInt16(OBJ_CAPTION); 247 } 248 249 void SdrCaptionObj::operator=(const SdrObject& rObj) 250 { 251 SdrRectObj::operator=(rObj); 252 aTailPoly=((SdrCaptionObj&)rObj).aTailPoly; 253 } 254 255 void SdrCaptionObj::TakeObjNameSingul(XubString& rName) const 256 { 257 rName=ImpGetResStr(STR_ObjNameSingulCAPTION); 258 259 String aName( GetName() ); 260 if(aName.Len()) 261 { 262 rName += sal_Unicode(' '); 263 rName += sal_Unicode('\''); 264 rName += aName; 265 rName += sal_Unicode('\''); 266 } 267 } 268 269 void SdrCaptionObj::TakeObjNamePlural(XubString& rName) const 270 { 271 rName=ImpGetResStr(STR_ObjNamePluralCAPTION); 272 } 273 274 basegfx::B2DPolyPolygon SdrCaptionObj::TakeXorPoly() const 275 { 276 basegfx::B2DPolyPolygon aPolyPoly(SdrRectObj::TakeXorPoly()); 277 aPolyPoly.append(aTailPoly.getB2DPolygon()); 278 279 return aPolyPoly; 280 } 281 282 sal_uInt32 SdrCaptionObj::GetHdlCount() const 283 { 284 sal_uInt32 nAnz1(SdrRectObj::GetHdlCount()); 285 // sal_uInt32 nAnz2(aTailPoly.GetSize()); 286 // Derzeit ist nur das Draggen des Schwanzendes implementiert 287 return nAnz1 + 1L; 288 } 289 290 SdrHdl* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum) const 291 { 292 const sal_uInt32 nRectHdlAnz(SdrRectObj::GetHdlCount()); 293 294 if(nHdlNum < nRectHdlAnz) 295 { 296 return SdrRectObj::GetHdl(nHdlNum); 297 } 298 else 299 { 300 sal_uInt32 nPntNum(nHdlNum); 301 nPntNum -= nRectHdlAnz; 302 303 if(nPntNum < aTailPoly.GetSize()) 304 { 305 SdrHdl* pHdl = new SdrHdl(aTailPoly.GetPoint((sal_uInt16)nPntNum), HDL_POLY); 306 pHdl->SetPolyNum(1L); 307 pHdl->SetPointNum(nPntNum); 308 return pHdl; 309 } 310 else 311 { 312 return 0L; 313 } 314 } 315 } 316 317 //////////////////////////////////////////////////////////////////////////////////////////////////// 318 319 bool SdrCaptionObj::hasSpecialDrag() const 320 { 321 return true; 322 } 323 324 bool SdrCaptionObj::beginSpecialDrag(SdrDragStat& rDrag) const 325 { 326 const SdrHdl* pHdl = rDrag.GetHdl(); 327 rDrag.SetEndDragChangesAttributes(true); 328 rDrag.SetEndDragChangesGeoAndAttributes(true); 329 330 if(pHdl && 0 == pHdl->GetPolyNum()) 331 { 332 return SdrRectObj::beginSpecialDrag(rDrag); 333 } 334 else 335 { 336 rDrag.SetOrtho8Possible(true); 337 338 if(!pHdl) 339 { 340 if (bMovProt) 341 return 0; 342 343 rDrag.SetNoSnap(true); 344 rDrag.SetActionRect(aRect); 345 346 Point aHit(rDrag.GetStart()); 347 348 if(rDrag.GetPageView() && SdrObjectPrimitiveHit(*this, aHit, 0, *rDrag.GetPageView(), 0, false)) 349 { 350 return true; 351 } 352 } 353 else 354 { 355 if((1 == pHdl->GetPolyNum()) && (0 == pHdl->GetPointNum())) 356 return true; 357 } 358 } 359 360 return false; 361 } 362 363 bool SdrCaptionObj::applySpecialDrag(SdrDragStat& rDrag) 364 { 365 const SdrHdl* pHdl = rDrag.GetHdl(); 366 367 if(pHdl && 0 == pHdl->GetPolyNum()) 368 { 369 const bool bRet(SdrRectObj::applySpecialDrag(rDrag)); 370 ImpRecalcTail(); 371 ActionChanged(); 372 373 return bRet; 374 } 375 else 376 { 377 Point aDelt(rDrag.GetNow()-rDrag.GetStart()); 378 379 if(!pHdl) 380 { 381 aRect.Move(aDelt.X(),aDelt.Y()); 382 } 383 else 384 { 385 aTailPoly[0] += aDelt; 386 } 387 388 ImpRecalcTail(); 389 ActionChanged(); 390 391 return true; 392 } 393 } 394 395 String SdrCaptionObj::getSpecialDragComment(const SdrDragStat& rDrag) const 396 { 397 const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj()); 398 399 if(bCreateComment) 400 { 401 return String(); 402 } 403 else 404 { 405 const SdrHdl* pHdl = rDrag.GetHdl(); 406 407 if(pHdl && 0 == pHdl->GetPolyNum()) 408 { 409 return SdrRectObj::getSpecialDragComment(rDrag); 410 } 411 else 412 { 413 XubString aStr; 414 415 if(!pHdl) 416 { 417 ImpTakeDescriptionStr(STR_DragCaptFram, aStr); 418 } 419 else 420 { 421 ImpTakeDescriptionStr(STR_DragCaptTail, aStr); 422 } 423 424 return aStr; 425 } 426 } 427 } 428 429 //////////////////////////////////////////////////////////////////////////////////////////////////// 430 431 void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams& rPara) const 432 { 433 const SfxItemSet& rSet = GetObjectItemSet(); 434 rPara.eType =((SdrCaptionTypeItem&) (rSet.Get(SDRATTR_CAPTIONTYPE ))).GetValue(); 435 rPara.bFixedAngle=((SdrCaptionFixedAngleItem&)(rSet.Get(SDRATTR_CAPTIONANGLE ))).GetValue(); 436 rPara.nAngle =((SdrCaptionAngleItem&) (rSet.Get(SDRATTR_CAPTIONFIXEDANGLE))).GetValue(); 437 rPara.nGap =((SdrCaptionGapItem&) (rSet.Get(SDRATTR_CAPTIONGAP ))).GetValue(); 438 rPara.eEscDir =((SdrCaptionEscDirItem&) (rSet.Get(SDRATTR_CAPTIONESCDIR ))).GetValue(); 439 rPara.bEscRel =((SdrCaptionEscIsRelItem&) (rSet.Get(SDRATTR_CAPTIONESCISREL ))).GetValue(); 440 rPara.nEscRel =((SdrCaptionEscRelItem&) (rSet.Get(SDRATTR_CAPTIONESCREL ))).GetValue(); 441 rPara.nEscAbs =((SdrCaptionEscAbsItem&) (rSet.Get(SDRATTR_CAPTIONESCABS ))).GetValue(); 442 rPara.nLineLen =((SdrCaptionLineLenItem&) (rSet.Get(SDRATTR_CAPTIONLINELEN ))).GetValue(); 443 rPara.bFitLineLen=((SdrCaptionFitLineLenItem&)(rSet.Get(SDRATTR_CAPTIONFITLINELEN))).GetValue(); 444 } 445 446 void SdrCaptionObj::ImpRecalcTail() 447 { 448 ImpCaptParams aPara; 449 ImpGetCaptParams(aPara); 450 ImpCalcTail(aPara,aTailPoly,aRect); 451 SetRectsDirty(); 452 SetXPolyDirty(); 453 } 454 455 // #i35971# 456 // SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack. 457 // I really wonder why this had not triggered problems before. I am 458 // sure there are some places where SetTailPos() is called at least 459 // twice or SetSnapRect after it again just to work around this. 460 // Changed this method to not do that. 461 // Also found why this has been done: For interactive dragging of the 462 // tail end pos for SDRCAPT_TYPE1. This sure was the simplest method 463 // to achieve this, for the cost to make a whole group of const methods 464 // of this object implicitly chainging the object's position. 465 void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const 466 { 467 Polygon aPol(2); 468 Point aTl(rPoly[0]); 469 470 aPol[0] = aTl; 471 aPol[1] = aTl; 472 473 EscDir eEscDir; 474 Point aEscPos; 475 476 rPara.CalcEscPos(aTl, rRect, aEscPos, eEscDir); 477 aPol[1] = aEscPos; 478 479 if(eEscDir==LKS || eEscDir==RTS) 480 { 481 aPol[0].X() = aEscPos.X(); 482 } 483 else 484 { 485 aPol[0].Y() = aEscPos.Y(); 486 } 487 488 rPoly = aPol; 489 } 490 491 void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const 492 { // Gap/EscDir/EscPos/Angle 493 Polygon aPol(2); 494 Point aTl(rPoly[0]); 495 aPol[0]=aTl; 496 497 EscDir eEscDir; 498 Point aEscPos; 499 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir); 500 aPol[1]=aEscPos; 501 502 if (!rPara.bFixedAngle) { 503 // fehlende Implementation 504 } 505 rPoly=aPol; 506 } 507 508 void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const 509 { // Gap/EscDir/EscPos/Angle/LineLen 510 Polygon aPol(3); 511 Point aTl(rPoly[0]); 512 aPol[0]=aTl; 513 514 EscDir eEscDir; 515 Point aEscPos; 516 rPara.CalcEscPos(aTl,rRect,aEscPos,eEscDir); 517 aPol[1]=aEscPos; 518 aPol[2]=aEscPos; 519 520 if (eEscDir==LKS || eEscDir==RTS) { 521 if (rPara.bFitLineLen) { 522 aPol[1].X()=(aTl.X()+aEscPos.X())/2; 523 } else { 524 if (eEscDir==LKS) aPol[1].X()-=rPara.nLineLen; 525 else aPol[1].X()+=rPara.nLineLen; 526 } 527 } else { 528 if (rPara.bFitLineLen) { 529 aPol[1].Y()=(aTl.Y()+aEscPos.Y())/2; 530 } else { 531 if (eEscDir==OBN) aPol[1].Y()-=rPara.nLineLen; 532 else aPol[1].Y()+=rPara.nLineLen; 533 } 534 } 535 if (!rPara.bFixedAngle) { 536 // fehlende Implementation 537 } 538 rPoly=aPol; 539 } 540 541 void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const 542 { 543 ImpCalcTail3(rPara,rPoly,rRect); 544 } 545 546 void SdrCaptionObj::ImpCalcTail(const ImpCaptParams& rPara, Polygon& rPoly, Rectangle& rRect) const 547 { 548 switch (rPara.eType) { 549 case SDRCAPT_TYPE1: ImpCalcTail1(rPara,rPoly,rRect); break; 550 case SDRCAPT_TYPE2: ImpCalcTail2(rPara,rPoly,rRect); break; 551 case SDRCAPT_TYPE3: ImpCalcTail3(rPara,rPoly,rRect); break; 552 case SDRCAPT_TYPE4: ImpCalcTail4(rPara,rPoly,rRect); break; 553 } 554 } 555 556 FASTBOOL SdrCaptionObj::BegCreate(SdrDragStat& rStat) 557 { 558 if (aRect.IsEmpty()) return sal_False; // Create z.Zt. nur mit vorgegebenen Rect 559 560 ImpCaptParams aPara; 561 ImpGetCaptParams(aPara); 562 aRect.SetPos(rStat.GetNow()); 563 aTailPoly[0]=rStat.GetStart(); 564 ImpCalcTail(aPara,aTailPoly,aRect); 565 rStat.SetActionRect(aRect); 566 return sal_True; 567 } 568 569 FASTBOOL SdrCaptionObj::MovCreate(SdrDragStat& rStat) 570 { 571 ImpCaptParams aPara; 572 ImpGetCaptParams(aPara); 573 aRect.SetPos(rStat.GetNow()); 574 ImpCalcTail(aPara,aTailPoly,aRect); 575 rStat.SetActionRect(aRect); 576 SetBoundRectDirty(); 577 bSnapRectDirty=sal_True; 578 return sal_True; 579 } 580 581 FASTBOOL SdrCaptionObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) 582 { 583 ImpCaptParams aPara; 584 ImpGetCaptParams(aPara); 585 aRect.SetPos(rStat.GetNow()); 586 ImpCalcTail(aPara,aTailPoly,aRect); 587 SetRectsDirty(); 588 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); 589 } 590 591 FASTBOOL SdrCaptionObj::BckCreate(SdrDragStat& /*rStat*/) 592 { 593 return sal_False; 594 } 595 596 void SdrCaptionObj::BrkCreate(SdrDragStat& /*rStat*/) 597 { 598 } 599 600 basegfx::B2DPolyPolygon SdrCaptionObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const 601 { 602 basegfx::B2DPolyPolygon aRetval; 603 const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); 604 aRetval.append(basegfx::tools::createPolygonFromRect(aRange)); 605 aRetval.append(aTailPoly.getB2DPolygon()); 606 return aRetval; 607 } 608 609 Pointer SdrCaptionObj::GetCreatePointer() const 610 { 611 return Pointer(POINTER_DRAW_CAPTION); 612 } 613 614 void SdrCaptionObj::NbcMove(const Size& rSiz) 615 { 616 SdrRectObj::NbcMove(rSiz); 617 MovePoly(aTailPoly,rSiz); 618 if(mbFixedTail) 619 SetTailPos(GetFixedTailPos()); 620 } 621 622 void SdrCaptionObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) 623 { 624 SdrRectObj::NbcResize(rRef,xFact,yFact); 625 ResizePoly(aTailPoly,rRef,xFact,yFact); 626 ImpRecalcTail(); 627 if(mbFixedTail) 628 SetTailPos(GetFixedTailPos()); 629 } 630 631 void SdrCaptionObj::NbcSetRelativePos(const Point& rPnt) 632 { 633 Point aRelPos0(aTailPoly.GetPoint(0)-aAnchor); 634 Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y()); 635 NbcMove(aSiz); // Der ruft auch das SetRectsDirty() 636 } 637 638 Point SdrCaptionObj::GetRelativePos() const 639 { 640 return aTailPoly.GetPoint(0)-aAnchor; 641 } 642 643 void SdrCaptionObj::NbcSetAnchorPos(const Point& rPnt) 644 { 645 SdrRectObj::NbcSetAnchorPos(rPnt); 646 // !!!!! fehlende Impl. 647 } 648 649 const Point& SdrCaptionObj::GetAnchorPos() const 650 { 651 // !!!!! fehlende Impl. 652 return SdrRectObj::GetAnchorPos(); 653 } 654 655 void SdrCaptionObj::RecalcSnapRect() 656 { 657 SdrRectObj::RecalcSnapRect(); 658 // #i32599# 659 // maSnapRect.Union(aTailPoly.GetBoundRect()); 660 // !!!!! fehlende Impl. 661 } 662 663 const Rectangle& SdrCaptionObj::GetSnapRect() const 664 { 665 return SdrRectObj::GetSnapRect(); 666 } 667 668 void SdrCaptionObj::NbcSetSnapRect(const Rectangle& rRect) 669 { 670 // #i32599# 671 // Move back to see the rectangle of the underlying SdrRectObj 672 // as the SnapRect, without the TailPos. That simplifies SnapRect 673 // handling again, if not allows it at all... 674 SdrRectObj::NbcSetSnapRect(rRect); 675 } 676 677 const Rectangle& SdrCaptionObj::GetLogicRect() const 678 { 679 return aRect; 680 } 681 682 void SdrCaptionObj::NbcSetLogicRect(const Rectangle& rRect) 683 { 684 SdrRectObj::NbcSetLogicRect(rRect); 685 ImpRecalcTail(); 686 } 687 688 const Point& SdrCaptionObj::GetTailPos() const 689 { 690 return aTailPoly[0]; 691 } 692 693 void SdrCaptionObj::SetTailPos(const Point& rPos) 694 { 695 if (aTailPoly.GetSize()==0 || aTailPoly[0]!=rPos) { 696 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); 697 // #110094#-14 SendRepaintBroadcast(); 698 NbcSetTailPos(rPos); 699 SetChanged(); 700 BroadcastObjectChange(); 701 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); 702 } 703 } 704 705 void SdrCaptionObj::NbcSetTailPos(const Point& rPos) 706 { 707 aTailPoly[0]=rPos; 708 ImpRecalcTail(); 709 } 710 711 sal_uInt32 SdrCaptionObj::GetSnapPointCount() const 712 { 713 // !!!!! fehlende Impl. 714 return 0L; 715 } 716 717 Point SdrCaptionObj::GetSnapPoint(sal_uInt32 /*i*/) const 718 { 719 // !!!!! fehlende Impl. 720 return Point(0,0); 721 } 722 723 void SdrCaptionObj::SetModel(SdrModel* pNewModel) 724 { 725 SdrRectObj::SetModel(pNewModel); 726 ImpRecalcTail(); 727 } 728 729 void SdrCaptionObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) 730 { 731 SdrRectObj::Notify(rBC,rHint); 732 ImpRecalcTail(); 733 } 734 735 SdrObjGeoData* SdrCaptionObj::NewGeoData() const 736 { 737 return new SdrCaptObjGeoData; 738 } 739 740 void SdrCaptionObj::SaveGeoData(SdrObjGeoData& rGeo) const 741 { 742 SdrRectObj::SaveGeoData(rGeo); 743 SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo; 744 rCGeo.aTailPoly=aTailPoly; 745 } 746 747 void SdrCaptionObj::RestGeoData(const SdrObjGeoData& rGeo) 748 { 749 SdrRectObj::RestGeoData(rGeo); 750 SdrCaptObjGeoData& rCGeo=(SdrCaptObjGeoData&)rGeo; 751 aTailPoly=rCGeo.aTailPoly; 752 } 753 754 SdrObject* SdrCaptionObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const 755 { // #42334# - Convert implementiert 756 SdrObject* pRect=SdrRectObj::DoConvertToPolyObj(bBezier, bAddText); 757 SdrObject* pTail = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly.getB2DPolygon()), sal_False, bBezier); 758 SdrObject* pRet=(pTail!=NULL) ? pTail : pRect; 759 if (pTail!=NULL && pRect!=NULL) { 760 FASTBOOL bInsRect=sal_True; 761 FASTBOOL bInsTail=sal_True; 762 SdrObjList* pOL=pTail->GetSubList(); 763 if (pOL!=NULL) { pRet=pRect; bInsTail=sal_False; } 764 if (pOL==NULL) pOL=pRect->GetSubList(); 765 if (pOL!=NULL) { pRet=pRect; bInsRect=sal_False; } 766 if (pOL==NULL) { 767 SdrObjGroup* pGrp=new SdrObjGroup; 768 pOL=pGrp->GetSubList(); 769 pRet=pGrp; 770 } 771 if (bInsRect) pOL->NbcInsertObject(pRect); 772 if (bInsTail) pOL->NbcInsertObject(pTail,0); 773 } 774 return pRet; 775 } 776 777 // #i32599# 778 // Add own implementation for TRSetBaseGeometry to handle TailPos over changes. 779 void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) 780 { 781 // break up matrix 782 basegfx::B2DTuple aScale; 783 basegfx::B2DTuple aTranslate; 784 double fRotate, fShearX; 785 rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); 786 787 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings 788 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly 789 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) 790 { 791 aScale.setX(fabs(aScale.getX())); 792 aScale.setY(fabs(aScale.getY())); 793 fRotate = fmod(fRotate + F_PI, F_2PI); 794 } 795 796 // force metric to pool metric 797 SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); 798 if(eMapUnit != SFX_MAPUNIT_100TH_MM) 799 { 800 switch(eMapUnit) 801 { 802 case SFX_MAPUNIT_TWIP : 803 { 804 // position 805 aTranslate.setX(ImplMMToTwips(aTranslate.getX())); 806 aTranslate.setY(ImplMMToTwips(aTranslate.getY())); 807 808 // size 809 aScale.setX(ImplMMToTwips(aScale.getX())); 810 aScale.setY(ImplMMToTwips(aScale.getY())); 811 812 break; 813 } 814 default: 815 { 816 DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); 817 } 818 } 819 } 820 821 // if anchor is used, make position relative to it 822 if( pModel->IsWriter() ) 823 { 824 if(GetAnchorPos().X() || GetAnchorPos().Y()) 825 { 826 aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); 827 } 828 } 829 830 // build BaseRect 831 Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY())); 832 Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY()))); 833 834 // set BaseRect, but rescue TailPos over this call 835 const Point aTailPoint = GetTailPos(); 836 SetSnapRect(aBaseRect); 837 SetTailPos(aTailPoint); 838 ImpRecalcTail(); 839 } 840 841 // geometry access 842 basegfx::B2DPolygon SdrCaptionObj::getTailPolygon() const 843 { 844 return aTailPoly.getB2DPolygon(); 845 } 846 847 // eof 848