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 <config_wasm_strip.h>
22 #include <hintids.hxx>
23 #include <svtools/optionsdrawinglayer.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/fmmodel.hxx>
27 #include <sot/exchange.hxx>
28 #include <svx/sdrundomanager.hxx>
29 #include <tools/globname.hxx>
30 #include <editeng/outliner.hxx>
31 #include <osl/diagnose.h>
32 #include <com/sun/star/embed/EmbedMisc.hpp>
33 #include <com/sun/star/embed/XEmbeddedObject.hpp>
35 #include <pagefrm.hxx>
36 #include <rootfrm.hxx>
38 #include <notxtfrm.hxx>
41 #include <dflyobj.hxx>
42 #include <dcontact.hxx>
43 #include <textboxhelper.hxx>
45 #include <viewimp.hxx>
51 #include <fmtanchr.hxx>
52 #include <IDocumentUndoRedo.hxx>
53 #include <DocumentSettingManager.hxx>
54 #include <IDocumentLayoutAccess.hxx>
56 #include <com/sun/star/embed/Aspects.hpp>
60 #include <sortedobjs.hxx>
62 using namespace com::sun::star
;
66 class SwSdrHdl
: public SdrHdl
69 SwSdrHdl(const Point
& rPnt
, bool bTopRight
) :
70 SdrHdl( rPnt
, bTopRight
? SdrHdlKind::Anchor_TR
: SdrHdlKind::Anchor
) {}
71 virtual bool IsFocusHdl() const override
;
76 bool SwSdrHdl::IsFocusHdl() const
78 if( SdrHdlKind::Anchor
== eKind
|| SdrHdlKind::Anchor_TR
== eKind
)
80 return SdrHdl::IsFocusHdl();
83 static const SwFrame
*lcl_FindAnchor( const SdrObject
*pObj
, bool bAll
)
85 const SwVirtFlyDrawObj
*pVirt
= dynamic_cast< const SwVirtFlyDrawObj
*>( pObj
);
88 if ( bAll
|| !pVirt
->GetFlyFrame()->IsFlyInContentFrame() )
89 return pVirt
->GetFlyFrame()->GetAnchorFrame();
93 const SwDrawContact
*pCont
= static_cast<const SwDrawContact
*>(GetUserCall(pObj
));
95 return pCont
->GetAnchorFrame( pObj
);
100 SwDrawView::SwDrawView(
102 FmFormModel
& rFmFormModel
,
103 OutputDevice
* pOutDev
)
104 : FmFormView(rFmFormModel
, pOutDev
),
107 SetPageVisible( false );
108 SetBordVisible( false );
109 SetGridVisible( false );
110 SetHlplVisible( false );
111 SetGlueVisible( false );
112 SetFrameDragSingles();
115 EnableExtendedKeyInputDispatcher( false );
116 EnableExtendedMouseEventDispatcher( false );
118 SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );
120 SetPrintPreview( rI
.GetShell()->IsPreview() );
122 // #i73602# Use default from the configuration
123 SetBufferedOverlayAllowed(SvtOptionsDrawinglayer::IsOverlayBuffer_Writer());
125 // #i74769#, #i75172# Use default from the configuration
126 SetBufferedOutputAllowed(SvtOptionsDrawinglayer::IsPaintBuffer_Writer());
130 bool SwDrawView::IsAntiAliasing()
132 return SvtOptionsDrawinglayer::IsAntiAliasing();
135 static SdrObject
* impLocalHitCorrection(SdrObject
* pRetval
, const Point
& rPnt
, sal_uInt16 nTol
, const SdrMarkList
&rMrkList
)
139 // the old method forced back to outer bounds test when nTol == 0, so
140 // do not try to correct when nTol is not set (used from HelpContent)
144 // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
145 // the SdrObject-specific CheckHit implementations are now replaced with primitives and
146 // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
147 // detect if object is selected) are no longer valid.
148 // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
149 // implementation reduced this excluding the inner bound when the object was not selected.
150 SwVirtFlyDrawObj
* pSwVirtFlyDrawObj
= dynamic_cast< SwVirtFlyDrawObj
* >(pRetval
);
152 if(pSwVirtFlyDrawObj
)
154 if(pSwVirtFlyDrawObj
->GetFlyFrame()->Lower() && pSwVirtFlyDrawObj
->GetFlyFrame()->Lower()->IsNoTextFrame())
156 // the old method used IsNoTextFrame (should be for SW's own OLE and
157 // graphic's) to accept hit only based on outer bounds; nothing to do
161 // check if the object is selected in this view
162 const size_t nMarkCount(rMrkList
.GetMarkCount());
163 bool bSelected(false);
165 for(size_t a
= 0; !bSelected
&& a
< nMarkCount
; ++a
)
167 if(pSwVirtFlyDrawObj
== rMrkList
.GetMark(a
)->GetMarkedSdrObj())
175 // when not selected, the object is not hit when hit position is inside
176 // inner range. Get and shrink inner range
177 basegfx::B2DRange
aInnerBound(pSwVirtFlyDrawObj
->getInnerBound());
179 aInnerBound
.grow(-1.0 * nTol
);
181 if(aInnerBound
.isInside(basegfx::B2DPoint(rPnt
.X(), rPnt
.Y())))
194 SdrObject
* SwDrawView::CheckSingleSdrObjectHit(const Point
& rPnt
, sal_uInt16 nTol
, SdrObject
* pObj
, SdrPageView
* pPV
, SdrSearchOptions nOptions
, const SdrLayerIDSet
* pMVisLay
) const
197 SdrObject
* pRetval
= FmFormView::CheckSingleSdrObjectHit(rPnt
, nTol
, pObj
, pPV
, nOptions
, pMVisLay
);
201 // override to allow extra handling when picking SwVirtFlyDrawObj's
202 pRetval
= impLocalHitCorrection(pRetval
, rPnt
, nTol
, GetMarkedObjectList());
208 /// Gets called every time the handles need to be build
209 void SwDrawView::AddCustomHdl()
211 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
213 if(rMrkList
.GetMarkCount() != 1 || !GetUserCall(rMrkList
.GetMark( 0 )->GetMarkedSdrObj()))
216 SdrObject
*pObj
= rMrkList
.GetMark(0)->GetMarkedSdrObj();
218 SwFrameFormat
* pFrameFormat( ::FindFrameFormat( pObj
) );
221 OSL_FAIL( "<SwDrawView::AddCustomHdl()> - missing frame format!" );
224 const SwFormatAnchor
&rAnchor
= pFrameFormat
->GetAnchor();
226 if (RndStdIds::FLY_AS_CHAR
== rAnchor
.GetAnchorId())
229 const SwFrame
* pAnch
= CalcAnchor();
233 Point
aPos(m_aAnchorPoint
);
235 if ( RndStdIds::FLY_AT_CHAR
== rAnchor
.GetAnchorId() )
237 // #i28701# - use last character rectangle saved at object
238 // in order to avoid a format of the anchor frame
239 SwAnchoredObject
* pAnchoredObj
= ::GetUserCall( pObj
)->GetAnchoredObj( pObj
);
241 // Invalidate/recalc LastCharRect which can contain invalid frame offset because
242 // of later frame changes
243 pAnchoredObj
->CheckCharRectAndTopOfLine(false);
245 SwRect aAutoPos
= pAnchoredObj
->GetLastCharRect();
246 if ( aAutoPos
.Height() )
248 aPos
= aAutoPos
.Pos();
252 // add anchor handle:
253 std::unique_ptr
<SdrHdl
> hdl
= std::make_unique
<SwSdrHdl
>( aPos
, ( pAnch
->IsVertical() && !pAnch
->IsVertLR() ) ||
254 pAnch
->IsRightToLeft() );
255 hdl
->SetObjHdlNum(maHdlList
.GetHdlCount());
256 maHdlList
.AddHdl(std::move(hdl
));
259 SdrObject
* SwDrawView::GetMaxToTopObj( SdrObject
* pObj
) const
261 if ( GetUserCall(pObj
) )
263 const SwFrame
*pAnch
= ::lcl_FindAnchor( pObj
, false );
266 //The topmost Obj within the anchor must not be overtaken.
267 const SwFlyFrame
*pFly
= pAnch
->FindFlyFrame();
270 const SwPageFrame
*pPage
= pFly
->FindPageFrame();
271 if ( pPage
->GetSortedObjs() )
274 for (SwAnchoredObject
* i
: *pPage
->GetSortedObjs())
276 const SdrObject
*pO
= i
->GetDrawObj();
278 if ( pO
->GetOrdNumDirect() > nOrdNum
)
280 const SwFrame
*pTmpAnch
= ::lcl_FindAnchor( pO
, false );
281 if ( pFly
->IsAnLower( pTmpAnch
) )
283 nOrdNum
= pO
->GetOrdNumDirect();
289 SdrPage
*pTmpPage
= GetModel().GetPage( 0 );
291 if ( nOrdNum
< pTmpPage
->GetObjCount() )
293 return pTmpPage
->GetObj( nOrdNum
);
303 SdrObject
* SwDrawView::GetMaxToBtmObj(SdrObject
* pObj
) const
305 if ( GetUserCall(pObj
) )
307 const SwFrame
*pAnch
= ::lcl_FindAnchor( pObj
, false );
310 //The Fly of the anchor must not be "flying under".
311 const SwFlyFrame
*pFly
= pAnch
->FindFlyFrame();
314 SdrObject
*pRet
= const_cast<SdrObject
*>(static_cast<SdrObject
const *>(pFly
->GetVirtDrawObj()));
315 return pRet
!= pObj
? pRet
: nullptr;
322 /// determine maximal order number for a 'child' object of given 'parent' object
323 sal_uInt32
SwDrawView::GetMaxChildOrdNum( const SwFlyFrame
& _rParentObj
,
324 const SdrObject
* _pExclChildObj
)
326 sal_uInt32 nMaxChildOrdNum
= _rParentObj
.GetDrawObj()->GetOrdNum();
328 const SdrPage
* pDrawPage
= _rParentObj
.GetDrawObj()->getSdrPageFromSdrObject();
329 OSL_ENSURE( pDrawPage
,
330 "<SwDrawView::GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" );
332 const size_t nObjCount
= pDrawPage
->GetObjCount();
333 for ( size_t i
= nObjCount
-1; i
> _rParentObj
.GetDrawObj()->GetOrdNum() ; --i
)
335 const SdrObject
* pObj
= pDrawPage
->GetObj( i
);
337 // Don't consider 'child' object <_pExclChildObj>
338 if ( pObj
== _pExclChildObj
)
343 if ( pObj
->GetOrdNum() > nMaxChildOrdNum
&&
344 _rParentObj
.IsAnLower( lcl_FindAnchor( pObj
, true ) ) )
346 nMaxChildOrdNum
= pObj
->GetOrdNum();
351 return nMaxChildOrdNum
;
354 /// method to move 'repeated' objects of the given moved object to the according level
355 void SwDrawView::MoveRepeatedObjs( const SwAnchoredObject
& _rMovedAnchoredObj
,
356 const std::vector
<SdrObject
*>& _rMovedChildObjs
) const
358 // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
359 std::vector
<SwAnchoredObject
*> aAnchoredObjs
;
361 const SwContact
* pContact
= ::GetUserCall( _rMovedAnchoredObj
.GetDrawObj() );
362 assert(pContact
&& "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.");
363 pContact
->GetAnchoredObjs( aAnchoredObjs
);
366 // check, if 'repeated' objects exists.
367 if ( aAnchoredObjs
.size() <= 1 )
370 SdrPage
* pDrawPage
= GetModel().GetPage( 0 );
372 // move 'repeated' ones to the same order number as the already moved one.
373 const size_t nNewPos
= _rMovedAnchoredObj
.GetDrawObj()->GetOrdNum();
374 while ( !aAnchoredObjs
.empty() )
376 SwAnchoredObject
* pAnchoredObj
= aAnchoredObjs
.back();
377 if ( pAnchoredObj
!= &_rMovedAnchoredObj
)
379 pDrawPage
->SetObjectOrdNum( pAnchoredObj
->GetDrawObj()->GetOrdNum(),
381 pDrawPage
->RecalcObjOrdNums();
382 // adjustments for accessibility API
383 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
384 if ( auto pTmpFlyFrame
= pAnchoredObj
->DynCastFlyFrame() )
386 m_rImp
.DisposeAccessibleFrame( pTmpFlyFrame
);
387 m_rImp
.AddAccessibleFrame( pTmpFlyFrame
);
391 m_rImp
.DisposeAccessibleObj(pAnchoredObj
->GetDrawObj(), true);
392 m_rImp
.AddAccessibleObj( pAnchoredObj
->GetDrawObj() );
396 aAnchoredObjs
.pop_back();
399 // move 'repeated' ones of 'child' objects
400 for ( SdrObject
* pChildObj
: _rMovedChildObjs
)
403 const SwContact
* pContact
= ::GetUserCall( pChildObj
);
404 assert(pContact
&& "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.");
405 pContact
->GetAnchoredObjs( aAnchoredObjs
);
407 // move 'repeated' ones to the same order number as the already moved one.
408 const size_t nTmpNewPos
= pChildObj
->GetOrdNum();
409 while ( !aAnchoredObjs
.empty() )
411 SwAnchoredObject
* pAnchoredObj
= aAnchoredObjs
.back();
412 if ( pAnchoredObj
->GetDrawObj() != pChildObj
)
414 pDrawPage
->SetObjectOrdNum( pAnchoredObj
->GetDrawObj()->GetOrdNum(),
416 pDrawPage
->RecalcObjOrdNums();
417 // adjustments for accessibility API
418 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
419 if ( auto pTmpFlyFrame
= pAnchoredObj
->DynCastFlyFrame() )
421 m_rImp
.DisposeAccessibleFrame( pTmpFlyFrame
);
422 m_rImp
.AddAccessibleFrame( pTmpFlyFrame
);
426 m_rImp
.DisposeAccessibleObj(pAnchoredObj
->GetDrawObj(), true);
427 m_rImp
.AddAccessibleObj( pAnchoredObj
->GetDrawObj() );
431 aAnchoredObjs
.pop_back();
436 // --> adjustment and re-factoring of method
437 void SwDrawView::ObjOrderChanged( SdrObject
* pObj
, size_t nOldPos
,
440 // nothing to do for group members
441 if ( pObj
->getParentSdrObjectFromSdrObject() )
446 // determine drawing page and assure that the order numbers are correct.
447 SdrPage
* pDrawPage
= GetModel().GetPage( 0 );
448 if ( pDrawPage
->IsObjOrdNumsDirty() )
449 pDrawPage
->RecalcObjOrdNums();
450 const size_t nObjCount
= pDrawPage
->GetObjCount();
452 SwAnchoredObject
* pMovedAnchoredObj
=
453 ::GetUserCall( pObj
)->GetAnchoredObj( pObj
);
454 const SwFlyFrame
* pParentAnchoredObj
=
455 pMovedAnchoredObj
->GetAnchorFrame()->FindFlyFrame();
457 const bool bMovedForward
= nOldPos
< nNewPos
;
459 // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
460 if ( pParentAnchoredObj
)
464 const size_t nMaxChildOrdNumWithoutMoved
=
465 GetMaxChildOrdNum( *pParentAnchoredObj
, pMovedAnchoredObj
->GetDrawObj() );
466 if ( nNewPos
> nMaxChildOrdNumWithoutMoved
+1 )
468 // set position to the top of the 'child' object group
469 pDrawPage
->SetObjectOrdNum( nNewPos
, nMaxChildOrdNumWithoutMoved
+1 );
470 nNewPos
= nMaxChildOrdNumWithoutMoved
+1;
475 const size_t nParentOrdNum
= pParentAnchoredObj
->GetDrawObj()->GetOrdNum();
476 if ( nNewPos
< nParentOrdNum
)
478 // set position to the bottom of the 'child' object group
479 pDrawPage
->SetObjectOrdNum( nNewPos
, nParentOrdNum
);
480 nNewPos
= nParentOrdNum
;
483 if ( pDrawPage
->IsObjOrdNumsDirty() )
484 pDrawPage
->RecalcObjOrdNums();
487 // Assure, that object isn't positioned between 'repeated' ones
488 if ( ( bMovedForward
&& nNewPos
< nObjCount
- 1 ) ||
489 ( !bMovedForward
&& nNewPos
> 0 ) )
491 const SdrObject
* pTmpObj
=
492 pDrawPage
->GetObj( bMovedForward
? nNewPos
- 1 : nNewPos
+ 1 );
495 size_t nTmpNewPos( nNewPos
);
498 // move before the top 'repeated' object
499 const sal_uInt32 nTmpMaxOrdNum
=
500 ::GetUserCall( pTmpObj
)->GetMaxOrdNum();
501 if ( nTmpMaxOrdNum
> nNewPos
)
502 nTmpNewPos
= nTmpMaxOrdNum
;
506 // move behind the bottom 'repeated' object
507 const sal_uInt32 nTmpMinOrdNum
=
508 ::GetUserCall( pTmpObj
)->GetMinOrdNum();
509 if ( nTmpMinOrdNum
< nNewPos
)
510 nTmpNewPos
= nTmpMinOrdNum
;
512 if ( nTmpNewPos
!= nNewPos
)
514 pDrawPage
->SetObjectOrdNum( nNewPos
, nTmpNewPos
);
515 nNewPos
= nTmpNewPos
;
516 pDrawPage
->RecalcObjOrdNums();
521 // On move forward, assure that object is moved before its own children.
522 // Only Writer fly frames can have children.
523 if ( pMovedAnchoredObj
->DynCastFlyFrame() &&
524 bMovedForward
&& nNewPos
< nObjCount
- 1 )
526 sal_uInt32 nMaxChildOrdNum
=
527 GetMaxChildOrdNum( *static_cast<const SwFlyFrame
*>(pMovedAnchoredObj
) );
528 if ( nNewPos
< nMaxChildOrdNum
)
530 // determine position before the object before its top 'child' object
531 const SdrObject
* pTmpObj
= pDrawPage
->GetObj( nMaxChildOrdNum
);
532 size_t nTmpNewPos
= ::GetUserCall( pTmpObj
)->GetMaxOrdNum() + 1;
533 if ( nTmpNewPos
>= nObjCount
)
537 // assure, that determined position isn't between 'repeated' objects
538 pTmpObj
= pDrawPage
->GetObj( nTmpNewPos
);
539 nTmpNewPos
= ::GetUserCall( pTmpObj
)->GetMaxOrdNum();
540 // apply new position
541 pDrawPage
->SetObjectOrdNum( nNewPos
, nTmpNewPos
);
542 nNewPos
= nTmpNewPos
;
543 pDrawPage
->RecalcObjOrdNums();
547 // Assure, that object isn't positioned between nested objects
548 if ( ( bMovedForward
&& nNewPos
< nObjCount
- 1 ) ||
549 ( !bMovedForward
&& nNewPos
> 0 ) )
551 size_t nTmpNewPos( nNewPos
);
552 const SwFrameFormat
* pParentFrameFormat
=
553 pParentAnchoredObj
? &(pParentAnchoredObj
->GetFrameFormat()) : nullptr;
554 const SdrObject
* pTmpObj
= pDrawPage
->GetObj( nNewPos
+ 1 );
557 // #i38563# - assure, that anchor frame exists.
558 // If object is anchored inside an invisible part of the document
559 // (e.g. page header, whose page style isn't applied, or hidden
560 // section), no anchor frame exists.
561 const SwFrame
* pTmpAnchorFrame
= lcl_FindAnchor( pTmpObj
, true );
562 const SwFlyFrame
* pTmpParentObj
= pTmpAnchorFrame
563 ? pTmpAnchorFrame
->FindFlyFrame() : nullptr;
564 if ( pTmpParentObj
&&
565 &(pTmpParentObj
->GetFrameFormat()) != pParentFrameFormat
)
569 nTmpNewPos
= ::GetUserCall( pTmpObj
)->GetMaxOrdNum();
570 pTmpObj
= pDrawPage
->GetObj( nTmpNewPos
+ 1 );
574 nTmpNewPos
= ::GetUserCall( pTmpParentObj
->GetDrawObj() )
576 pTmpObj
= pTmpParentObj
->GetDrawObj();
582 if ( nTmpNewPos
!= nNewPos
)
584 pDrawPage
->SetObjectOrdNum( nNewPos
, nTmpNewPos
);
585 nNewPos
= nTmpNewPos
;
586 pDrawPage
->RecalcObjOrdNums();
590 // setup collection of moved 'child' objects to move its 'repeated' objects.
591 std::vector
< SdrObject
* > aMovedChildObjs
;
593 // move 'children' accordingly
594 if ( auto pFlyFrame
= pMovedAnchoredObj
->DynCastFlyFrame() )
596 // adjustments for accessibility API
597 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
598 m_rImp
.DisposeAccessibleFrame( pFlyFrame
);
599 m_rImp
.AddAccessibleFrame( pFlyFrame
);
602 const sal_uInt32 nChildNewPos
= bMovedForward
? nNewPos
: nNewPos
+1;
603 size_t i
= bMovedForward
? nOldPos
: nObjCount
-1;
606 SdrObject
* pTmpObj
= pDrawPage
->GetObj( i
);
607 if ( pTmpObj
== pObj
)
610 // #i38563# - assure, that anchor frame exists.
611 // If object is anchored inside an invisible part of the document
612 // (e.g. page header, whose page style isn't applied, or hidden
613 // section), no anchor frame exists.
614 const SwFrame
* pTmpAnchorFrame
= lcl_FindAnchor( pTmpObj
, true );
615 const SwFlyFrame
* pTmpParentObj
= pTmpAnchorFrame
616 ? pTmpAnchorFrame
->FindFlyFrame() : nullptr;
617 if ( pTmpParentObj
&&
618 ( ( pTmpParentObj
== pFlyFrame
) ||
619 ( pFlyFrame
->IsUpperOf( *pTmpParentObj
) ) ) )
621 // move child object.,
622 pDrawPage
->SetObjectOrdNum( i
, nChildNewPos
);
623 pDrawPage
->RecalcObjOrdNums();
624 // collect 'child' object
625 aMovedChildObjs
.push_back( pTmpObj
);
626 // adjustments for accessibility API
627 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
628 if ( auto pFlyDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>( pTmpObj
) )
630 const SwFlyFrame
*pTmpFlyFrame
= pFlyDrawObj
->GetFlyFrame();
631 m_rImp
.DisposeAccessibleFrame( pTmpFlyFrame
);
632 m_rImp
.AddAccessibleFrame( pTmpFlyFrame
);
636 m_rImp
.DisposeAccessibleObj(pTmpObj
, true);
637 m_rImp
.AddAccessibleObj( pTmpObj
);
643 // adjust loop counter
650 } while ( ( bMovedForward
&& i
< ( nObjCount
- aMovedChildObjs
.size() ) ) ||
651 ( !bMovedForward
&& i
> ( nNewPos
+ aMovedChildObjs
.size() ) ) );
653 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
656 // adjustments for accessibility API
657 m_rImp
.DisposeAccessibleObj(pObj
, true);
658 m_rImp
.AddAccessibleObj( pObj
);
662 MoveRepeatedObjs( *pMovedAnchoredObj
, aMovedChildObjs
);
665 bool SwDrawView::TakeDragLimit( SdrDragMode eMode
,
666 tools::Rectangle
& rRect
) const
668 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
670 if( 1 == rMrkList
.GetMarkCount() )
672 const SdrObject
*pObj
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
674 if( ::CalcClipRect( pObj
, aRect
, eMode
== SdrDragMode::Move
) )
676 rRect
= aRect
.SVRect();
683 const SwFrame
* SwDrawView::CalcAnchor()
685 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
686 if ( rMrkList
.GetMarkCount() != 1 )
689 SdrObject
* pObj
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
691 //Search for paragraph bound objects, otherwise only the
692 //current anchor. Search only if we currently drag.
693 const SwFrame
* pAnch
;
694 tools::Rectangle aMyRect
;
695 auto pFlyDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>( pObj
);
698 pAnch
= pFlyDrawObj
->GetFlyFrame()->GetAnchorFrame();
699 aMyRect
= pFlyDrawObj
->GetFlyFrame()->getFrameArea().SVRect();
703 SwDrawContact
*pC
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
704 // determine correct anchor position for 'virtual' drawing objects.
706 pAnch
= pC
->GetAnchorFrame( pObj
);
709 pC
->ConnectToLayout();
710 // determine correct anchor position for 'virtual' drawing objects.
712 pAnch
= pC
->GetAnchorFrame( pObj
);
714 aMyRect
= pObj
->GetSnapRect();
717 const bool bTopRight
= pAnch
&& ( ( pAnch
->IsVertical() &&
718 !pAnch
->IsVertLR() ) ||
719 pAnch
->IsRightToLeft() );
720 const Point aMyPt
= bTopRight
? aMyRect
.TopRight() : aMyRect
.TopLeft();
725 if ( !TakeDragObjAnchorPos( aPt
, bTopRight
) )
730 tools::Rectangle aRect
= pObj
->GetSnapRect();
731 aPt
= bTopRight
? aRect
.TopRight() : aRect
.TopLeft();
736 if ( pAnch
&& pAnch
->IsContentFrame() )
738 // allow drawing objects in header/footer,
739 // but exclude control objects.
740 bool bBodyOnly
= CheckControlLayer( pObj
);
741 pAnch
= ::FindAnchor( static_cast<const SwContentFrame
*>(pAnch
), aPt
, bBodyOnly
);
743 else if ( !pFlyDrawObj
)
745 const SwRect
aRect( aPt
.getX(), aPt
.getY(), 1, 1 );
747 SwDrawContact
* pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
748 if ( pContact
->GetAnchorFrame( pObj
) &&
749 pContact
->GetAnchorFrame( pObj
)->IsPageFrame() )
750 pAnch
= pContact
->GetPageFrame();
752 pAnch
= pContact
->FindPage( aRect
);
755 if( pAnch
&& !pAnch
->IsProtected() )
756 m_aAnchorPoint
= pAnch
->GetFrameAnchorPos( ::HasWrap( pObj
) );
762 void SwDrawView::ShowDragAnchor()
764 SdrHdl
* pHdl
= maHdlList
.GetHdl(SdrHdlKind::Anchor
);
766 pHdl
= maHdlList
.GetHdl(SdrHdlKind::Anchor_TR
);
771 pHdl
->SetPos(m_aAnchorPoint
);
775 void SwDrawView::MarkListHasChanged()
777 Imp().GetShell()->DrawSelChanged();
778 FmFormView::MarkListHasChanged();
782 void SwDrawView::ModelHasChanged()
784 // The ModelHasChanged() call in DrawingLayer also updates
785 // an eventually active text edit view (OutlinerView). This also leads
786 // to newly setting the background color for that edit view. Thus,
787 // this method rescues the current background color if an OutlinerView
788 // exists and re-establishes it then. To be more safe, the OutlinerView
789 // will be fetched again (maybe textedit has ended).
790 OutlinerView
* pView
= GetTextEditOutlinerView();
792 bool bColorWasSaved(false);
796 aBackColor
= pView
->GetBackgroundColor();
797 bColorWasSaved
= true;
801 FmFormView::ModelHasChanged();
805 pView
= GetTextEditOutlinerView();
809 pView
->SetBackgroundColor(aBackColor
);
814 void SwDrawView::MakeVisible( const tools::Rectangle
&rRect
, vcl::Window
& )
816 OSL_ENSURE( m_rImp
.GetShell()->GetWin(), "MakeVisible, unknown Window");
817 m_rImp
.GetShell()->MakeVisible( SwRect( rRect
) );
820 void SwDrawView::CheckPossibilities()
822 FmFormView::CheckPossibilities();
824 //In addition to the existing flags of the objects themselves,
825 //which are evaluated by the DrawingEngine, other circumstances
826 //lead to a protection.
827 //Objects that are anchored in frames need to be protected
828 //if the content of the frame is protected.
829 //OLE-Objects may themselves wish a resize protection (StarMath)
831 const SdrMarkList
&rMrkList
= GetMarkedObjectList();
832 bool bProtect
= false;
833 bool bSzProtect
= false;
836 for ( size_t i
= 0; !bProtect
&& i
< rMrkList
.GetMarkCount(); ++i
)
838 const SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
839 const SwFrame
*pFrame
= nullptr;
840 if ( auto pVirtFlyDrawObj
= dynamic_cast< const SwVirtFlyDrawObj
*>( pObj
) )
842 const SwFlyFrame
*pFly
= pVirtFlyDrawObj
->GetFlyFrame();
845 pFrame
= pFly
->GetAnchorFrame();
846 if ( pFly
->Lower() && pFly
->Lower()->IsNoTextFrame() )
848 const SwNoTextFrame
*const pNTF(static_cast<const SwNoTextFrame
*>(pFly
->Lower()));
849 const SwOLENode
*const pOLENd
= pNTF
->GetNode()->GetOLENode();
850 const SwGrfNode
*const pGrfNd
= pNTF
->GetNode()->GetGrfNode();
854 const uno::Reference
< embed::XEmbeddedObject
> xObj
= const_cast< SwOLEObj
& >(pOLENd
->GetOLEObj()).GetOleRef();
858 // --> improvement for the future, when more
859 // than one Writer fly frame can be selected.
861 // TODO/LATER: retrieve Aspect - from where?!
862 bSzProtect
|= ( embed::EmbedMisc::EMBED_NEVERRESIZE
& xObj
->getStatus( embed::Aspects::MSOLE_CONTENT
) ) != 0;
864 // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
865 SwDoc
* pDoc
= Imp().GetShell()->GetDoc();
866 const bool bProtectMathPos
= SotExchange::IsMath( xObj
->getClassID() )
867 && RndStdIds::FLY_AS_CHAR
== pFly
->GetFormat()->GetAnchor().GetAnchorId()
868 && pDoc
->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT
);
870 m_bMoveProtect
= true;
875 // RotGrfFlyFrame: GraphicNode allows rotation(s). The loop ew are in stops
876 // as soon as bMoveProtect is set, but since rotation is valid only with
877 // a single object selected this makes no difference
885 SwDrawContact
*pC
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
887 pFrame
= pC
->GetAnchorFrame( pObj
);
890 bProtect
= pFrame
->IsProtected(); //Frames, areas etc.
892 SwFrameFormat
* pFrameFormat( ::FindFrameFormat( const_cast<SdrObject
*>(pObj
) ) );
895 OSL_FAIL( "<SwDrawView::CheckPossibilities()> - missing frame format" );
898 else if ((RndStdIds::FLY_AS_CHAR
== pFrameFormat
->GetAnchor().GetAnchorId()) &&
899 rMrkList
.GetMarkCount() > 1 )
905 m_bMoveProtect
|= bProtect
;
906 m_bResizeProtect
|= bProtect
|| bSzProtect
;
908 // RotGrfFlyFrame: allow rotation when SwGrfNode is selected and not size protected
909 m_bRotateFreeAllowed
|= bRotate
&& !bProtect
;
910 m_bRotate90Allowed
|= m_bRotateFreeAllowed
;
913 /// replace marked <SwDrawVirtObj>-objects by its reference object for delete marked objects.
914 void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView
& _rMarkView
)
916 SdrPageView
* pDrawPageView
= _rMarkView
.GetSdrPageView();
917 const SdrMarkList
& rMarkList
= _rMarkView
.GetMarkedObjectList();
919 if( !rMarkList
.GetMarkCount() )
922 // collect marked objects in a local data structure
923 std::vector
<SdrObject
*> aMarkedObjs
;
924 for( size_t i
= 0; i
< rMarkList
.GetMarkCount(); ++i
)
926 SdrObject
* pMarkedObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
927 aMarkedObjs
.push_back( pMarkedObj
);
929 // unmark all objects
930 _rMarkView
.UnmarkAllObj();
931 // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
933 while ( !aMarkedObjs
.empty() )
935 SdrObject
* pMarkObj
= aMarkedObjs
.back();
936 if ( auto pVirtObj
= dynamic_cast<SwDrawVirtObj
*>( pMarkObj
) )
938 SdrObject
* pRefObj
= &(pVirtObj
->ReferencedObj());
939 if ( !_rMarkView
.IsObjMarked( pRefObj
) )
941 _rMarkView
.MarkObj( pRefObj
, pDrawPageView
);
946 _rMarkView
.MarkObj( pMarkObj
, pDrawPageView
);
949 aMarkedObjs
.pop_back();
951 // sort marked list in order to assure consistent state in drawing layer
952 _rMarkView
.SortMarkedObjects();
955 SfxViewShell
* SwDrawView::GetSfxViewShell() const
957 return m_rImp
.GetShell()->GetSfxViewShell();
960 void SwDrawView::DeleteMarked()
962 SwDoc
* pDoc
= Imp().GetShell()->GetDoc();
963 SwRootFrame
*pTmpRoot
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
965 pTmpRoot
->StartAllAction();
966 pDoc
->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY
, nullptr);
967 // replace marked <SwDrawVirtObj>-objects by its reference objects.
968 if (SdrPageView
* pDrawPageView
= m_rImp
.GetPageView())
970 ReplaceMarkedDrawVirtObjs(pDrawPageView
->GetView());
973 // Check what textboxes have to be deleted afterwards.
974 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
975 std::vector
<SwFrameFormat
*> aTextBoxesToDelete
;
976 for (size_t i
= 0; i
< rMarkList
.GetMarkCount(); ++i
)
978 SdrObject
*pObject
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
979 SwContact
* pContact
= GetUserCall(pObject
);
980 SwFrameFormat
* pFormat
= pContact
->GetFormat();
981 if (pObject
->getChildrenOfSdrObject())
983 auto pChildTextBoxes
= SwTextBoxHelper::CollectTextBoxes(pObject
, pFormat
);
984 for (auto& rChildTextBox
: pChildTextBoxes
)
985 aTextBoxesToDelete
.push_back(rChildTextBox
);
988 if (SwFrameFormat
* pTextBox
= SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_DRAWFRMFMT
))
989 aTextBoxesToDelete
.push_back(pTextBox
);
992 if ( pDoc
->DeleteSelection( *this ) )
994 FmFormView::DeleteMarked();
995 ::FrameNotify( Imp().GetShell(), FLY_DRAG_END
);
998 // Only delete these now: earlier deletion would clear the mark list as well.
999 // Delete in reverse order, assuming that the container is sorted by anchor positions.
1000 for (int i
= aTextBoxesToDelete
.size() - 1; i
>= 0; --i
)
1002 SwFrameFormat
*& rpTextBox
= aTextBoxesToDelete
[i
];
1003 pDoc
->getIDocumentLayoutAccess().DelLayoutFormat(rpTextBox
);
1006 pDoc
->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY
, nullptr);
1008 pTmpRoot
->EndAllAction();
1011 // Create a new view-local UndoManager manager for Writer
1012 std::unique_ptr
<SdrUndoManager
> SwDrawView::createLocalTextUndoManager()
1014 std::unique_ptr
<SdrUndoManager
> pUndoManager(new SdrUndoManager
);
1015 pUndoManager
->SetDocShell(SfxObjectShell::Current());
1016 return pUndoManager
;
1019 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */