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