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_sw.hxx" 30 #include <anchoreddrawobject.hxx> 31 #include <svx/svdobj.hxx> 32 #include <dcontact.hxx> 33 #include <rootfrm.hxx> 34 #include <pagefrm.hxx> 35 #include <cntfrm.hxx> 36 #include <doc.hxx> 37 #include <tocntntanchoredobjectposition.hxx> 38 #include <tolayoutanchoredobjectposition.hxx> 39 #include <frmtool.hxx> 40 #include <fmtornt.hxx> 41 // --> OD 2004-08-12 #i32795# 42 #include <txtfrm.hxx> 43 // <-- 44 // --> OD 2004-08-12 #i32795# 45 // template class <std::vector> 46 #include <vector> 47 // <-- 48 49 // --> OD 2004-08-10 #i28749# 50 #include <com/sun/star/text/PositionLayoutDir.hpp> 51 // <-- 52 // --> OD 2005-03-09 #i44559# 53 #include <ndtxt.hxx> 54 // <-- 55 56 using namespace ::com::sun::star; 57 58 // ============================================================================ 59 // helper class for correct notification due to the positioning of 60 // the anchored drawing object 61 // ============================================================================ 62 class SwPosNotify 63 { 64 private: 65 SwAnchoredDrawObject* mpAnchoredDrawObj; 66 SwRect maOldObjRect; 67 SwPageFrm* mpOldPageFrm; 68 69 public: 70 SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj ); 71 ~SwPosNotify(); 72 // --> OD 2004-08-12 #i32795# 73 Point LastObjPos() const; 74 // <-- 75 }; 76 77 SwPosNotify::SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj ) : 78 mpAnchoredDrawObj( _pAnchoredDrawObj ) 79 { 80 maOldObjRect = mpAnchoredDrawObj->GetObjRect(); 81 // --> OD 2004-10-20 #i35640# - determine correct page frame 82 mpOldPageFrm = mpAnchoredDrawObj->GetPageFrm(); 83 // <-- 84 } 85 86 SwPosNotify::~SwPosNotify() 87 { 88 if ( maOldObjRect != mpAnchoredDrawObj->GetObjRect() ) 89 { 90 if( maOldObjRect.HasArea() && mpOldPageFrm ) 91 { 92 mpAnchoredDrawObj->NotifyBackground( mpOldPageFrm, maOldObjRect, 93 PREP_FLY_LEAVE ); 94 } 95 SwRect aNewObjRect( mpAnchoredDrawObj->GetObjRect() ); 96 if( aNewObjRect.HasArea() ) 97 { 98 // --> OD 2004-10-20 #i35640# - determine correct page frame 99 SwPageFrm* pNewPageFrm = mpAnchoredDrawObj->GetPageFrm(); 100 // <-- 101 if( pNewPageFrm ) 102 mpAnchoredDrawObj->NotifyBackground( pNewPageFrm, aNewObjRect, 103 PREP_FLY_ARRIVE ); 104 } 105 106 ::ClrContourCache( mpAnchoredDrawObj->GetDrawObj() ); 107 108 // --> OD 2004-10-20 #i35640# - additional notify anchor text frame 109 // Needed for negative positioned drawing objects 110 // --> OD 2005-03-01 #i43255# - refine condition to avoid unneeded 111 // invalidations: anchored object had to be on the page of its anchor 112 // text frame. 113 if ( mpAnchoredDrawObj->GetAnchorFrm()->IsTxtFrm() && 114 mpOldPageFrm == mpAnchoredDrawObj->GetAnchorFrm()->FindPageFrm() ) 115 { 116 mpAnchoredDrawObj->AnchorFrm()->Prepare( PREP_FLY_LEAVE ); 117 } 118 // <-- 119 120 // indicate a restart of the layout process 121 mpAnchoredDrawObj->SetRestartLayoutProcess( true ); 122 } 123 else 124 { 125 // lock position 126 mpAnchoredDrawObj->LockPosition(); 127 128 if ( !mpAnchoredDrawObj->ConsiderForTextWrap() ) 129 { 130 // indicate that object has to be considered for text wrap 131 mpAnchoredDrawObj->SetConsiderForTextWrap( true ); 132 // invalidate 'background' in order to allow its 'background' 133 // to wrap around it. 134 mpAnchoredDrawObj->NotifyBackground( mpAnchoredDrawObj->GetPageFrm(), 135 mpAnchoredDrawObj->GetObjRectWithSpaces(), 136 PREP_FLY_ARRIVE ); 137 // invalidate position of anchor frame in order to force 138 // a re-format of the anchor frame, which also causes a 139 // re-format of the invalid previous frames of the anchor frame. 140 mpAnchoredDrawObj->AnchorFrm()->InvalidatePos(); 141 } 142 } 143 } 144 145 // --> OD 2004-08-12 #i32795# 146 Point SwPosNotify::LastObjPos() const 147 { 148 return maOldObjRect.Pos(); 149 } 150 //<-- 151 152 // ============================================================================ 153 // OD 2004-08-12 #i32795# 154 // helper class for oscillation control on object positioning 155 // ============================================================================ 156 class SwObjPosOscillationControl 157 { 158 private: 159 sal_uInt8 mnPosStackSize; 160 161 const SwAnchoredDrawObject* mpAnchoredDrawObj; 162 163 std::vector<Point*> maObjPositions; 164 165 public: 166 SwObjPosOscillationControl( const SwAnchoredDrawObject& _rAnchoredDrawObj ); 167 ~SwObjPosOscillationControl(); 168 169 bool OscillationDetected(); 170 }; 171 172 SwObjPosOscillationControl::SwObjPosOscillationControl( 173 const SwAnchoredDrawObject& _rAnchoredDrawObj ) 174 : mnPosStackSize( 20 ), 175 mpAnchoredDrawObj( &_rAnchoredDrawObj ) 176 { 177 } 178 179 SwObjPosOscillationControl::~SwObjPosOscillationControl() 180 { 181 while ( !maObjPositions.empty() ) 182 { 183 Point* pPos = maObjPositions.back(); 184 delete pPos; 185 186 maObjPositions.pop_back(); 187 } 188 } 189 190 bool SwObjPosOscillationControl::OscillationDetected() 191 { 192 bool bOscillationDetected = false; 193 194 if ( maObjPositions.size() == mnPosStackSize ) 195 { 196 // position stack is full -> oscillation 197 bOscillationDetected = true; 198 } 199 else 200 { 201 Point* pNewObjPos = new Point( mpAnchoredDrawObj->GetObjRect().Pos() ); 202 for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin(); 203 aObjPosIter != maObjPositions.end(); 204 ++aObjPosIter ) 205 { 206 if ( *(pNewObjPos) == *(*aObjPosIter) ) 207 { 208 // position already occured -> oscillation 209 bOscillationDetected = true; 210 delete pNewObjPos; 211 break; 212 } 213 } 214 if ( !bOscillationDetected ) 215 { 216 maObjPositions.push_back( pNewObjPos ); 217 } 218 } 219 220 return bOscillationDetected; 221 } 222 223 // ============================================================================ 224 // implementation of class <SwAnchoredDrawObject> 225 // ============================================================================ 226 TYPEINIT1(SwAnchoredDrawObject,SwAnchoredObject); 227 228 SwAnchoredDrawObject::SwAnchoredDrawObject() : 229 SwAnchoredObject(), 230 mbValidPos( false ), 231 // --> OD 2004-09-29 #i34748# 232 mpLastObjRect( 0L ), 233 // <-- 234 mbNotYetAttachedToAnchorFrame( true ), 235 // --> OD 2004-08-09 #i28749# 236 mbNotYetPositioned( true ), 237 // <-- 238 // --> OD 2006-03-17 #i62875# 239 mbCaptureAfterLayoutDirChange( false ) 240 // <-- 241 { 242 } 243 244 SwAnchoredDrawObject::~SwAnchoredDrawObject() 245 { 246 // --> OD 2004-11-03 - follow-up of #i34748# 247 delete mpLastObjRect; 248 // <-- 249 } 250 251 // --> OD 2006-03-17 #i62875# 252 void SwAnchoredDrawObject::UpdateLayoutDir() 253 { 254 SwFrmFmt::tLayoutDir nOldLayoutDir( GetFrmFmt().GetLayoutDir() ); 255 256 SwAnchoredObject::UpdateLayoutDir(); 257 258 if ( !NotYetPositioned() && 259 GetFrmFmt().GetLayoutDir() != nOldLayoutDir && 260 GetFrmFmt().GetDoc()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) && 261 !IsOutsidePage() ) 262 { 263 mbCaptureAfterLayoutDirChange = true; 264 } 265 } 266 // <-- 267 268 // --> OD 2006-03-17 #i62875# 269 bool SwAnchoredDrawObject::IsOutsidePage() const 270 { 271 bool bOutsidePage( false ); 272 273 if ( !NotYetPositioned() && GetPageFrm() ) 274 { 275 SwRect aTmpRect( GetObjRect() ); 276 bOutsidePage = 277 ( aTmpRect.Intersection( GetPageFrm()->Frm() ) != GetObjRect() ); 278 } 279 280 return bOutsidePage; 281 } 282 // <-- 283 284 // ============================================================================= 285 // OD 2004-03-25 #i26791# - implementation of pure virtual method declared in 286 // base class <SwAnchoredObject> 287 // ============================================================================= 288 void SwAnchoredDrawObject::MakeObjPos() 289 { 290 if ( IsPositioningInProgress() ) 291 { 292 // nothind to do - positioning already in progress 293 return; 294 } 295 296 if ( mbValidPos ) 297 { 298 // nothing to do - position is valid 299 return; 300 } 301 302 // --> OD 2004-08-09 #i28749# - anchored drawing object has to be attached 303 // to anchor frame 304 if ( mbNotYetAttachedToAnchorFrame ) 305 { 306 ASSERT( false, 307 "<SwAnchoredDrawObject::MakeObjPos() - drawing object not yet attached to anchor frame -> no positioning" ); 308 return; 309 } 310 311 SwDrawContact* pDrawContact = 312 static_cast<SwDrawContact*>(::GetUserCall( GetDrawObj() )); 313 314 // --> OD 2004-08-09 #i28749# - if anchored drawing object hasn't been yet 315 // positioned, convert its positioning attributes, if its positioning 316 // attributes are given in horizontal left-to-right layout. 317 // --> OD 2004-10-25 #i36010# - Note: horizontal left-to-right layout is made 318 // the default layout direction for <SwDrawFrmFmt> instances. Thus, it has 319 // to be adjusted manually, if no adjustment of the positioning attributes 320 // have to be performed here. 321 // --> OD 2004-11-17 #i35635# - additionally move drawing object to the 322 // visible layer. 323 if ( mbNotYetPositioned ) 324 { 325 // --> OD 2004-11-17 #i35635# 326 pDrawContact->MoveObjToVisibleLayer( DrawObj() ); 327 // <-- 328 // --> OD 2004-09-29 #117975# - perform conversion of positioning 329 // attributes only for 'master' drawing objects 330 // --> OD 2005-03-11 #i44334#, #i44681# - check, if positioning 331 // attributes already have been set. 332 if ( !GetDrawObj()->ISA(SwDrawVirtObj) && 333 !static_cast<SwDrawFrmFmt&>(GetFrmFmt()).IsPosAttrSet() ) 334 { 335 _SetPositioningAttr(); 336 } 337 // <-- 338 // --> OD 2006-05-24 #b6418964# 339 // - reset internal flag after all needed actions are performed to 340 // avoid callbacks from drawing layer 341 mbNotYetPositioned = false; 342 // <-- 343 } 344 // <-- 345 346 // indicate that positioning is in progress 347 { 348 SwObjPositioningInProgress aObjPosInProgress( *this ); 349 350 // determine relative position of drawing object and set it 351 switch ( pDrawContact->GetAnchorId() ) 352 { 353 case FLY_AS_CHAR: 354 { 355 // indicate that position will be valid after positioning is performed 356 mbValidPos = true; 357 // nothing to do, because as-character anchored objects are positioned 358 // during the format of its anchor frame - see <SwFlyCntPortion::SetBase(..)> 359 } 360 break; 361 case FLY_AT_PARA: 362 case FLY_AT_CHAR: 363 { 364 // --> OD 2004-08-12 #i32795# - move intrinsic positioning to 365 // helper method <_MakeObjPosAnchoredAtPara()> 366 _MakeObjPosAnchoredAtPara(); 367 } 368 break; 369 case FLY_AT_PAGE: 370 case FLY_AT_FLY: 371 { 372 // --> OD 2004-08-12 #i32795# - move intrinsic positioning to 373 // helper method <_MakeObjPosAnchoredAtLayout()> 374 _MakeObjPosAnchoredAtLayout(); 375 } 376 break; 377 default: 378 { 379 ASSERT( false, "<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type - please inform OD." ); 380 } 381 } 382 383 // keep, current object rectangle 384 // --> OD 2004-09-29 #i34748# - use new method <SetLastObjRect(..)> 385 SetLastObjRect( GetObjRect().SVRect() ); 386 // <-- 387 388 // Assure for 'master' drawing object, that it's registered at the correct page. 389 // Perform check not for as-character anchored drawing objects and only if 390 // the anchor frame is valid. 391 if ( !GetDrawObj()->ISA(SwDrawVirtObj) && 392 !pDrawContact->ObjAnchoredAsChar() && 393 GetAnchorFrm()->IsValid() ) 394 { 395 pDrawContact->ChkPage(); 396 } 397 } 398 399 // --> OD 2006-03-17 #i62875# 400 if ( mbCaptureAfterLayoutDirChange && 401 GetPageFrm() ) 402 { 403 SwRect aPageRect( GetPageFrm()->Frm() ); 404 SwRect aObjRect( GetObjRect() ); 405 if ( aObjRect.Right() >= aPageRect.Right() + 10 ) 406 { 407 Size aSize( aPageRect.Right() - aObjRect.Right(), 0 ); 408 DrawObj()->Move( aSize ); 409 aObjRect = GetObjRect(); 410 } 411 412 if ( aObjRect.Left() + 10 <= aPageRect.Left() ) 413 { 414 Size aSize( aPageRect.Left() - aObjRect.Left(), 0 ); 415 DrawObj()->Move( aSize ); 416 } 417 418 mbCaptureAfterLayoutDirChange = false; 419 } 420 // <-- 421 } 422 423 /** method for the intrinsic positioning of a at-paragraph|at-character 424 anchored drawing object 425 426 OD 2004-08-12 #i32795# - helper method for method <MakeObjPos> 427 428 @author OD 429 */ 430 void SwAnchoredDrawObject::_MakeObjPosAnchoredAtPara() 431 { 432 // --> OD 2004-08-12 #i32795# - adopt positioning algorithm from Writer 433 // fly frames, which are anchored at paragraph|at character 434 435 // Determine, if anchor frame can/has to be formatted. 436 // If yes, after each object positioning the anchor frame is formatted. 437 // If after the anchor frame format the object position isn't valid, the 438 // object is positioned again. 439 // --> OD 2005-02-22 #i43255# - refine condition: anchor frame format not 440 // allowed, if another anchored object, has to be consider its wrap influence 441 // --> OD 2005-06-07 #i50356# - format anchor frame containing the anchor 442 // position. E.g., for at-character anchored object this can be the follow 443 // frame of the anchor frame, which contains the anchor character. 444 const bool bFormatAnchor = 445 !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() && 446 !ConsiderObjWrapInfluenceOnObjPos() && 447 !ConsiderObjWrapInfluenceOfOtherObjs(); 448 // <-- 449 450 if ( bFormatAnchor ) 451 { 452 // --> OD 2005-06-07 #i50356# 453 GetAnchorFrmContainingAnchPos()->Calc(); 454 // <-- 455 } 456 457 bool bOscillationDetected = false; 458 SwObjPosOscillationControl aObjPosOscCtrl( *this ); 459 // --> OD 2004-08-25 #i3317# - boolean, to apply temporarly the 460 // 'straightforward positioning process' for the frame due to its 461 // overlapping with a previous column. 462 bool bConsiderWrapInfluenceDueToOverlapPrevCol( false ); 463 // <-- 464 do { 465 // indicate that position will be valid after positioning is performed 466 mbValidPos = true; 467 468 // --> OD 2004-10-20 #i35640# - correct scope for <SwPosNotify> instance 469 { 470 // create instance of <SwPosNotify> for correct notification 471 SwPosNotify aPosNotify( this ); 472 473 // determine and set position 474 objectpositioning::SwToCntntAnchoredObjectPosition 475 aObjPositioning( *DrawObj() ); 476 aObjPositioning.CalcPosition(); 477 478 // get further needed results of the positioning algorithm 479 SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() ); 480 _SetDrawObjAnchor(); 481 482 // check for object position oscillation, if position has changed. 483 if ( GetObjRect().Pos() != aPosNotify.LastObjPos() ) 484 { 485 bOscillationDetected = aObjPosOscCtrl.OscillationDetected(); 486 } 487 } 488 // <-- 489 // format anchor frame, if requested. 490 // Note: the format of the anchor frame can cause the object position 491 // to be invalid. 492 if ( bFormatAnchor ) 493 { 494 // --> OD 2005-06-07 #i50356# 495 GetAnchorFrmContainingAnchPos()->Calc(); 496 // <-- 497 } 498 499 // --> OD 2004-08-25 #i3317# 500 if ( !ConsiderObjWrapInfluenceOnObjPos() && 501 OverlapsPrevColumn() ) 502 { 503 bConsiderWrapInfluenceDueToOverlapPrevCol = true; 504 } 505 // <-- 506 } while ( !mbValidPos && !bOscillationDetected && 507 !bConsiderWrapInfluenceDueToOverlapPrevCol ); 508 509 // --> OD 2004-08-25 #i3317# - consider a detected oscillation and overlapping 510 // with previous column. 511 // temporarly consider the anchored objects wrapping style influence 512 if ( bOscillationDetected || bConsiderWrapInfluenceDueToOverlapPrevCol ) 513 { 514 SetTmpConsiderWrapInfluence( true ); 515 SetRestartLayoutProcess( true ); 516 } 517 // <-- 518 } 519 520 /** method for the intrinsic positioning of a at-page|at-frame anchored 521 drawing object 522 523 OD 2004-08-12 #i32795# - helper method for method <MakeObjPos> 524 525 @author OD 526 */ 527 void SwAnchoredDrawObject::_MakeObjPosAnchoredAtLayout() 528 { 529 // indicate that position will be valid after positioning is performed 530 mbValidPos = true; 531 532 // create instance of <SwPosNotify> for correct notification 533 SwPosNotify aPosNotify( this ); 534 535 // determine position 536 objectpositioning::SwToLayoutAnchoredObjectPosition 537 aObjPositioning( *DrawObj() ); 538 aObjPositioning.CalcPosition(); 539 540 // set position 541 542 // --> OD 2004-07-29 #i31698# 543 // --> OD 2004-10-18 #i34995# - setting anchor position needed for filters, 544 // especially for the xml-filter to the OpenOffice.org file format 545 { 546 const Point aNewAnchorPos = 547 GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) ); 548 DrawObj()->SetAnchorPos( aNewAnchorPos ); 549 // --> OD 2006-10-05 #i70122# - missing invalidation 550 InvalidateObjRectWithSpaces(); 551 // <-- 552 } 553 // <-- 554 SetCurrRelPos( aObjPositioning.GetRelPos() ); 555 const SwFrm* pAnchorFrm = GetAnchorFrm(); 556 SWRECTFN( pAnchorFrm ); 557 const Point aAnchPos( (pAnchorFrm->Frm().*fnRect->fnGetPos)() ); 558 SetObjLeft( aAnchPos.X() + GetCurrRelPos().X() ); 559 SetObjTop( aAnchPos.Y() + GetCurrRelPos().Y() ); 560 // <-- 561 } 562 563 void SwAnchoredDrawObject::_SetDrawObjAnchor() 564 { 565 // new anchor position 566 // --> OD 2004-07-29 #i31698# - 567 Point aNewAnchorPos = 568 GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) ); 569 Point aCurrAnchorPos = GetDrawObj()->GetAnchorPos(); 570 if ( aNewAnchorPos != aCurrAnchorPos ) 571 { 572 // determine movement to be applied after setting the new anchor position 573 Size aMove( aCurrAnchorPos.X() - aNewAnchorPos.X(), 574 aCurrAnchorPos.Y() - aNewAnchorPos.Y() ); 575 // set new anchor position 576 DrawObj()->SetAnchorPos( aNewAnchorPos ); 577 // correct object position, caused by setting new anchor position 578 DrawObj()->Move( aMove ); 579 // --> OD 2006-10-05 #i70122# - missing invalidation 580 InvalidateObjRectWithSpaces(); 581 // <-- 582 } 583 } 584 585 /** method to invalidate the given page frame 586 587 OD 2004-07-02 #i28701# 588 589 @author OD 590 */ 591 void SwAnchoredDrawObject::_InvalidatePage( SwPageFrm* _pPageFrm ) 592 { 593 if ( _pPageFrm && !_pPageFrm->GetFmt()->GetDoc()->IsInDtor() ) 594 { 595 if ( _pPageFrm->GetUpper() ) 596 { 597 // --> OD 2004-11-11 #i35007# - correct invalidation for as-character 598 // anchored objects. 599 if ( GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR ) 600 { 601 _pPageFrm->InvalidateFlyInCnt(); 602 } 603 else 604 { 605 _pPageFrm->InvalidateFlyLayout(); 606 } 607 // <-- 608 609 SwRootFrm* pRootFrm = static_cast<SwRootFrm*>(_pPageFrm->GetUpper()); 610 pRootFrm->DisallowTurbo(); 611 if ( pRootFrm->GetTurbo() ) 612 { 613 const SwCntntFrm* pTmpFrm = pRootFrm->GetTurbo(); 614 pRootFrm->ResetTurbo(); 615 pTmpFrm->InvalidatePage(); 616 } 617 pRootFrm->SetIdleFlags(); 618 } 619 } 620 } 621 622 void SwAnchoredDrawObject::InvalidateObjPos() 623 { 624 // --> OD 2004-07-01 #i28701# - check, if invalidation is allowed 625 if ( mbValidPos && 626 InvalidationOfPosAllowed() ) 627 { 628 mbValidPos = false; 629 // --> OD 2006-08-10 #i68520# 630 InvalidateObjRectWithSpaces(); 631 // <-- 632 633 // --> OD 2005-03-08 #i44339# - check, if anchor frame exists. 634 if ( GetAnchorFrm() ) 635 { 636 // --> OD 2004-11-22 #118547# - notify anchor frame of as-character 637 // anchored object, because its positioned by the format of its anchor frame. 638 // --> OD 2005-03-09 #i44559# - assure, that text hint is already 639 // existing in the text frame 640 if ( GetAnchorFrm()->ISA(SwTxtFrm) && 641 (GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) ) 642 { 643 SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) ); 644 if ( pAnchorTxtFrm->GetTxtNode()->GetpSwpHints() && 645 pAnchorTxtFrm->CalcFlyPos( &GetFrmFmt() ) != STRING_LEN ) 646 { 647 AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() ); 648 } 649 } 650 // <-- 651 652 SwPageFrm* pPageFrm = AnchorFrm()->FindPageFrm(); 653 _InvalidatePage( pPageFrm ); 654 655 // --> OD 2004-08-12 #i32270# - also invalidate page frame, at which the 656 // drawing object is registered at. 657 SwPageFrm* pPageFrmRegisteredAt = GetPageFrm(); 658 if ( pPageFrmRegisteredAt && 659 pPageFrmRegisteredAt != pPageFrm ) 660 { 661 _InvalidatePage( pPageFrmRegisteredAt ); 662 } 663 // <-- 664 // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()> 665 // is replaced by method <FindPageFrmOfAnchor()>. It's return value 666 // have to be checked. 667 SwPageFrm* pPageFrmOfAnchor = FindPageFrmOfAnchor(); 668 if ( pPageFrmOfAnchor && 669 pPageFrmOfAnchor != pPageFrm && 670 pPageFrmOfAnchor != pPageFrmRegisteredAt ) 671 // <-- 672 { 673 _InvalidatePage( pPageFrmOfAnchor ); 674 } 675 } 676 // <-- 677 } 678 } 679 680 SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt() 681 { 682 ASSERT( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(), 683 "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." ); 684 return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt()); 685 } 686 const SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt() const 687 { 688 ASSERT( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(), 689 "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." ); 690 return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt()); 691 } 692 693 const SwRect SwAnchoredDrawObject::GetObjRect() const 694 { 695 // use geometry of drawing object 696 //return GetDrawObj()->GetCurrentBoundRect(); 697 return GetDrawObj()->GetSnapRect(); 698 } 699 700 // --> OD 2006-10-05 #i70122# 701 const SwRect SwAnchoredDrawObject::GetObjBoundRect() const 702 { 703 return GetDrawObj()->GetCurrentBoundRect(); 704 } 705 // <-- 706 707 // --> OD 2006-08-10 #i68520# 708 bool SwAnchoredDrawObject::_SetObjTop( const SwTwips _nTop ) 709 { 710 SwTwips nDiff = _nTop - GetObjRect().Top(); 711 DrawObj()->Move( Size( 0, nDiff ) ); 712 713 return nDiff != 0; 714 } 715 bool SwAnchoredDrawObject::_SetObjLeft( const SwTwips _nLeft ) 716 { 717 SwTwips nDiff = _nLeft - GetObjRect().Left(); 718 DrawObj()->Move( Size( nDiff, 0 ) ); 719 720 return nDiff != 0; 721 } 722 // <-- 723 724 /** adjust positioning and alignment attributes for new anchor frame 725 726 OD 2004-08-24 #i33313# - add second optional parameter <_pNewObjRect> 727 728 @author OD 729 */ 730 void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrm* _pNewAnchorFrm, 731 const SwRect* _pNewObjRect ) 732 { 733 SwTwips nHoriRelPos = 0; 734 SwTwips nVertRelPos = 0; 735 const Point aAnchorPos = _pNewAnchorFrm->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) ); 736 // --> OD 2004-08-24 #i33313# 737 const SwRect aObjRect( _pNewObjRect ? *_pNewObjRect : GetObjRect() ); 738 // <-- 739 const bool bVert = _pNewAnchorFrm->IsVertical(); 740 const bool bR2L = _pNewAnchorFrm->IsRightToLeft(); 741 if ( bVert ) 742 { 743 nHoriRelPos = aObjRect.Top() - aAnchorPos.Y(); 744 nVertRelPos = aAnchorPos.X() - aObjRect.Right(); 745 } 746 else if ( bR2L ) 747 { 748 nHoriRelPos = aAnchorPos.X() - aObjRect.Right(); 749 nVertRelPos = aObjRect.Top() - aAnchorPos.Y(); 750 } 751 else 752 { 753 nHoriRelPos = aObjRect.Left() - aAnchorPos.X(); 754 nVertRelPos = aObjRect.Top() - aAnchorPos.Y(); 755 } 756 757 GetFrmFmt().SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) ); 758 GetFrmFmt().SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) ); 759 } 760 761 // --> OD 2004-09-29 #i34748# - change return type 762 const Rectangle* SwAnchoredDrawObject::GetLastObjRect() const 763 { 764 return mpLastObjRect; 765 } 766 // <-- 767 768 // --> OD 2004-09-29 #i34748# - change return type. 769 // If member <mpLastObjRect> is NULL, create one. 770 void SwAnchoredDrawObject::SetLastObjRect( const Rectangle& _rNewLastRect ) 771 { 772 if ( !mpLastObjRect ) 773 { 774 mpLastObjRect = new Rectangle; 775 } 776 *(mpLastObjRect) = _rNewLastRect; 777 } 778 // <-- 779 780 void SwAnchoredDrawObject::ObjectAttachedToAnchorFrame() 781 { 782 // --> OD 2004-07-27 #i31698# 783 SwAnchoredObject::ObjectAttachedToAnchorFrame(); 784 // <-- 785 786 if ( mbNotYetAttachedToAnchorFrame ) 787 { 788 mbNotYetAttachedToAnchorFrame = false; 789 } 790 } 791 792 /** method to set positioning attributes 793 794 OD 2004-10-20 #i35798# 795 During load the positioning attributes aren't set. 796 Thus, the positioning attributes are set by the current object geometry. 797 This method is also used for the conversion for drawing objects 798 (not anchored as-character) imported from OpenOffice.org file format 799 once and directly before the first positioning. 800 801 @author OD 802 */ 803 void SwAnchoredDrawObject::_SetPositioningAttr() 804 { 805 SwDrawContact* pDrawContact = 806 static_cast<SwDrawContact*>(GetUserCall( GetDrawObj() )); 807 808 if ( !pDrawContact->ObjAnchoredAsChar() ) 809 { 810 SwRect aObjRect( GetObjRect() ); 811 812 SwTwips nHoriPos = aObjRect.Left(); 813 SwTwips nVertPos = aObjRect.Top(); 814 // --> OD 2005-03-10 #i44334#, #i44681# 815 // perform conversion only if position is in horizontal-left-to-right-layout. 816 if ( GetFrmFmt().GetPositionLayoutDir() == 817 text::PositionLayoutDir::PositionInHoriL2R ) 818 { 819 SwFrmFmt::tLayoutDir eLayoutDir = GetFrmFmt().GetLayoutDir(); 820 switch ( eLayoutDir ) 821 { 822 case SwFrmFmt::HORI_L2R: 823 { 824 // nothing to do 825 } 826 break; 827 case SwFrmFmt::HORI_R2L: 828 { 829 nHoriPos = -aObjRect.Left() - aObjRect.Width(); 830 } 831 break; 832 case SwFrmFmt::VERT_R2L: 833 { 834 nHoriPos = aObjRect.Top(); 835 nVertPos = -aObjRect.Left() - aObjRect.Width(); 836 } 837 break; 838 default: 839 { 840 ASSERT( false, 841 "<SwAnchoredDrawObject::_SetPositioningAttr()> - unsupported layout direction" ); 842 } 843 } 844 } 845 // <-- 846 847 // --> OD 2006-11-10 #i71182# 848 // only change position - do not lose other attributes 849 SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() ); 850 aHori.SetPos( nHoriPos ); 851 GetFrmFmt().SetFmtAttr( aHori ); 852 853 SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() ); 854 // --> OD 2007-01-03 #i73079# - vertical position already correct 855 // if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR || 856 // aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) 857 // { 858 // nVertPos = -nVertPos; 859 // } 860 // <-- 861 aVert.SetPos( nVertPos ); 862 GetFrmFmt().SetFmtAttr( aVert ); 863 // <-- 864 865 // --> OD 2004-10-25 #i36010# - set layout direction of the position 866 GetFrmFmt().SetPositionLayoutDir( 867 text::PositionLayoutDir::PositionInLayoutDirOfAnchor ); 868 // <-- 869 } 870 // --> OD 2007-11-29 #i65798# - also for as-character anchored objects 871 // --> OD 2005-05-10 #i45952# - indicate that position 872 // attributes are set now. 873 static_cast<SwDrawFrmFmt&>(GetFrmFmt()).PosAttrSet(); 874 // <-- 875 } 876 877 void SwAnchoredDrawObject::NotifyBackground( SwPageFrm* _pPageFrm, 878 const SwRect& _rRect, 879 PrepareHint _eHint ) 880 { 881 ::Notify_Background( GetDrawObj(), _pPageFrm, _rRect, _eHint, sal_True ); 882 } 883 884 /** method to assure that anchored object is registered at the correct 885 page frame 886 887 OD 2004-07-02 #i28701# 888 889 @author OD 890 */ 891 void SwAnchoredDrawObject::RegisterAtCorrectPage() 892 { 893 SwPageFrm* pPageFrm( 0L ); 894 if ( GetVertPosOrientFrm() ) 895 { 896 pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm()); 897 } 898 if ( pPageFrm && GetPageFrm() != pPageFrm ) 899 { 900 if ( GetPageFrm() ) 901 GetPageFrm()->RemoveDrawObjFromPage( *this ); 902 pPageFrm->AppendDrawObjToPage( *this ); 903 } 904 } 905 906 // ============================================================================= 907