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