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 27 #include "hintids.hxx" 28 #include <editeng/protitem.hxx> 29 #include <svx/svdpagv.hxx> 30 #include <svx/fmmodel.hxx> 31 #include <sot/exchange.hxx> 32 33 #include "swtypes.hxx" 34 #include "pagefrm.hxx" 35 #include "rootfrm.hxx" 36 #include "cntfrm.hxx" 37 #include "flyfrm.hxx" 38 #include "frmfmt.hxx" 39 #include "dflyobj.hxx" 40 #include "dcontact.hxx" 41 #include "frmatr.hxx" 42 #include "viewsh.hxx" 43 #include "viewimp.hxx" 44 #include "dview.hxx" 45 #include "dpage.hxx" 46 #include "doc.hxx" 47 #include "mdiexp.hxx" 48 #include <ndole.hxx> 49 #include <fmtanchr.hxx> 50 #include "shellres.hxx" 51 #include <IDocumentUndoRedo.hxx> 52 53 // #i7672# 54 #include <editeng/outliner.hxx> 55 56 #include <com/sun/star/embed/EmbedMisc.hpp> 57 58 // OD 18.06.2003 #108784# 59 //#ifndef _SVDVMARK_HXX //autogen 60 //#include <svx/svdvmark.hxx> 61 //#endif 62 #include <vector> 63 // --> OD 2004-06-24 #i28701# 64 #include <sortedobjs.hxx> 65 #include <flyfrms.hxx> 66 // <-- 67 68 69 using namespace com::sun::star; 70 71 72 class SwSdrHdl : public SdrHdl 73 { 74 public: 75 SwSdrHdl(const Point& rPnt, bool bTopRight ) : 76 SdrHdl( rPnt, bTopRight ? HDL_ANCHOR_TR : HDL_ANCHOR ) {} 77 virtual sal_Bool IsFocusHdl() const; 78 }; 79 80 sal_Bool SwSdrHdl::IsFocusHdl() const 81 { 82 if( HDL_ANCHOR == eKind || HDL_ANCHOR_TR == eKind ) 83 return sal_True; 84 return SdrHdl::IsFocusHdl(); 85 } 86 87 const SwFrm *lcl_FindAnchor( const SdrObject *pObj, sal_Bool bAll ) 88 { 89 const SwVirtFlyDrawObj *pVirt = pObj->ISA(SwVirtFlyDrawObj) ? 90 (SwVirtFlyDrawObj*)pObj : 0; 91 if ( pVirt ) 92 { 93 if ( bAll || !pVirt->GetFlyFrm()->IsFlyInCntFrm() ) 94 return pVirt->GetFlyFrm()->GetAnchorFrm(); 95 } 96 else 97 { 98 const SwDrawContact *pCont = (const SwDrawContact*)GetUserCall(pObj); 99 if ( pCont ) 100 return pCont->GetAnchorFrm( pObj ); 101 } 102 return 0; 103 } 104 105 /************************************************************************* 106 |* 107 |* SwDrawView::Ctor 108 |* 109 |* Ersterstellung OK 18.11.94 110 |* Letzte Aenderung MA 22. Jul. 96 111 |* 112 *************************************************************************/ 113 114 115 116 SwDrawView::SwDrawView( SwViewImp &rI, SdrModel *pMd, OutputDevice *pOutDev) : 117 FmFormView( (FmFormModel*)pMd, pOutDev ), 118 rImp( rI ) 119 { 120 SetPageVisible( sal_False ); 121 SetBordVisible( sal_False ); 122 SetGridVisible( sal_False ); 123 SetHlplVisible( sal_False ); 124 SetGlueVisible( sal_False ); 125 SetFrameDragSingles( sal_True ); 126 SetVirtualObjectBundling( sal_True ); 127 SetSwapAsynchron( sal_True ); 128 129 EnableExtendedKeyInputDispatcher( sal_False ); 130 EnableExtendedMouseEventDispatcher( sal_False ); 131 EnableExtendedCommandEventDispatcher( sal_False ); 132 133 SetHitTolerancePixel( GetMarkHdlSizePixel()/2 ); 134 135 SetPrintPreview( rI.GetShell()->IsPreView() ); 136 137 // #i73602# Use default from the configuration 138 SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Writer()); 139 140 // #i74769#, #i75172# Use default from the configuration 141 SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Writer()); 142 } 143 144 // --> OD 2009-03-05 #i99665# 145 sal_Bool SwDrawView::IsAntiAliasing() const 146 { 147 return getOptionsDrawinglayer().IsAntiAliasing(); 148 } 149 // <-- 150 151 ////////////////////////////////////////////////////////////////////////////// 152 153 SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList) 154 { 155 if(!nTol) 156 { 157 // the old method forced back to outer bounds test when nTol == 0, so 158 // do not try to correct when nTol is not set (used from HelpContent) 159 } 160 else 161 { 162 // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since 163 // the SdrObject-specific CheckHit implementations are now replaced with primitives and 164 // 'tricks' like in the old implementation (e.g. using a view from a model-data class to 165 // detect if object is selected) are no longer valid. 166 // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old 167 // implementation reduced this excluding the inner bound when the object was not selected. 168 SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval); 169 170 if(pSwVirtFlyDrawObj) 171 { 172 if(pSwVirtFlyDrawObj->GetFlyFrm()->Lower() && pSwVirtFlyDrawObj->GetFlyFrm()->Lower()->IsNoTxtFrm()) 173 { 174 // the old method used IsNoTxtFrm (should be for SW's own OLE and 175 // graphic's) to accept hit only based on outer bounds; nothing to do 176 } 177 else 178 { 179 // check if the object is selected in this view 180 const sal_uInt32 nMarkCount(rMrkList.GetMarkCount()); 181 bool bSelected(false); 182 183 for(sal_uInt32 a(0); !bSelected && a < nMarkCount; a++) 184 { 185 if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj()) 186 { 187 bSelected = true; 188 } 189 } 190 191 if(!bSelected) 192 { 193 // when not selected, the object is not hit when hit position is inside 194 // inner range. Get and shrink inner range 195 basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound()); 196 197 aInnerBound.grow(-1.0 * nTol); 198 199 if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y()))) 200 { 201 // exclude this hit 202 pRetval = 0; 203 } 204 } 205 } 206 } 207 } 208 209 return pRetval; 210 } 211 212 SdrObject* SwDrawView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, sal_uLong nOptions, const SetOfByte* pMVisLay) const 213 { 214 // call parent 215 SdrObject* pRetval = FmFormView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay); 216 217 if(pRetval) 218 { 219 // overloaded to allow extra handling when picking SwVirtFlyDrawObj's 220 pRetval = impLocalHitCorrection(pRetval, rPnt, nTol, GetMarkedObjectList()); 221 } 222 223 return pRetval; 224 } 225 226 /************************************************************************* 227 |* 228 |* SwDrawView::AddCustomHdl() 229 |* 230 |* Gets called every time the handles need to be build 231 |* 232 |* Ersterstellung AW 06. Sep. 99 233 |* Letzte Aenderung AW 06. Sep. 99 234 |* 235 *************************************************************************/ 236 237 void SwDrawView::AddCustomHdl() 238 { 239 const SdrMarkList &rMrkList = GetMarkedObjectList(); 240 241 if(rMrkList.GetMarkCount() != 1 || !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj())) 242 return; 243 244 SdrObject *pObj = rMrkList.GetMark(0)->GetMarkedSdrObj(); 245 // --> OD 2006-11-06 #130889# - make code robust 246 // const SwFmtAnchor &rAnchor = ::FindFrmFmt(pObj)->GetAnchor(); 247 SwFrmFmt* pFrmFmt( ::FindFrmFmt( pObj ) ); 248 if ( !pFrmFmt ) 249 { 250 ASSERT( false, "<SwDrawView::AddCustomHdl()> - missing frame format!" ); 251 return; 252 } 253 const SwFmtAnchor &rAnchor = pFrmFmt->GetAnchor(); 254 // <-- 255 256 if (FLY_AS_CHAR == rAnchor.GetAnchorId()) 257 return; 258 259 const SwFrm* pAnch; 260 if(0 == (pAnch = CalcAnchor())) 261 return; 262 263 Point aPos(aAnchorPoint); 264 265 if ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) 266 { 267 // --> OD 2004-06-24 #i28701# - use last character rectangle saved at object 268 // in order to avoid a format of the anchor frame 269 SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj ); 270 SwRect aAutoPos = pAnchoredObj->GetLastCharRect(); 271 if ( aAutoPos.Height() ) 272 { 273 aPos = aAutoPos.Pos(); 274 } 275 } 276 277 // add anchor handle: 278 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 279 aHdl.AddHdl( new SwSdrHdl( aPos, ( pAnch->IsVertical() && !pAnch->IsVertLR() ) || 280 pAnch->IsRightToLeft() ) ); 281 } 282 283 /************************************************************************* 284 |* 285 |* SwDrawView::GetMaxToTopObj(), _GetMaxToTopObj() 286 |* 287 |* Ersterstellung MA 13. Jan. 95 288 |* Letzte Aenderung MA 18. Mar. 97 289 |* 290 *************************************************************************/ 291 292 293 SdrObject* SwDrawView::GetMaxToTopObj( SdrObject* pObj ) const 294 { 295 if ( GetUserCall(pObj) ) 296 { 297 const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False ); 298 if ( pAnch ) 299 { 300 //Das oberste Obj innerhalb des Ankers darf nicht ueberholt 301 //werden. 302 const SwFlyFrm *pFly = pAnch->FindFlyFrm(); 303 if ( pFly ) 304 { 305 const SwPageFrm *pPage = pFly->FindPageFrm(); 306 if ( pPage->GetSortedObjs() ) 307 { 308 sal_uInt32 nOrdNum = 0; 309 for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i ) 310 { 311 const SdrObject *pO = 312 (*pPage->GetSortedObjs())[i]->GetDrawObj(); 313 314 if ( pO->GetOrdNumDirect() > nOrdNum ) 315 { 316 const SwFrm *pTmpAnch = ::lcl_FindAnchor( pO, sal_False ); 317 if ( pFly->IsAnLower( pTmpAnch ) ) 318 { 319 nOrdNum = pO->GetOrdNumDirect(); 320 } 321 } 322 } 323 if ( nOrdNum ) 324 { 325 SdrPage *pTmpPage = GetModel()->GetPage( 0 ); 326 ++nOrdNum; 327 if ( nOrdNum < pTmpPage->GetObjCount() ) 328 { 329 return pTmpPage->GetObj( nOrdNum ); 330 } 331 } 332 } 333 } 334 } 335 } 336 return 0; 337 } 338 339 /************************************************************************* 340 |* 341 |* SwDrawView::GetMaxToBtmObj() 342 |* 343 |* Ersterstellung MA 13. Jan. 95 344 |* Letzte Aenderung MA 05. Sep. 96 345 |* 346 *************************************************************************/ 347 348 349 SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const 350 { 351 if ( GetUserCall(pObj) ) 352 { 353 const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False ); 354 if ( pAnch ) 355 { 356 //Der Fly des Ankers darf nicht "unterflogen" werden. 357 const SwFlyFrm *pFly = pAnch->FindFlyFrm(); 358 if ( pFly ) 359 { 360 SdrObject *pRet = (SdrObject*)pFly->GetVirtDrawObj(); 361 return pRet != pObj ? pRet : 0; 362 } 363 } 364 } 365 return 0; 366 } 367 368 /************************************************************************* 369 |* 370 |* SwDrawView::ObjOrderChanged() 371 |* 372 |* Ersterstellung MA 31. Jul. 95 373 |* Letzte Aenderung MA 18. Mar. 97 374 |* 375 *************************************************************************/ 376 377 inline sal_Bool lcl_IsChild( SdrObject *pParent, SdrObject *pChild ) 378 { 379 if ( pParent->ISA(SwVirtFlyDrawObj) ) 380 { 381 const SwFrm *pAnch = lcl_FindAnchor( pChild, sal_False ); 382 if ( pAnch && ((SwVirtFlyDrawObj*)pParent)->GetFlyFrm()->IsAnLower( pAnch )) 383 { 384 return sal_True; 385 } 386 } 387 return sal_False; 388 } 389 390 inline SdrObject *lcl_FindParent( SdrObject *pObj ) 391 { 392 const SwFrm *pAnch = lcl_FindAnchor( pObj, sal_False ); 393 if ( pAnch && pAnch->IsInFly() ) 394 return (SdrObject*)pAnch->FindFlyFrm()->GetVirtDrawObj(); 395 return 0; 396 } 397 398 /** determine maximal order number for a 'child' object of given 'parent' object 399 400 OD 2004-08-20 #110810# 401 402 @author OD 403 */ 404 sal_uInt32 SwDrawView::_GetMaxChildOrdNum( const SwFlyFrm& _rParentObj, 405 const SdrObject* _pExclChildObj ) const 406 { 407 sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum(); 408 409 const SdrPage* pDrawPage = _rParentObj.GetDrawObj()->GetPage(); 410 ASSERT( pDrawPage, 411 "<SwDrawView::_GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" ); 412 413 sal_uInt32 nObjCount = pDrawPage->GetObjCount(); 414 for ( sal_uInt32 i = nObjCount-1; i > _rParentObj.GetDrawObj()->GetOrdNum() ; --i ) 415 { 416 const SdrObject* pObj = pDrawPage->GetObj( i ); 417 418 // Don't consider 'child' object <_pExclChildObj> 419 if ( pObj == _pExclChildObj ) 420 { 421 continue; 422 } 423 424 if ( pObj->GetOrdNum() > nMaxChildOrdNum && 425 _rParentObj.IsAnLower( lcl_FindAnchor( pObj, sal_True ) ) ) 426 { 427 nMaxChildOrdNum = pObj->GetOrdNum(); 428 break; 429 } 430 } 431 432 return nMaxChildOrdNum; 433 } 434 435 /** method to move 'repeated' objects of the given moved object to the 436 according level 437 438 OD 2004-08-23 #110810# 439 440 @author OD 441 */ 442 void SwDrawView::_MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj, 443 const std::vector<SdrObject*>& _rMovedChildObjs ) const 444 { 445 // determine 'repeated' objects of already moved object <_rMovedAnchoredObj> 446 std::list<SwAnchoredObject*> aAnchoredObjs; 447 { 448 const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() ); 449 ASSERT( pContact, 450 "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." ); 451 pContact->GetAnchoredObjs( aAnchoredObjs ); 452 } 453 454 // check, if 'repeated' objects exists. 455 if ( aAnchoredObjs.size() > 1 ) 456 { 457 SdrPage* pDrawPage = GetModel()->GetPage( 0 ); 458 459 // move 'repeated' ones to the same order number as the already moved one. 460 sal_uInt32 nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum(); 461 while ( !aAnchoredObjs.empty() ) 462 { 463 SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back(); 464 if ( pAnchoredObj != &_rMovedAnchoredObj ) 465 { 466 pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(), 467 nNewPos ); 468 pDrawPage->RecalcObjOrdNums(); 469 // adjustments for accessibility API 470 if ( pAnchoredObj->ISA(SwFlyFrm) ) 471 { 472 const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj); 473 rImp.DisposeAccessibleFrm( pTmpFlyFrm ); 474 rImp.AddAccessibleFrm( pTmpFlyFrm ); 475 } 476 else 477 { 478 rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() ); 479 rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() ); 480 } 481 } 482 aAnchoredObjs.pop_back(); 483 } 484 485 // move 'repeated' ones of 'child' objects 486 for ( std::vector<SdrObject*>::const_iterator aObjIter = _rMovedChildObjs.begin(); 487 aObjIter != _rMovedChildObjs.end(); ++aObjIter ) 488 { 489 SdrObject* pChildObj = (*aObjIter); 490 { 491 const SwContact* pContact = ::GetUserCall( pChildObj ); 492 ASSERT( pContact, 493 "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." ); 494 pContact->GetAnchoredObjs( aAnchoredObjs ); 495 } 496 // move 'repeated' ones to the same order number as the already moved one. 497 const sal_uInt32 nTmpNewPos = pChildObj->GetOrdNum(); 498 while ( !aAnchoredObjs.empty() ) 499 { 500 SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back(); 501 if ( pAnchoredObj->GetDrawObj() != pChildObj ) 502 { 503 pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(), 504 nTmpNewPos ); 505 pDrawPage->RecalcObjOrdNums(); 506 // adjustments for accessibility API 507 if ( pAnchoredObj->ISA(SwFlyFrm) ) 508 { 509 const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj); 510 rImp.DisposeAccessibleFrm( pTmpFlyFrm ); 511 rImp.AddAccessibleFrm( pTmpFlyFrm ); 512 } 513 else 514 { 515 rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() ); 516 rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() ); 517 } 518 } 519 aAnchoredObjs.pop_back(); 520 } 521 } 522 } 523 } 524 525 // --> OD 2004-08-20 #110810# - adjustment and re-factoring of method 526 void SwDrawView::ObjOrderChanged( SdrObject* pObj, sal_uLong nOldPos, 527 sal_uLong nNewPos ) 528 { 529 // --> OD 2004-08-17 #110810# - nothing to do for group members 530 if ( pObj->GetUpGroup() ) 531 { 532 return; 533 } 534 // <-- 535 536 // determine drawing page and assure that the order numbers are correct. 537 SdrPage* pDrawPage = GetModel()->GetPage( 0 ); 538 if ( pDrawPage->IsObjOrdNumsDirty() ) 539 pDrawPage->RecalcObjOrdNums(); 540 const sal_uInt32 nObjCount = pDrawPage->GetObjCount(); 541 542 SwAnchoredObject* pMovedAnchoredObj = 543 ::GetUserCall( pObj )->GetAnchoredObj( pObj ); 544 const SwFlyFrm* pParentAnchoredObj = 545 pMovedAnchoredObj->GetAnchorFrm()->FindFlyFrm(); 546 547 const bool bMovedForward = nOldPos < nNewPos; 548 549 // assure for a 'child' object, that it doesn't exceed the limits of its 'parent' 550 if ( pParentAnchoredObj ) 551 { 552 if ( bMovedForward ) 553 { 554 sal_uInt32 nMaxChildOrdNumWithoutMoved = 555 _GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() ); 556 if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 ) 557 { 558 // set position to the top of the 'child' object group 559 pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 ); 560 nNewPos = nMaxChildOrdNumWithoutMoved+1; 561 } 562 } 563 else 564 { 565 const sal_uInt32 nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum(); 566 if ( nNewPos < nParentOrdNum ) 567 { 568 // set position to the bottom of the 'child' object group 569 pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum ); 570 nNewPos = nParentOrdNum; 571 } 572 } 573 if ( pDrawPage->IsObjOrdNumsDirty() ) 574 pDrawPage->RecalcObjOrdNums(); 575 } 576 577 // Assure, that object isn't positioned between 'repeated' ones 578 if ( ( bMovedForward && nNewPos < nObjCount - 1 ) || 579 ( !bMovedForward && nNewPos > 0 ) ) 580 { 581 const SdrObject* pTmpObj = 582 pDrawPage->GetObj( bMovedForward ? nNewPos - 1 : nNewPos + 1 ); 583 if ( pTmpObj ) 584 { 585 sal_uInt32 nTmpNewPos( nNewPos ); 586 if ( bMovedForward ) 587 { 588 // move before the top 'repeated' object 589 const sal_uInt32 nTmpMaxOrdNum = 590 ::GetUserCall( pTmpObj )->GetMaxOrdNum(); 591 if ( nTmpMaxOrdNum > nNewPos ) 592 nTmpNewPos = nTmpMaxOrdNum; 593 } 594 else 595 { 596 // move behind the bottom 'repeated' object 597 const sal_uInt32 nTmpMinOrdNum = 598 ::GetUserCall( pTmpObj )->GetMinOrdNum(); 599 if ( nTmpMinOrdNum < nNewPos ) 600 nTmpNewPos = nTmpMinOrdNum; 601 } 602 if ( nTmpNewPos != nNewPos ) 603 { 604 pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos ); 605 nNewPos = nTmpNewPos; 606 pDrawPage->RecalcObjOrdNums(); 607 } 608 } 609 } 610 611 // On move forward, assure that object is moved before its own childs. 612 // Only Writer fly frames can have childs. 613 if ( pMovedAnchoredObj->ISA(SwFlyFrm) && 614 bMovedForward && nNewPos < nObjCount - 1 ) 615 { 616 sal_uInt32 nMaxChildOrdNum = 617 _GetMaxChildOrdNum( *(static_cast<const SwFlyFrm*>(pMovedAnchoredObj)) ); 618 if ( nNewPos < nMaxChildOrdNum ) 619 { 620 // determine position before the object before its top 'child' object 621 const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum ); 622 sal_uInt32 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum() + 1; 623 if ( nTmpNewPos >= nObjCount ) 624 { 625 --nTmpNewPos; 626 } 627 // assure, that determined position isn't between 'repeated' objects 628 pTmpObj = pDrawPage->GetObj( nTmpNewPos ); 629 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum(); 630 // apply new position 631 pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos ); 632 nNewPos = nTmpNewPos; 633 pDrawPage->RecalcObjOrdNums(); 634 } 635 } 636 637 // Assure, that object isn't positioned between nested objects 638 if ( ( bMovedForward && nNewPos < nObjCount - 1 ) || 639 ( !bMovedForward && nNewPos > 0 ) ) 640 { 641 sal_uInt32 nTmpNewPos( nNewPos ); 642 const SwFrmFmt* pParentFrmFmt = 643 pParentAnchoredObj ? &(pParentAnchoredObj->GetFrmFmt()) : 0L; 644 const SdrObject* pTmpObj = pDrawPage->GetObj( nNewPos + 1 ); 645 while ( pTmpObj ) 646 { 647 // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists. 648 // If object is anchored inside a invisible part of the document 649 // (e.g. page header, whose page style isn't applied, or hidden 650 // section), no anchor frame exists. 651 const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True ); 652 const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm 653 ? pTmpAnchorFrm->FindFlyFrm() : 0L; 654 // <-- 655 if ( pTmpParentObj && 656 &(pTmpParentObj->GetFrmFmt()) != pParentFrmFmt ) 657 { 658 if ( bMovedForward ) 659 { 660 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum(); 661 pTmpObj = pDrawPage->GetObj( nTmpNewPos + 1 ); 662 } 663 else 664 { 665 nTmpNewPos = ::GetUserCall( pTmpParentObj->GetDrawObj() ) 666 ->GetMinOrdNum(); 667 pTmpObj = pTmpParentObj->GetDrawObj(); 668 } 669 } 670 else 671 break; 672 } 673 if ( nTmpNewPos != nNewPos ) 674 { 675 pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos ); 676 nNewPos = nTmpNewPos; 677 pDrawPage->RecalcObjOrdNums(); 678 } 679 } 680 681 // setup collection of moved 'child' objects to move its 'repeated' objects. 682 std::vector< SdrObject* > aMovedChildObjs; 683 684 // move 'childs' accordingly 685 if ( pMovedAnchoredObj->ISA(SwFlyFrm) ) 686 { 687 const SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pMovedAnchoredObj); 688 689 // adjustments for accessibility API 690 rImp.DisposeAccessibleFrm( pFlyFrm ); 691 rImp.AddAccessibleFrm( pFlyFrm ); 692 693 const sal_uInt32 nChildNewPos = bMovedForward ? nNewPos : nNewPos+1; 694 sal_uInt32 i = bMovedForward ? nOldPos : nObjCount-1; 695 do 696 { 697 SdrObject* pTmpObj = pDrawPage->GetObj( i ); 698 if ( pTmpObj == pObj ) 699 break; 700 701 // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists. 702 // If object is anchored inside a invisible part of the document 703 // (e.g. page header, whose page style isn't applied, or hidden 704 // section), no anchor frame exists. 705 const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True ); 706 const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm 707 ? pTmpAnchorFrm->FindFlyFrm() : 0L; 708 // <-- 709 if ( pTmpParentObj && 710 ( ( pTmpParentObj == pFlyFrm ) || 711 ( pFlyFrm->IsUpperOf( *pTmpParentObj ) ) ) ) 712 { 713 // move child object., 714 pDrawPage->SetObjectOrdNum( i, nChildNewPos ); 715 pDrawPage->RecalcObjOrdNums(); 716 // collect 'child' object 717 aMovedChildObjs.push_back( pTmpObj ); 718 // adjustments for accessibility API 719 if ( pTmpObj->ISA(SwVirtFlyDrawObj) ) 720 { 721 const SwFlyFrm *pTmpFlyFrm = 722 static_cast<SwVirtFlyDrawObj*>(pTmpObj)->GetFlyFrm(); 723 rImp.DisposeAccessibleFrm( pTmpFlyFrm ); 724 rImp.AddAccessibleFrm( pTmpFlyFrm ); 725 } 726 else 727 { 728 rImp.DisposeAccessibleObj( pTmpObj ); 729 rImp.AddAccessibleObj( pTmpObj ); 730 } 731 } 732 else 733 { 734 // adjust loop counter 735 if ( bMovedForward ) 736 ++i; 737 else if ( !bMovedForward && i > 0 ) 738 --i; 739 } 740 741 } while ( ( bMovedForward && i < ( nObjCount - aMovedChildObjs.size() ) ) || 742 ( !bMovedForward && i > ( nNewPos + aMovedChildObjs.size() ) ) ); 743 } 744 else 745 { 746 // adjustments for accessibility API 747 rImp.DisposeAccessibleObj( pObj ); 748 rImp.AddAccessibleObj( pObj ); 749 } 750 751 _MoveRepeatedObjs( *pMovedAnchoredObj, aMovedChildObjs ); 752 } 753 // <-- 754 755 /************************************************************************* 756 |* 757 |* SwDrawView::TakeDragLimit() 758 |* 759 |* Ersterstellung AMA 26. Apr. 96 760 |* Letzte Aenderung MA 03. May. 96 761 |* 762 *************************************************************************/ 763 764 765 sal_Bool SwDrawView::TakeDragLimit( SdrDragMode eMode, 766 Rectangle& rRect ) const 767 { 768 const SdrMarkList &rMrkList = GetMarkedObjectList(); 769 sal_Bool bRet = sal_False; 770 if( 1 == rMrkList.GetMarkCount() ) 771 { 772 const SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); 773 SwRect aRect; 774 if( ::CalcClipRect( pObj, aRect, eMode == SDRDRAG_MOVE ) ) 775 { 776 rRect = aRect.SVRect(); 777 bRet = sal_True; 778 } 779 } 780 return bRet; 781 } 782 783 /************************************************************************* 784 |* 785 |* SwDrawView::CalcAnchor() 786 |* 787 |* Ersterstellung MA 13. Jan. 95 788 |* Letzte Aenderung MA 08. Nov. 96 789 |* 790 *************************************************************************/ 791 792 793 const SwFrm* SwDrawView::CalcAnchor() 794 { 795 const SdrMarkList &rMrkList = GetMarkedObjectList(); 796 if ( rMrkList.GetMarkCount() != 1 ) 797 return NULL; 798 799 SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); 800 801 //Fuer Absatzgebundene Objekte suchen, andernfalls einfach nur 802 //der aktuelle Anker. Nur suchen wenn wir gerade draggen. 803 const SwFrm* pAnch; 804 Rectangle aMyRect; 805 const sal_Bool bFly = pObj->ISA(SwVirtFlyDrawObj); 806 if ( bFly ) 807 { 808 pAnch = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetAnchorFrm(); 809 aMyRect = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->Frm().SVRect(); 810 } 811 else 812 { 813 SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj); 814 // OD 17.06.2003 #108784# - determine correct anchor position for 815 // 'virtual' drawing objects. 816 // OD 2004-03-25 #i26791# 817 pAnch = pC->GetAnchorFrm( pObj ); 818 if( !pAnch ) 819 { 820 pC->ConnectToLayout(); 821 // OD 17.06.2003 #108784# - determine correct anchor position for 822 // 'virtual' drawing objects. 823 // OD 2004-03-25 #i26791# 824 pAnch = pC->GetAnchorFrm( pObj ); 825 } 826 aMyRect = pObj->GetSnapRect(); 827 } 828 829 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 830 const sal_Bool bTopRight = pAnch && ( ( pAnch->IsVertical() && 831 !pAnch->IsVertLR() ) || 832 pAnch->IsRightToLeft() ); 833 const Point aMyPt = bTopRight ? aMyRect.TopRight() : aMyRect.TopLeft(); 834 835 Point aPt; 836 if ( IsAction() ) 837 { 838 if ( !TakeDragObjAnchorPos( aPt, bTopRight ) ) 839 return NULL; 840 } 841 else 842 { 843 Rectangle aRect = pObj->GetSnapRect(); 844 aPt = bTopRight ? aRect.TopRight() : aRect.TopLeft(); 845 } 846 847 if ( aPt != aMyPt ) 848 { 849 if ( pAnch->IsCntntFrm() ) 850 { 851 // OD 26.06.2003 #108784# - allow drawing objects in header/footer, 852 // but exclude control objects. 853 bool bBodyOnly = CheckControlLayer( pObj ); 854 pAnch = ::FindAnchor( (SwCntntFrm*)pAnch, aPt, bBodyOnly ); 855 } 856 else if ( !bFly ) 857 { 858 const SwRect aRect( aPt.X(), aPt.Y(), 1, 1 ); 859 860 SwDrawContact* pContact = (SwDrawContact*)GetUserCall(pObj); 861 if ( pContact->GetAnchorFrm( pObj ) && 862 pContact->GetAnchorFrm( pObj )->IsPageFrm() ) 863 pAnch = pContact->GetPageFrm(); 864 else 865 pAnch = pContact->FindPage( aRect ); 866 } 867 } 868 if( pAnch && !pAnch->IsProtected() ) 869 aAnchorPoint = pAnch->GetFrmAnchorPos( ::HasWrap( pObj ) ); 870 else 871 pAnch = 0; 872 return pAnch; 873 } 874 875 /************************************************************************* 876 |* 877 |* SwDrawView::ShowDragXor(), HideDragXor() 878 |* 879 |* Ersterstellung MA 17. Jan. 95 880 |* Letzte Aenderung MA 27. Jan. 95 881 |* 882 *************************************************************************/ 883 884 885 void SwDrawView::ShowDragAnchor() 886 { 887 SdrHdl* pHdl = aHdl.GetHdl(HDL_ANCHOR); 888 if ( ! pHdl ) 889 pHdl = aHdl.GetHdl(HDL_ANCHOR_TR); 890 891 if(pHdl) 892 { 893 CalcAnchor(); 894 pHdl->SetPos(aAnchorPoint); 895 //OLMRefreshAllIAOManagers(); 896 } 897 } 898 899 /************************************************************************* 900 |* 901 |* SwDrawView::MarkListHasChanged() 902 |* 903 |* Ersterstellung OM 02. Feb. 95 904 |* Letzte Aenderung OM 07. Jul. 95 905 |* 906 *************************************************************************/ 907 908 909 void SwDrawView::MarkListHasChanged() 910 { 911 Imp().GetShell()->DrawSelChanged(); 912 FmFormView::MarkListHasChanged(); 913 } 914 915 // #i7672# 916 void SwDrawView::ModelHasChanged() 917 { 918 // The ModelHasChanged() call in DrawingLayer also updates 919 // a eventually active text edit view (OutlinerView). This also leads 920 // to newly setting the background color for that edit view. Thus, 921 // this method rescues the current background color if a OutlinerView 922 // exists and re-establishes it then. To be more safe, the OutlinerView 923 // will be fetched again (maybe textedit has ended). 924 OutlinerView* pView = GetTextEditOutlinerView(); 925 Color aBackColor; 926 sal_Bool bColorWasSaved(sal_False); 927 928 if(pView) 929 { 930 aBackColor = pView->GetBackgroundColor(); 931 bColorWasSaved = sal_True; 932 } 933 934 // call parent 935 FmFormView::ModelHasChanged(); 936 937 if(bColorWasSaved) 938 { 939 pView = GetTextEditOutlinerView(); 940 941 if(pView) 942 { 943 pView->SetBackgroundColor(aBackColor); 944 } 945 } 946 } 947 948 void SwDrawView::MakeVisible( const Rectangle &rRect, Window & ) 949 { 950 ASSERT( rImp.GetShell()->GetWin(), "MakeVisible, unknown Window"); 951 rImp.GetShell()->MakeVisible( SwRect( rRect ) ); 952 } 953 954 void SwDrawView::CheckPossibilities() 955 { 956 FmFormView::CheckPossibilities(); 957 958 //Zusaetzlich zu den bestehenden Flags der Objekte selbst, die von der 959 //DrawingEngine ausgewertet werden, koennen weitere Umstaende zu einem 960 //Schutz fuehren. 961 //Objekte, die in Rahmen verankert sind, muessen genau dann geschuetzt 962 //sein, wenn der Inhalt des Rahmens geschuetzt ist. 963 //OLE-Objekte konnen selbst einen Resize-Schutz wuenschen (StarMath) 964 965 const SdrMarkList &rMrkList = GetMarkedObjectList(); 966 sal_Bool bProtect = sal_False, 967 bSzProtect = sal_False; 968 for ( sal_uInt16 i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i ) 969 { 970 const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); 971 const SwFrm *pFrm = NULL; 972 if ( pObj->ISA(SwVirtFlyDrawObj) ) 973 { 974 const SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); 975 if ( pFly ) 976 { 977 pFrm = pFly->GetAnchorFrm(); 978 if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() ) 979 { 980 SwOLENode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode(); 981 if ( pNd ) 982 { 983 uno::Reference < embed::XEmbeddedObject > xObj = pNd->GetOLEObj().GetOleRef(); 984 if ( xObj.is() ) 985 { 986 // --> OD 2004-08-16 #110810# - improvement for 987 // the future, when more than one Writer fly frame 988 // can be selected. 989 990 // TODO/LATER: retrieve Aspect - from where?! 991 bSzProtect |= ( embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) ? sal_True : sal_False; 992 993 // <-- 994 995 // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated 996 SwDoc* pDoc = Imp().GetShell()->GetDoc(); 997 const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() ) 998 && FLY_AS_CHAR == pFly->GetFmt()->GetAnchor().GetAnchorId() 999 && pDoc->get( IDocumentSettingAccess::MATH_BASELINE_ALIGNMENT ); 1000 if (bProtectMathPos) 1001 bMoveProtect = true; 1002 } 1003 } 1004 } 1005 } 1006 } 1007 else 1008 { 1009 SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj); 1010 if ( pC ) 1011 pFrm = pC->GetAnchorFrm( pObj ); 1012 } 1013 if ( pFrm ) 1014 bProtect = pFrm->IsProtected(); //Rahmen, Bereiche usw. 1015 { 1016 SwFrmFmt* pFrmFmt( ::FindFrmFmt( const_cast<SdrObject*>(pObj) ) ); 1017 if ( !pFrmFmt ) 1018 { 1019 ASSERT( false, 1020 "<SwDrawView::CheckPossibilities()> - missing frame format" ); 1021 bProtect = sal_True; 1022 } 1023 else if ((FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId()) && 1024 rMrkList.GetMarkCount() > 1 ) 1025 { 1026 bProtect = sal_True; 1027 } 1028 } 1029 } 1030 bMoveProtect |= bProtect; 1031 bResizeProtect |= bProtect | bSzProtect; 1032 } 1033 1034 /** replace marked <SwDrawVirtObj>-objects by its reference object for delete 1035 marked objects. 1036 1037 OD 18.06.2003 #108784# 1038 1039 @author OD 1040 */ 1041 void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView ) 1042 { 1043 SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView(); 1044 const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList(); 1045 1046 if( rMarkList.GetMarkCount() ) 1047 { 1048 // collect marked objects in a local data structure 1049 std::vector<SdrObject*> aMarkedObjs; 1050 for( sal_uInt32 i = 0; i < rMarkList.GetMarkCount(); ++i ) 1051 { 1052 SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj(); 1053 aMarkedObjs.push_back( pMarkedObj ); 1054 } 1055 // unmark all objects 1056 _rMarkView.UnmarkAllObj(); 1057 // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its 1058 // reference object. 1059 while ( !aMarkedObjs.empty() ) 1060 { 1061 SdrObject* pMarkObj = aMarkedObjs.back(); 1062 if ( pMarkObj->ISA(SwDrawVirtObj) ) 1063 { 1064 SdrObject* pRefObj = &(static_cast<SwDrawVirtObj*>(pMarkObj)->ReferencedObj()); 1065 if ( !_rMarkView.IsObjMarked( pRefObj ) ) 1066 { 1067 _rMarkView.MarkObj( pRefObj, pDrawPageView ); 1068 } 1069 } 1070 else 1071 { 1072 _rMarkView.MarkObj( pMarkObj, pDrawPageView ); 1073 } 1074 1075 aMarkedObjs.pop_back(); 1076 } 1077 // sort marked list in order to assure consistent state in drawing layer 1078 _rMarkView.SortMarkedObjects(); 1079 } 1080 } 1081 1082 void SwDrawView::DeleteMarked() 1083 { 1084 SwDoc* pDoc = Imp().GetShell()->GetDoc(); 1085 SwRootFrm *pTmpRoot = pDoc->GetCurrentLayout();//swmod 080317 1086 if ( pTmpRoot ) 1087 pTmpRoot->StartAllAction(); 1088 pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); 1089 // OD 18.06.2003 #108784# - replace marked <SwDrawVirtObj>-objects by its 1090 // reference objects. 1091 { 1092 SdrPageView* pDrawPageView = rImp.GetPageView(); 1093 if ( pDrawPageView ) 1094 { 1095 SdrMarkView* pMarkView = PTR_CAST( SdrMarkView, &(pDrawPageView->GetView()) ); 1096 if ( pMarkView ) 1097 { 1098 ReplaceMarkedDrawVirtObjs( *pMarkView ); 1099 } 1100 } 1101 } 1102 if ( pDoc->DeleteSelection( *this ) ) 1103 { 1104 FmFormView::DeleteMarked(); 1105 ::FrameNotify( Imp().GetShell(), FLY_DRAG_END ); 1106 } 1107 pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL); 1108 if( pTmpRoot ) 1109 pTmpRoot->EndAllAction(); //swmod 080218 1110 } 1111 1112