1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <editeng/protitem.hxx>
22 #include <svx/svdpagv.hxx>
23 #include <svx/fmmodel.hxx>
24 #include <sot/exchange.hxx>
25 #include <svx/sdrundomanager.hxx>
26 #include <tools/globname.hxx>
27 #include <editeng/outliner.hxx>
28 #include <com/sun/star/embed/EmbedMisc.hpp>
30 #include <swtypes.hxx>
31 #include <pagefrm.hxx>
32 #include <rootfrm.hxx>
34 #include <notxtfrm.hxx>
37 #include <dflyobj.hxx>
38 #include <dcontact.hxx>
39 #include <textboxhelper.hxx>
42 #include <viewimp.hxx>
49 #include <fmtanchr.hxx>
50 #include <shellres.hxx>
51 #include <IDocumentUndoRedo.hxx>
52 #include <DocumentSettingManager.hxx>
53 #include <IDocumentLayoutAccess.hxx>
55 #include <com/sun/star/embed/Aspects.hpp>
59 #include <sortedobjs.hxx>
60 #include <flyfrms.hxx>
61 #include <UndoManager.hxx>
63 using namespace com::sun::star
;
65 class SwSdrHdl
: public SdrHdl
68 SwSdrHdl(const Point
& rPnt
, bool bTopRight
) :
69 SdrHdl( rPnt
, bTopRight
? SdrHdlKind::Anchor_TR
: SdrHdlKind::Anchor
) {}
70 virtual bool IsFocusHdl() const override
;
73 bool SwSdrHdl::IsFocusHdl() const
75 if( SdrHdlKind::Anchor
== eKind
|| SdrHdlKind::Anchor_TR
== eKind
)
77 return SdrHdl::IsFocusHdl();
80 static const SwFrame
*lcl_FindAnchor( const SdrObject
*pObj
, bool bAll
)
82 const SwVirtFlyDrawObj
*pVirt
= dynamic_cast< const SwVirtFlyDrawObj
*>( pObj
) != nullptr ?
83 static_cast<const SwVirtFlyDrawObj
*>(pObj
) : nullptr;
86 if ( bAll
|| !pVirt
->GetFlyFrame()->IsFlyInContentFrame() )
87 return pVirt
->GetFlyFrame()->GetAnchorFrame();
91 const SwDrawContact
*pCont
= static_cast<const SwDrawContact
*>(GetUserCall(pObj
));
93 return pCont
->GetAnchorFrame( pObj
);
98 SwDrawView::SwDrawView(
100 FmFormModel
& rFmFormModel
,
101 OutputDevice
* pOutDev
)
102 : FmFormView(rFmFormModel
, pOutDev
),
105 SetPageVisible( false );
106 SetBordVisible( false );
107 SetGridVisible( false );
108 SetHlplVisible( false );
109 SetGlueVisible( false );
110 SetFrameDragSingles();
113 EnableExtendedKeyInputDispatcher( false );
114 EnableExtendedMouseEventDispatcher( false );
116 SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );
118 SetPrintPreview( rI
.GetShell()->IsPreview() );
120 // #i73602# Use default from the configuration
121 SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Writer());
123 // #i74769#, #i75172# Use default from the configuration
124 SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Writer());
128 bool SwDrawView::IsAntiAliasing() const
130 return getOptionsDrawinglayer().IsAntiAliasing();
133 SdrObject
* impLocalHitCorrection(SdrObject
* pRetval
, const Point
& rPnt
, sal_uInt16 nTol
, const SdrMarkList
&rMrkList
)
137 // the old method forced back to outer bounds test when nTol == 0, so
138 // do not try to correct when nTol is not set (used from HelpContent)
142 // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
143 // the SdrObject-specific CheckHit implementations are now replaced with primitives and
144 // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
145 // detect if object is selected) are no longer valid.
146 // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
147 // implementation reduced this excluding the inner bound when the object was not selected.
148 SwVirtFlyDrawObj
* pSwVirtFlyDrawObj
= dynamic_cast< SwVirtFlyDrawObj
* >(pRetval
);
150 if(pSwVirtFlyDrawObj
)
152 if(pSwVirtFlyDrawObj
->GetFlyFrame()->Lower() && pSwVirtFlyDrawObj
->GetFlyFrame()->Lower()->IsNoTextFrame())
154 // the old method used IsNoTextFrame (should be for SW's own OLE and
155 // graphic's) to accept hit only based on outer bounds; nothing to do
159 // check if the object is selected in this view
160 const size_t nMarkCount(rMrkList
.GetMarkCount());
161 bool bSelected(false);
163 for(size_t a
= 0; !bSelected
&& a
< nMarkCount
; ++a
)
165 if(pSwVirtFlyDrawObj
== rMrkList
.GetMark(a
)->GetMarkedSdrObj())
173 // when not selected, the object is not hit when hit position is inside
174 // inner range. Get and shrink inner range
175 basegfx::B2DRange
aInnerBound(pSwVirtFlyDrawObj
->getInnerBound());
177 aInnerBound
.grow(-1.0 * nTol
);
179 if(aInnerBound
.isInside(basegfx::B2DPoint(rPnt
.X(), rPnt
.Y())))
192 SdrObject
* SwDrawView::CheckSingleSdrObjectHit(const Point
& rPnt
, sal_uInt16 nTol
, SdrObject
* pObj
, SdrPageView
* pPV
, SdrSearchOptions nOptions
, const SdrLayerIDSet
* pMVisLay
) const
195 SdrObject
* pRetval
= FmFormView::CheckSingleSdrObjectHit(rPnt
, nTol
, pObj
, pPV
, nOptions
, pMVisLay
);
199 // override to allow extra handling when picking SwVirtFlyDrawObj's
200 pRetval
= impLocalHitCorrection(pRetval
, rPnt
, nTol
, GetMarkedObjectList());
206 /// Gets called every time the handles need to be build
207 void SwDrawView::AddCustomHdl()
209 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
211 if(rMrkList
.GetMarkCount() != 1 || !GetUserCall(rMrkList
.GetMark( 0 )->GetMarkedSdrObj()))
214 SdrObject
*pObj
= rMrkList
.GetMark(0)->GetMarkedSdrObj();
216 SwFrameFormat
* pFrameFormat( ::FindFrameFormat( pObj
) );
219 OSL_FAIL( "<SwDrawView::AddCustomHdl()> - missing frame format!" );
222 const SwFormatAnchor
&rAnchor
= pFrameFormat
->GetAnchor();
224 if (RndStdIds::FLY_AS_CHAR
== rAnchor
.GetAnchorId())
227 const SwFrame
* pAnch
;
228 if(nullptr == (pAnch
= CalcAnchor()))
231 Point
aPos(m_aAnchorPoint
);
233 if ( RndStdIds::FLY_AT_CHAR
== rAnchor
.GetAnchorId() )
235 // #i28701# - use last character rectangle saved at object
236 // in order to avoid a format of the anchor frame
237 SwAnchoredObject
* pAnchoredObj
= ::GetUserCall( pObj
)->GetAnchoredObj( pObj
);
238 SwRect aAutoPos
= pAnchoredObj
->GetLastCharRect();
239 if ( aAutoPos
.Height() )
241 aPos
= aAutoPos
.Pos();
245 // add anchor handle:
246 maHdlList
.AddHdl( new SwSdrHdl( aPos
, ( pAnch
->IsVertical() && !pAnch
->IsVertLR() ) ||
247 pAnch
->IsRightToLeft() ) );
250 SdrObject
* SwDrawView::GetMaxToTopObj( SdrObject
* pObj
) const
252 if ( GetUserCall(pObj
) )
254 const SwFrame
*pAnch
= ::lcl_FindAnchor( pObj
, false );
257 //The topmost Obj within the anchor must not be overtaken.
258 const SwFlyFrame
*pFly
= pAnch
->FindFlyFrame();
261 const SwPageFrame
*pPage
= pFly
->FindPageFrame();
262 if ( pPage
->GetSortedObjs() )
265 for (SwAnchoredObject
* i
: *pPage
->GetSortedObjs())
267 const SdrObject
*pO
= i
->GetDrawObj();
269 if ( pO
->GetOrdNumDirect() > nOrdNum
)
271 const SwFrame
*pTmpAnch
= ::lcl_FindAnchor( pO
, false );
272 if ( pFly
->IsAnLower( pTmpAnch
) )
274 nOrdNum
= pO
->GetOrdNumDirect();
280 SdrPage
*pTmpPage
= GetModel()->GetPage( 0 );
282 if ( nOrdNum
< pTmpPage
->GetObjCount() )
284 return pTmpPage
->GetObj( nOrdNum
);
294 SdrObject
* SwDrawView::GetMaxToBtmObj(SdrObject
* pObj
) const
296 if ( GetUserCall(pObj
) )
298 const SwFrame
*pAnch
= ::lcl_FindAnchor( pObj
, false );
301 //The Fly of the anchor must not be "flying under".
302 const SwFlyFrame
*pFly
= pAnch
->FindFlyFrame();
305 SdrObject
*pRet
= const_cast<SdrObject
*>(static_cast<SdrObject
const *>(pFly
->GetVirtDrawObj()));
306 return pRet
!= pObj
? pRet
: nullptr;
313 /// determine maximal order number for a 'child' object of given 'parent' object
314 sal_uInt32
SwDrawView::GetMaxChildOrdNum( const SwFlyFrame
& _rParentObj
,
315 const SdrObject
* _pExclChildObj
)
317 sal_uInt32 nMaxChildOrdNum
= _rParentObj
.GetDrawObj()->GetOrdNum();
319 const SdrPage
* pDrawPage
= _rParentObj
.GetDrawObj()->GetPage();
320 OSL_ENSURE( pDrawPage
,
321 "<SwDrawView::GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" );
323 const size_t nObjCount
= pDrawPage
->GetObjCount();
324 for ( size_t i
= nObjCount
-1; i
> _rParentObj
.GetDrawObj()->GetOrdNum() ; --i
)
326 const SdrObject
* pObj
= pDrawPage
->GetObj( i
);
328 // Don't consider 'child' object <_pExclChildObj>
329 if ( pObj
== _pExclChildObj
)
334 if ( pObj
->GetOrdNum() > nMaxChildOrdNum
&&
335 _rParentObj
.IsAnLower( lcl_FindAnchor( pObj
, true ) ) )
337 nMaxChildOrdNum
= pObj
->GetOrdNum();
342 return nMaxChildOrdNum
;
345 /// method to move 'repeated' objects of the given moved object to the according level
346 void SwDrawView::MoveRepeatedObjs( const SwAnchoredObject
& _rMovedAnchoredObj
,
347 const std::vector
<SdrObject
*>& _rMovedChildObjs
) const
349 // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
350 std::vector
<SwAnchoredObject
*> aAnchoredObjs
;
352 const SwContact
* pContact
= ::GetUserCall( _rMovedAnchoredObj
.GetDrawObj() );
353 assert(pContact
&& "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.");
354 pContact
->GetAnchoredObjs( aAnchoredObjs
);
357 // check, if 'repeated' objects exists.
358 if ( aAnchoredObjs
.size() > 1 )
360 SdrPage
* pDrawPage
= GetModel()->GetPage( 0 );
362 // move 'repeated' ones to the same order number as the already moved one.
363 const size_t nNewPos
= _rMovedAnchoredObj
.GetDrawObj()->GetOrdNum();
364 while ( !aAnchoredObjs
.empty() )
366 SwAnchoredObject
* pAnchoredObj
= aAnchoredObjs
.back();
367 if ( pAnchoredObj
!= &_rMovedAnchoredObj
)
369 pDrawPage
->SetObjectOrdNum( pAnchoredObj
->GetDrawObj()->GetOrdNum(),
371 pDrawPage
->RecalcObjOrdNums();
372 // adjustments for accessibility API
373 if ( dynamic_cast< const SwFlyFrame
*>( pAnchoredObj
) != nullptr )
375 const SwFlyFrame
*pTmpFlyFrame
= static_cast<SwFlyFrame
*>(pAnchoredObj
);
376 m_rImp
.DisposeAccessibleFrame( pTmpFlyFrame
);
377 m_rImp
.AddAccessibleFrame( pTmpFlyFrame
);
381 m_rImp
.DisposeAccessibleObj(pAnchoredObj
->GetDrawObj(), true);
382 m_rImp
.AddAccessibleObj( pAnchoredObj
->GetDrawObj() );
385 aAnchoredObjs
.pop_back();
388 // move 'repeated' ones of 'child' objects
389 for ( std::vector
<SdrObject
*>::const_iterator aObjIter
= _rMovedChildObjs
.begin();
390 aObjIter
!= _rMovedChildObjs
.end(); ++aObjIter
)
392 SdrObject
* pChildObj
= (*aObjIter
);
394 const SwContact
* pContact
= ::GetUserCall( pChildObj
);
395 assert(pContact
&& "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.");
396 pContact
->GetAnchoredObjs( aAnchoredObjs
);
398 // move 'repeated' ones to the same order number as the already moved one.
399 const size_t nTmpNewPos
= pChildObj
->GetOrdNum();
400 while ( !aAnchoredObjs
.empty() )
402 SwAnchoredObject
* pAnchoredObj
= aAnchoredObjs
.back();
403 if ( pAnchoredObj
->GetDrawObj() != pChildObj
)
405 pDrawPage
->SetObjectOrdNum( pAnchoredObj
->GetDrawObj()->GetOrdNum(),
407 pDrawPage
->RecalcObjOrdNums();
408 // adjustments for accessibility API
409 if ( dynamic_cast< const SwFlyFrame
*>( pAnchoredObj
) != nullptr )
411 const SwFlyFrame
*pTmpFlyFrame
= static_cast<SwFlyFrame
*>(pAnchoredObj
);
412 m_rImp
.DisposeAccessibleFrame( pTmpFlyFrame
);
413 m_rImp
.AddAccessibleFrame( pTmpFlyFrame
);
417 m_rImp
.DisposeAccessibleObj(pAnchoredObj
->GetDrawObj(), true);
418 m_rImp
.AddAccessibleObj( pAnchoredObj
->GetDrawObj() );
421 aAnchoredObjs
.pop_back();
427 // --> adjustment and re-factoring of method
428 void SwDrawView::ObjOrderChanged( SdrObject
* pObj
, size_t nOldPos
,
431 // nothing to do for group members
432 if ( pObj
->GetUpGroup() )
437 // determine drawing page and assure that the order numbers are correct.
438 SdrPage
* pDrawPage
= GetModel()->GetPage( 0 );
439 if ( pDrawPage
->IsObjOrdNumsDirty() )
440 pDrawPage
->RecalcObjOrdNums();
441 const size_t nObjCount
= pDrawPage
->GetObjCount();
443 SwAnchoredObject
* pMovedAnchoredObj
=
444 ::GetUserCall( pObj
)->GetAnchoredObj( pObj
);
445 const SwFlyFrame
* pParentAnchoredObj
=
446 pMovedAnchoredObj
->GetAnchorFrame()->FindFlyFrame();
448 const bool bMovedForward
= nOldPos
< nNewPos
;
450 // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
451 if ( pParentAnchoredObj
)
455 const size_t nMaxChildOrdNumWithoutMoved
=
456 GetMaxChildOrdNum( *pParentAnchoredObj
, pMovedAnchoredObj
->GetDrawObj() );
457 if ( nNewPos
> nMaxChildOrdNumWithoutMoved
+1 )
459 // set position to the top of the 'child' object group
460 pDrawPage
->SetObjectOrdNum( nNewPos
, nMaxChildOrdNumWithoutMoved
+1 );
461 nNewPos
= nMaxChildOrdNumWithoutMoved
+1;
466 const size_t nParentOrdNum
= pParentAnchoredObj
->GetDrawObj()->GetOrdNum();
467 if ( nNewPos
< nParentOrdNum
)
469 // set position to the bottom of the 'child' object group
470 pDrawPage
->SetObjectOrdNum( nNewPos
, nParentOrdNum
);
471 nNewPos
= nParentOrdNum
;
474 if ( pDrawPage
->IsObjOrdNumsDirty() )
475 pDrawPage
->RecalcObjOrdNums();
478 // Assure, that object isn't positioned between 'repeated' ones
479 if ( ( bMovedForward
&& nNewPos
< nObjCount
- 1 ) ||
480 ( !bMovedForward
&& nNewPos
> 0 ) )
482 const SdrObject
* pTmpObj
=
483 pDrawPage
->GetObj( bMovedForward
? nNewPos
- 1 : nNewPos
+ 1 );
486 size_t nTmpNewPos( nNewPos
);
489 // move before the top 'repeated' object
490 const sal_uInt32 nTmpMaxOrdNum
=
491 ::GetUserCall( pTmpObj
)->GetMaxOrdNum();
492 if ( nTmpMaxOrdNum
> nNewPos
)
493 nTmpNewPos
= nTmpMaxOrdNum
;
497 // move behind the bottom 'repeated' object
498 const sal_uInt32 nTmpMinOrdNum
=
499 ::GetUserCall( pTmpObj
)->GetMinOrdNum();
500 if ( nTmpMinOrdNum
< nNewPos
)
501 nTmpNewPos
= nTmpMinOrdNum
;
503 if ( nTmpNewPos
!= nNewPos
)
505 pDrawPage
->SetObjectOrdNum( nNewPos
, nTmpNewPos
);
506 nNewPos
= nTmpNewPos
;
507 pDrawPage
->RecalcObjOrdNums();
512 // On move forward, assure that object is moved before its own children.
513 // Only Writer fly frames can have children.
514 if ( dynamic_cast< const SwFlyFrame
*>( pMovedAnchoredObj
) != nullptr &&
515 bMovedForward
&& nNewPos
< nObjCount
- 1 )
517 sal_uInt32 nMaxChildOrdNum
=
518 GetMaxChildOrdNum( *static_cast<const SwFlyFrame
*>(pMovedAnchoredObj
) );
519 if ( nNewPos
< nMaxChildOrdNum
)
521 // determine position before the object before its top 'child' object
522 const SdrObject
* pTmpObj
= pDrawPage
->GetObj( nMaxChildOrdNum
);
523 size_t nTmpNewPos
= ::GetUserCall( pTmpObj
)->GetMaxOrdNum() + 1;
524 if ( nTmpNewPos
>= nObjCount
)
528 // assure, that determined position isn't between 'repeated' objects
529 pTmpObj
= pDrawPage
->GetObj( nTmpNewPos
);
530 nTmpNewPos
= ::GetUserCall( pTmpObj
)->GetMaxOrdNum();
531 // apply new position
532 pDrawPage
->SetObjectOrdNum( nNewPos
, nTmpNewPos
);
533 nNewPos
= nTmpNewPos
;
534 pDrawPage
->RecalcObjOrdNums();
538 // Assure, that object isn't positioned between nested objects
539 if ( ( bMovedForward
&& nNewPos
< nObjCount
- 1 ) ||
540 ( !bMovedForward
&& nNewPos
> 0 ) )
542 size_t nTmpNewPos( nNewPos
);
543 const SwFrameFormat
* pParentFrameFormat
=
544 pParentAnchoredObj
? &(pParentAnchoredObj
->GetFrameFormat()) : nullptr;
545 const SdrObject
* pTmpObj
= pDrawPage
->GetObj( nNewPos
+ 1 );
548 // #i38563# - assure, that anchor frame exists.
549 // If object is anchored inside a invisible part of the document
550 // (e.g. page header, whose page style isn't applied, or hidden
551 // section), no anchor frame exists.
552 const SwFrame
* pTmpAnchorFrame
= lcl_FindAnchor( pTmpObj
, true );
553 const SwFlyFrame
* pTmpParentObj
= pTmpAnchorFrame
554 ? pTmpAnchorFrame
->FindFlyFrame() : nullptr;
555 if ( pTmpParentObj
&&
556 &(pTmpParentObj
->GetFrameFormat()) != pParentFrameFormat
)
560 nTmpNewPos
= ::GetUserCall( pTmpObj
)->GetMaxOrdNum();
561 pTmpObj
= pDrawPage
->GetObj( nTmpNewPos
+ 1 );
565 nTmpNewPos
= ::GetUserCall( pTmpParentObj
->GetDrawObj() )
567 pTmpObj
= pTmpParentObj
->GetDrawObj();
573 if ( nTmpNewPos
!= nNewPos
)
575 pDrawPage
->SetObjectOrdNum( nNewPos
, nTmpNewPos
);
576 nNewPos
= nTmpNewPos
;
577 pDrawPage
->RecalcObjOrdNums();
581 // setup collection of moved 'child' objects to move its 'repeated' objects.
582 std::vector
< SdrObject
* > aMovedChildObjs
;
584 // move 'children' accordingly
585 if ( dynamic_cast< const SwFlyFrame
*>( pMovedAnchoredObj
) != nullptr )
587 const SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrame
*>(pMovedAnchoredObj
);
589 // adjustments for accessibility API
590 m_rImp
.DisposeAccessibleFrame( pFlyFrame
);
591 m_rImp
.AddAccessibleFrame( pFlyFrame
);
593 const sal_uInt32 nChildNewPos
= bMovedForward
? nNewPos
: nNewPos
+1;
594 size_t i
= bMovedForward
? nOldPos
: nObjCount
-1;
597 SdrObject
* pTmpObj
= pDrawPage
->GetObj( i
);
598 if ( pTmpObj
== pObj
)
601 // #i38563# - assure, that anchor frame exists.
602 // If object is anchored inside a invisible part of the document
603 // (e.g. page header, whose page style isn't applied, or hidden
604 // section), no anchor frame exists.
605 const SwFrame
* pTmpAnchorFrame
= lcl_FindAnchor( pTmpObj
, true );
606 const SwFlyFrame
* pTmpParentObj
= pTmpAnchorFrame
607 ? pTmpAnchorFrame
->FindFlyFrame() : nullptr;
608 if ( pTmpParentObj
&&
609 ( ( pTmpParentObj
== pFlyFrame
) ||
610 ( pFlyFrame
->IsUpperOf( *pTmpParentObj
) ) ) )
612 // move child object.,
613 pDrawPage
->SetObjectOrdNum( i
, nChildNewPos
);
614 pDrawPage
->RecalcObjOrdNums();
615 // collect 'child' object
616 aMovedChildObjs
.push_back( pTmpObj
);
617 // adjustments for accessibility API
618 if ( dynamic_cast< const SwVirtFlyDrawObj
*>( pTmpObj
) != nullptr )
620 const SwFlyFrame
*pTmpFlyFrame
=
621 static_cast<SwVirtFlyDrawObj
*>(pTmpObj
)->GetFlyFrame();
622 m_rImp
.DisposeAccessibleFrame( pTmpFlyFrame
);
623 m_rImp
.AddAccessibleFrame( pTmpFlyFrame
);
627 m_rImp
.DisposeAccessibleObj(pTmpObj
, true);
628 m_rImp
.AddAccessibleObj( pTmpObj
);
633 // adjust loop counter
636 else if ( !bMovedForward
&& i
> 0 )
640 } while ( ( bMovedForward
&& i
< ( nObjCount
- aMovedChildObjs
.size() ) ) ||
641 ( !bMovedForward
&& i
> ( nNewPos
+ aMovedChildObjs
.size() ) ) );
645 // adjustments for accessibility API
646 m_rImp
.DisposeAccessibleObj(pObj
, true);
647 m_rImp
.AddAccessibleObj( pObj
);
650 MoveRepeatedObjs( *pMovedAnchoredObj
, aMovedChildObjs
);
653 bool SwDrawView::TakeDragLimit( SdrDragMode eMode
,
654 tools::Rectangle
& rRect
) const
656 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
658 if( 1 == rMrkList
.GetMarkCount() )
660 const SdrObject
*pObj
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
662 if( ::CalcClipRect( pObj
, aRect
, eMode
== SdrDragMode::Move
) )
664 rRect
= aRect
.SVRect();
671 const SwFrame
* SwDrawView::CalcAnchor()
673 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
674 if ( rMrkList
.GetMarkCount() != 1 )
677 SdrObject
* pObj
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
679 //Search for paragraph bound objects, otherwise only the
680 //current anchor. Search only if we currently drag.
681 const SwFrame
* pAnch
;
682 tools::Rectangle aMyRect
;
683 const bool bFly
= dynamic_cast< const SwVirtFlyDrawObj
*>( pObj
) != nullptr;
686 pAnch
= static_cast<SwVirtFlyDrawObj
*>(pObj
)->GetFlyFrame()->GetAnchorFrame();
687 aMyRect
= static_cast<SwVirtFlyDrawObj
*>(pObj
)->GetFlyFrame()->getFrameArea().SVRect();
691 SwDrawContact
*pC
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
692 // determine correct anchor position for 'virtual' drawing objects.
694 pAnch
= pC
->GetAnchorFrame( pObj
);
697 pC
->ConnectToLayout();
698 // determine correct anchor position for 'virtual' drawing objects.
700 pAnch
= pC
->GetAnchorFrame( pObj
);
702 aMyRect
= pObj
->GetSnapRect();
705 const bool bTopRight
= pAnch
&& ( ( pAnch
->IsVertical() &&
706 !pAnch
->IsVertLR() ) ||
707 pAnch
->IsRightToLeft() );
708 const Point aMyPt
= bTopRight
? aMyRect
.TopRight() : aMyRect
.TopLeft();
713 if ( !TakeDragObjAnchorPos( aPt
, bTopRight
) )
718 tools::Rectangle aRect
= pObj
->GetSnapRect();
719 aPt
= bTopRight
? aRect
.TopRight() : aRect
.TopLeft();
724 if ( pAnch
&& pAnch
->IsContentFrame() )
726 // allow drawing objects in header/footer,
727 // but exclude control objects.
728 bool bBodyOnly
= CheckControlLayer( pObj
);
729 pAnch
= ::FindAnchor( static_cast<const SwContentFrame
*>(pAnch
), aPt
, bBodyOnly
);
733 const SwRect
aRect( aPt
.getX(), aPt
.getY(), 1, 1 );
735 SwDrawContact
* pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
736 if ( pContact
->GetAnchorFrame( pObj
) &&
737 pContact
->GetAnchorFrame( pObj
)->IsPageFrame() )
738 pAnch
= pContact
->GetPageFrame();
740 pAnch
= pContact
->FindPage( aRect
);
743 if( pAnch
&& !pAnch
->IsProtected() )
744 m_aAnchorPoint
= pAnch
->GetFrameAnchorPos( ::HasWrap( pObj
) );
750 void SwDrawView::ShowDragAnchor()
752 SdrHdl
* pHdl
= maHdlList
.GetHdl(SdrHdlKind::Anchor
);
754 pHdl
= maHdlList
.GetHdl(SdrHdlKind::Anchor_TR
);
759 pHdl
->SetPos(m_aAnchorPoint
);
763 void SwDrawView::MarkListHasChanged()
765 Imp().GetShell()->DrawSelChanged();
766 FmFormView::MarkListHasChanged();
770 void SwDrawView::ModelHasChanged()
772 // The ModelHasChanged() call in DrawingLayer also updates
773 // a eventually active text edit view (OutlinerView). This also leads
774 // to newly setting the background color for that edit view. Thus,
775 // this method rescues the current background color if a OutlinerView
776 // exists and re-establishes it then. To be more safe, the OutlinerView
777 // will be fetched again (maybe textedit has ended).
778 OutlinerView
* pView
= GetTextEditOutlinerView();
780 bool bColorWasSaved(false);
784 aBackColor
= pView
->GetBackgroundColor();
785 bColorWasSaved
= true;
789 FmFormView::ModelHasChanged();
793 pView
= GetTextEditOutlinerView();
797 pView
->SetBackgroundColor(aBackColor
);
802 void SwDrawView::MakeVisible( const tools::Rectangle
&rRect
, vcl::Window
& )
804 OSL_ENSURE( m_rImp
.GetShell()->GetWin(), "MakeVisible, unknown Window");
805 m_rImp
.GetShell()->MakeVisible( SwRect( rRect
) );
808 void SwDrawView::CheckPossibilities()
810 FmFormView::CheckPossibilities();
812 //In addition to the existing flags of the objects themselves,
813 //which are evaluated by the DrawingEngine, other circumstances
814 //lead to a protection.
815 //Objects that are anchored in frames need to be protected
816 //if the content of the frame is protected.
817 //OLE-Objects may themselves wish a resize protection (StarMath)
819 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
820 bool bProtect
= false;
821 bool bSzProtect
= false;
824 for ( size_t i
= 0; !bProtect
&& i
< rMrkList
.GetMarkCount(); ++i
)
826 const SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
827 const SwFrame
*pFrame
= nullptr;
828 if ( auto pVirtFlyDrawObj
= dynamic_cast< const SwVirtFlyDrawObj
*>( pObj
) )
830 const SwFlyFrame
*pFly
= pVirtFlyDrawObj
->GetFlyFrame();
833 pFrame
= pFly
->GetAnchorFrame();
834 if ( pFly
->Lower() && pFly
->Lower()->IsNoTextFrame() )
836 const SwNoTextFrame
*const pNTF(static_cast<const SwNoTextFrame
*>(pFly
->Lower()));
837 const SwOLENode
*const pOLENd
= pNTF
->GetNode()->GetOLENode();
838 const SwGrfNode
*const pGrfNd
= pNTF
->GetNode()->GetGrfNode();
842 const uno::Reference
< embed::XEmbeddedObject
> xObj
= const_cast< SwOLEObj
& >(pOLENd
->GetOLEObj()).GetOleRef();
846 // --> improvement for the future, when more
847 // than one Writer fly frame can be selected.
849 // TODO/LATER: retrieve Aspect - from where?!
850 bSzProtect
|= ( embed::EmbedMisc::EMBED_NEVERRESIZE
& xObj
->getStatus( embed::Aspects::MSOLE_CONTENT
) ) != 0;
852 // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
853 SwDoc
* pDoc
= Imp().GetShell()->GetDoc();
854 const bool bProtectMathPos
= SotExchange::IsMath( xObj
->getClassID() )
855 && RndStdIds::FLY_AS_CHAR
== pFly
->GetFormat()->GetAnchor().GetAnchorId()
856 && pDoc
->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT
);
863 // RotGrfFlyFrame: GraphicNode allows rotation(s). The loop ew are in stops
864 // as soon as bMoveProtect is set, but since rotation is valid only with
865 // a single object selected this makes no difference
873 SwDrawContact
*pC
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
875 pFrame
= pC
->GetAnchorFrame( pObj
);
878 bProtect
= pFrame
->IsProtected(); //Frames, areas etc.
880 SwFrameFormat
* pFrameFormat( ::FindFrameFormat( const_cast<SdrObject
*>(pObj
) ) );
883 OSL_FAIL( "<SwDrawView::CheckPossibilities()> - missing frame format" );
886 else if ((RndStdIds::FLY_AS_CHAR
== pFrameFormat
->GetAnchor().GetAnchorId()) &&
887 rMrkList
.GetMarkCount() > 1 )
893 bMoveProtect
|= bProtect
;
894 bResizeProtect
|= bProtect
|| bSzProtect
;
896 // RotGrfFlyFrame: allow rotation when SwGrfNode is selected and not size protected
897 bRotateFreeAllowed
|= bRotate
&& !bProtect
;
898 bRotate90Allowed
|= bRotateFreeAllowed
;
901 /// replace marked <SwDrawVirtObj>-objects by its reference object for delete marked objects.
902 void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView
& _rMarkView
)
904 SdrPageView
* pDrawPageView
= _rMarkView
.GetSdrPageView();
905 const SdrMarkList
& rMarkList
= _rMarkView
.GetMarkedObjectList();
907 if( rMarkList
.GetMarkCount() )
909 // collect marked objects in a local data structure
910 std::vector
<SdrObject
*> aMarkedObjs
;
911 for( size_t i
= 0; i
< rMarkList
.GetMarkCount(); ++i
)
913 SdrObject
* pMarkedObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
914 aMarkedObjs
.push_back( pMarkedObj
);
916 // unmark all objects
917 _rMarkView
.UnmarkAllObj();
918 // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
920 while ( !aMarkedObjs
.empty() )
922 SdrObject
* pMarkObj
= aMarkedObjs
.back();
923 if ( dynamic_cast< const SwDrawVirtObj
*>( pMarkObj
) != nullptr )
925 SdrObject
* pRefObj
= &(static_cast<SwDrawVirtObj
*>(pMarkObj
)->ReferencedObj());
926 if ( !_rMarkView
.IsObjMarked( pRefObj
) )
928 _rMarkView
.MarkObj( pRefObj
, pDrawPageView
);
933 _rMarkView
.MarkObj( pMarkObj
, pDrawPageView
);
936 aMarkedObjs
.pop_back();
938 // sort marked list in order to assure consistent state in drawing layer
939 _rMarkView
.SortMarkedObjects();
943 SfxViewShell
* SwDrawView::GetSfxViewShell() const
945 return m_rImp
.GetShell()->GetSfxViewShell();
948 void SwDrawView::DeleteMarked()
950 SwDoc
* pDoc
= Imp().GetShell()->GetDoc();
951 SwRootFrame
*pTmpRoot
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
953 pTmpRoot
->StartAllAction();
954 pDoc
->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY
, nullptr);
955 // replace marked <SwDrawVirtObj>-objects by its reference objects.
957 SdrPageView
* pDrawPageView
= m_rImp
.GetPageView();
960 SdrMarkView
* pMarkView
= &(pDrawPageView
->GetView());
963 ReplaceMarkedDrawVirtObjs( *pMarkView
);
968 // Check what textboxes have to be deleted afterwards.
969 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
970 std::vector
<SwFrameFormat
*> aTextBoxesToDelete
;
971 for (size_t i
= 0; i
< rMarkList
.GetMarkCount(); ++i
)
973 SdrObject
*pObject
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
974 SwDrawContact
* pDrawContact
= static_cast<SwDrawContact
*>(GetUserCall(pObject
));
975 SwFrameFormat
* pFormat
= pDrawContact
->GetFormat();
976 if (SwFrameFormat
* pTextBox
= SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_DRAWFRMFMT
))
977 aTextBoxesToDelete
.push_back(pTextBox
);
980 if ( pDoc
->DeleteSelection( *this ) )
982 FmFormView::DeleteMarked();
983 ::FrameNotify( Imp().GetShell(), FLY_DRAG_END
);
985 // Only delete these now: earlier deletion would clear the mark list as well.
986 for (std::vector
<SwFrameFormat
*>::iterator i
= aTextBoxesToDelete
.begin(); i
!= aTextBoxesToDelete
.end(); ++i
)
987 pDoc
->getIDocumentLayoutAccess().DelLayoutFormat(*i
);
989 pDoc
->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY
, nullptr);
991 pTmpRoot
->EndAllAction();
994 // support enhanced text edit for draw objects
995 SdrUndoManager
* SwDrawView::getSdrUndoManagerForEnhancedTextEdit() const
997 SwDoc
* pDoc
= Imp().GetShell()->GetDoc();
999 return pDoc
? dynamic_cast< SdrUndoManager
* >(&(pDoc
->GetUndoManager())) : nullptr;
1002 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */