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