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