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 <svx/strings.hrc>
22 #include <svx/sdrobjectfilter.hxx>
23 #include <svx/svddrgmt.hxx>
24 #include <svx/svditer.hxx>
25 #include <svx/svdobj.hxx>
26 #include <svx/svdouno.hxx>
27 #include <svx/svdogrp.hxx>
28 #include <svx/svdocirc.hxx>
29 #include <svx/svdopath.hxx>
30 #include <svx/sxciaitm.hxx>
31 #include <svx/svdocapt.hxx>
32 #include <svx/xlnwtit.hxx>
33 #include <svx/xlnstwit.hxx>
34 #include <svx/xlnedwit.hxx>
35 #include <svx/xlnedit.hxx>
36 #include <svx/xlnstit.hxx>
37 #include <svx/svdomeas.hxx>
38 #include <svx/sdtagitm.hxx>
39 #include <svx/sdtacitm.hxx>
40 #include <svx/sdtaaitm.hxx>
41 #include <editeng/opaqitem.hxx>
42 #include <editeng/protitem.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdpagv.hxx>
45 #include <svx/dialmgr.hxx>
46 #include <tools/globname.hxx>
47 #include <sot/exchange.hxx>
48 #include <IDocumentDrawModelAccess.hxx>
49 #include <IDocumentSettingAccess.hxx>
50 #include <DocumentSettingManager.hxx>
51 #include <IDocumentState.hxx>
52 #include <IDocumentLayoutAccess.hxx>
53 #include <drawdoc.hxx>
54 #include <textboxhelper.hxx>
57 #include <frmtool.hxx>
58 #include <fmtfsize.hxx>
59 #include <fmtanchr.hxx>
60 #include <fmtornt.hxx>
61 #include <fmtsrnd.hxx>
62 #include <fmtcntnt.hxx>
63 #include <fmtflcnt.hxx>
64 #include <fmtcnct.hxx>
65 #include <swmodule.hxx>
67 #include <rootfrm.hxx>
68 #include <pagefrm.hxx>
69 #include <sectfrm.hxx>
71 #include <IDocumentUndoRedo.hxx>
73 #include <dflyobj.hxx>
74 #include <dcontact.hxx>
75 #include <viewimp.hxx>
81 #include <viewopt.hxx>
83 #include <notxtfrm.hxx>
86 #include <sortedobjs.hxx>
87 #include <HandleAnchorNodeChg.hxx>
88 #include <basegfx/polygon/b2dpolygon.hxx>
89 #include <comphelper/lok.hxx>
90 #include <sfx2/lokhelper.hxx>
91 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
93 #include <basegfx/polygon/b2dpolygontools.hxx>
94 #include <svx/svxids.hrc>
96 #include <com/sun/star/embed/EmbedMisc.hpp>
97 #include <com/sun/star/embed/Aspects.hpp>
98 #include <com/sun/star/embed/XEmbeddedObject.hpp>
100 #include <svx/srchdlg.hxx>
104 using namespace com::sun::star
;
107 * set line starts and ends for the object to be created
112 ::basegfx::B2DPolyPolygon
getPolygon(const char* pResId
, const SdrModel
& rModel
)
114 ::basegfx::B2DPolyPolygon aRetval
;
115 XLineEndListRef
pLineEndList(rModel
.GetLineEndList());
117 if( pLineEndList
.is() )
119 OUString
aArrowName( SvxResId(pResId
) );
120 tools::Long nCount
= pLineEndList
->Count();
122 for( nIndex
= 0; nIndex
< nCount
; nIndex
++ )
124 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nIndex
);
125 if( pEntry
->GetName() == aArrowName
)
127 aRetval
= pEntry
->GetLineEnd();
138 SwFlyFrame
*GetFlyFromMarked( const SdrMarkList
*pLst
, SwViewShell
*pSh
)
141 pLst
= pSh
->HasDrawView() ? &pSh
->Imp()->GetDrawView()->GetMarkedObjectList():nullptr;
143 if ( pLst
&& pLst
->GetMarkCount() == 1 )
145 SdrObject
*pO
= pLst
->GetMark( 0 )->GetMarkedSdrObj();
146 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pO
))
147 return pVirtO
->GetFlyFrame();
152 static void lcl_GrabCursor( SwFEShell
* pSh
, SwFlyFrame
* pOldSelFly
)
154 const SwFrameFormat
*pFlyFormat
= pSh
->SelFlyGrabCursor();
155 if( pFlyFormat
&& !pSh
->ActionPend() &&
156 (!pOldSelFly
|| pOldSelFly
->GetFormat() != pFlyFormat
) )
158 // now call set macro if applicable
159 pSh
->GetFlyMacroLnk().Call( static_cast<const SwFlyFrameFormat
*>(pFlyFormat
) );
160 // if a dialog was started inside a macro, then
161 // MouseButtonUp arrives at macro and not to us. Therefore
162 // flag is always set here and will never be switched to
163 // respective Shell !!!!!!!
165 g_bNoInterrupt
= false;
167 else if( !pFlyFormat
|| RES_DRAWFRMFMT
== pFlyFormat
->Which() )
169 // --> assure consistent cursor
172 pSh
->SetCursor( pSh
->Imp()->GetDrawView()->GetAllMarkedRect().TopLeft(), true);
176 bool SwFEShell::SelectObj( const Point
& rPt
, sal_uInt8 nFlag
, SdrObject
*pObj
)
178 SwDrawView
*pDView
= Imp()->GetDrawView();
181 CurrShell
aCurr( this );
182 StartAction(); // action is necessary to assure only one AttrChgdNotify
183 // (e.g. due to Unmark->MarkListHasChgd) arrives
185 const SdrMarkList
&rMrkList
= pDView
->GetMarkedObjectList();
186 const bool bHadSelection
= rMrkList
.GetMarkCount();
187 const bool bAddSelect
= 0 != (SW_ADD_SELECT
& nFlag
);
188 const bool bEnterGroup
= 0 != (SW_ENTER_GROUP
& nFlag
);
189 SwFlyFrame
* pOldSelFly
= nullptr;
190 const Point
aOldPos( pDView
->GetAllMarkedRect().TopLeft() );
194 // call Unmark when !bAddSelect or if fly was selected
195 bool bUnmark
= !bAddSelect
;
197 if ( rMrkList
.GetMarkCount() == 1 )
199 // if fly was selected, deselect it first
200 pOldSelFly
= ::GetFlyFromMarked( &rMrkList
, this );
203 const sal_uInt16 nType
= GetCntType();
204 if( nType
!= CNT_TXT
|| (SW_LEAVE_FRAME
& nFlag
) ||
205 ( pOldSelFly
->GetFormat()->GetProtect().IsContentProtected()
206 && !IsReadOnlyAvailable() ))
208 // If a fly is deselected, which contains graphic, OLE or
209 // otherwise, the cursor should be removed from it.
210 // Similar if a fly with protected content is deselected.
211 // For simplicity we put the cursor next to the upper-left
213 Point
aPt( pOldSelFly
->getFrameArea().Pos() );
214 aPt
.setX(aPt
.getX() - 1);
215 bool bUnLockView
= !IsViewLocked();
217 SetCursor( aPt
, true );
221 if ( nType
& CNT_GRF
&&
222 static_cast<SwNoTextFrame
*>(pOldSelFly
->Lower())->HasAnimation() )
224 GetWin()->Invalidate( pOldSelFly
->getFrameArea().SVRect() );
228 if ( SdrDragMode::Crop
== GetDragMode() )
229 SetDragMode( SdrDragMode::Move
);
238 pOldSelFly
->SelectionHasChanged(this);
249 OSL_ENSURE( !bEnterGroup
, "SW_ENTER_GROUP is not supported" );
250 pDView
->MarkObj( pObj
, Imp()->GetPageView() );
254 // tolerance limit of Drawing-SS
255 const auto nHdlSizePixel
= Imp()->GetDrawView()->GetMarkHdlSizePixel();
256 const short nMinMove
= static_cast<short>(GetOut()->PixelToLogic(Size(nHdlSizePixel
/2, 0)).Width());
257 pDView
->MarkObj( rPt
, nMinMove
, bAddSelect
, bEnterGroup
);
260 const bool bRet
= 0 != rMrkList
.GetMarkCount();
262 if ( rMrkList
.GetMarkCount() > 1 )
264 // It sucks if Drawing objects were selected and now
265 // additionally a fly is selected.
266 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
268 SdrObject
*pTmpObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
269 bool bForget
= dynamic_cast<const SwVirtFlyDrawObj
*>( pTmpObj
) != nullptr;
273 pDView
->MarkObj( pTmpObj
, Imp()->GetPageView(), bAddSelect
, bEnterGroup
);
279 if ( rMrkList
.GetMarkCount() == 1 )
281 SwFlyFrame
*pSelFly
= ::GetFlyFromMarked( &rMrkList
, this );
283 pSelFly
->SelectionHasChanged(this);
286 if (!(nFlag
& SW_ALLOW_TEXTBOX
))
288 // If the fly frame is a textbox of a shape, then select the shape instead.
289 for (size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
291 SdrObject
* pObject
= rMrkList
.GetMark(i
)->GetMarkedSdrObj();
292 SwFrameFormat
* pFormat
= GetUserCall(pObject
)->GetFormat();
293 if (SwFrameFormat
* pShapeFormat
= SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_FLYFRMFMT
))
295 SdrObject
* pShape
= pShapeFormat
->FindSdrObject();
297 pDView
->MarkObj(pShape
, Imp()->GetPageView(), bAddSelect
, bEnterGroup
);
305 ::lcl_GrabCursor(this, pOldSelFly
);
306 if ( GetCntType() & CNT_GRF
)
308 const SwFlyFrame
*pTmp
= GetFlyFromMarked( &rMrkList
, this );
309 OSL_ENSURE( pTmp
, "Graphic without Fly" );
310 if ( static_cast<const SwNoTextFrame
*>(pTmp
->Lower())->HasAnimation() )
311 static_cast<const SwNoTextFrame
*>(pTmp
->Lower())->StopAnimation( GetOut() );
314 else if ( !pOldSelFly
&& bHadSelection
)
315 SetCursor( aOldPos
, true);
317 if( bRet
|| !bHadSelection
)
320 // update status line
321 ::FrameNotify( this, bRet
? FLY_DRAG_START
: FLY_DRAG_END
);
328 * Description: MoveAnchor( nDir ) looked for an another Anchor for
329 * the selected drawing object (or fly frame) in the given direction.
330 * An object "as character" doesn't moves anyway.
331 * A page bounded object could move to the previous/next page with up/down,
332 * an object bounded "at paragraph" moves to the previous/next paragraph, too.
333 * An object bounded "at character" moves to the previous/next paragraph
334 * with up/down and to the previous/next character with left/right.
335 * If the anchor for at paragraph/character bounded objects has vertical or
336 * right_to_left text direction, the directions for up/down/left/right will
337 * interpreted accordingly.
338 * An object bounded "at fly" takes the center of the actual anchor and looks
339 * for the nearest fly frame in the given direction.
342 static bool LessX( Point
const & aPt1
, Point
const & aPt2
, bool bOld
)
344 return aPt1
.getX() < aPt2
.getX()
345 || ( aPt1
.getX() == aPt2
.getX()
346 && ( aPt1
.getY() < aPt2
.getY()
347 || ( aPt1
.getY() == aPt2
.getY() && bOld
) ) );
349 static bool LessY( Point
const & aPt1
, Point
const & aPt2
, bool bOld
)
351 return aPt1
.getY() < aPt2
.getY()
352 || ( aPt1
.getY() == aPt2
.getY()
353 && ( aPt1
.getX() < aPt2
.getX()
354 || ( aPt1
.getX() == aPt2
.getX() && bOld
) ) );
357 bool SwFEShell::MoveAnchor( SwMove nDir
)
359 if (!Imp()->GetDrawView())
361 const SdrMarkList
& pMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
362 if (1 != pMrkList
.GetMarkCount())
365 SwFlyFrame
* pFly
= nullptr;
366 SdrObject
*pObj
= pMrkList
.GetMark( 0 )->GetMarkedSdrObj();
367 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
369 pFly
= pVirtO
->GetFlyFrame();
370 pOld
= pFly
->AnchorFrame();
373 pOld
= static_cast<SwDrawContact
*>(GetUserCall(pObj
))->GetAnchorFrame( pObj
);
377 SwFrame
* pNew
= pOld
;
379 SwAnchoredObject
* pAnchoredObj
= ::GetUserCall( pObj
)->GetAnchoredObj( pObj
);
380 SwFrameFormat
& rFormat
= pAnchoredObj
->GetFrameFormat();
381 SwFormatAnchor
aAnch( rFormat
.GetAnchor() );
382 RndStdIds nAnchorId
= aAnch
.GetAnchorId();
383 if ( RndStdIds::FLY_AS_CHAR
== nAnchorId
)
385 if( pOld
->IsVertical() )
387 if( pOld
->IsTextFrame() )
390 case SwMove::UP
: nDir
= SwMove::LEFT
; break;
391 case SwMove::DOWN
: nDir
= SwMove::RIGHT
; break;
392 case SwMove::LEFT
: nDir
= SwMove::DOWN
; break;
393 case SwMove::RIGHT
: nDir
= SwMove::UP
; break;
395 if( pOld
->IsRightToLeft() )
397 if( nDir
== SwMove::LEFT
)
398 nDir
= SwMove::RIGHT
;
399 else if( nDir
== SwMove::RIGHT
)
404 switch ( nAnchorId
) {
405 case RndStdIds::FLY_AT_PAGE
:
407 OSL_ENSURE( pOld
->IsPageFrame(), "Wrong anchor, page expected." );
408 if( SwMove::UP
== nDir
)
409 pNew
= pOld
->GetPrev();
410 else if( SwMove::DOWN
== nDir
)
411 pNew
= pOld
->GetNext();
412 if( pNew
&& pNew
!= pOld
)
414 aAnch
.SetPageNum( static_cast<SwPageFrame
*>(pNew
)->GetPhyPageNum() );
419 case RndStdIds::FLY_AT_CHAR
:
421 OSL_ENSURE(pOld
->IsTextFrame(), "Wrong anchor, text frame expected.");
422 if( SwMove::LEFT
== nDir
|| SwMove::RIGHT
== nDir
)
424 SwPosition pos
= *aAnch
.GetContentAnchor();
425 SwTextFrame
*const pOldFrame(static_cast<SwTextFrame
*>(pOld
));
426 TextFrameIndex
const nAct(pOldFrame
->MapModelToViewPos(pos
));
427 if( SwMove::LEFT
== nDir
)
432 pos
= pOldFrame
->MapViewToModelPos(nAct
- TextFrameIndex(1));
439 TextFrameIndex
const nMax(pOldFrame
->GetText().getLength());
443 pos
= pOldFrame
->MapViewToModelPos(nAct
+ TextFrameIndex(1));
448 if( pos
!= *aAnch
.GetContentAnchor())
449 aAnch
.SetAnchor( &pos
);
453 case RndStdIds::FLY_AT_PARA
:
455 OSL_ENSURE(pOld
->IsTextFrame(), "Wrong anchor, text frame expected.");
456 if( SwMove::UP
== nDir
)
457 pNew
= pOld
->FindPrev();
458 else if( SwMove::DOWN
== nDir
)
459 pNew
= pOld
->FindNext();
460 if( pNew
&& pNew
!= pOld
&& pNew
->IsContentFrame() )
462 SwTextFrame
*const pNewFrame(static_cast<SwTextFrame
*>(pNew
));
463 SwPosition
const pos
= pNewFrame
->MapViewToModelPos(
465 (bRet
&& pNewFrame
->GetText().getLength() != 0)
466 ? pNewFrame
->GetText().getLength() - 1
468 aAnch
.SetAnchor( &pos
);
471 else if( SwMove::UP
== nDir
|| SwMove::DOWN
== nDir
)
475 case RndStdIds::FLY_AT_FLY
:
477 OSL_ENSURE( pOld
->IsFlyFrame(), "Wrong anchor, fly frame expected.");
478 SwPageFrame
* pPage
= pOld
->FindPageFrame();
479 OSL_ENSURE( pPage
, "Where's my page?" );
480 SwFlyFrame
* pNewFly
= nullptr;
481 if( pPage
->GetSortedObjs() )
484 Point
aCenter( pOld
->getFrameArea().Left() + pOld
->getFrameArea().Width()/2,
485 pOld
->getFrameArea().Top() + pOld
->getFrameArea().Height()/2 );
487 for(SwAnchoredObject
* pAnchObj
: *pPage
->GetSortedObjs())
489 if( auto pTmp
= dynamic_cast<SwFlyFrame
*>( pAnchObj
) )
495 const SwFlyFrame
* pCheck
= pFly
? pTmp
: nullptr;
500 const SwFrame
*pNxt
= pCheck
->GetAnchorFrame();
501 pCheck
= pNxt
? pNxt
->FindFlyFrame() : nullptr;
503 if( pCheck
|| pTmp
->IsProtected() )
505 Point
aNew( pTmp
->getFrameArea().Left() +
506 pTmp
->getFrameArea().Width()/2,
507 pTmp
->getFrameArea().Top() +
508 pTmp
->getFrameArea().Height()/2 );
509 bool bAccept
= false;
513 bAccept
= LessX( aCenter
, aNew
, bOld
)
515 LessX( aNew
, aBest
, false ) );
520 bAccept
= LessX( aNew
, aCenter
, !bOld
)
522 LessX( aBest
, aNew
, true ) );
527 bAccept
= LessY( aNew
, aCenter
, !bOld
)
529 LessY( aBest
, aNew
, true ) );
534 bAccept
= LessY( aCenter
, aNew
, bOld
)
536 LessY( aNew
, aBest
, false ) );
552 SwPosition
aPos( *pNewFly
->GetFormat()->
553 GetContent().GetContentIdx());
554 aAnch
.SetAnchor( &aPos
);
564 // --> handle change of anchor node:
565 // if count of the anchor frame also change, the fly frames have to be
566 // re-created. Thus, delete all fly frames except the <this> before the
567 // anchor attribute is change and re-create them afterwards.
569 std::unique_ptr
<SwHandleAnchorNodeChg
, o3tl::default_delete
<SwHandleAnchorNodeChg
>> pHandleAnchorNodeChg
;
570 SwFlyFrameFormat
* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat
*>(&rFormat
) );
571 if ( pFlyFrameFormat
)
573 pHandleAnchorNodeChg
.reset(
574 new SwHandleAnchorNodeChg( *pFlyFrameFormat
, aAnch
));
576 rFormat
.GetDoc()->SetAttr( aAnch
, rFormat
);
578 // #i28701# - no call of method
579 // <CheckCharRectAndTopOfLine()> for to-character anchored
580 // Writer fly frame needed. This method call can cause a
581 // format of the anchor frame, which is no longer intended.
582 // Instead clear the anchor character rectangle and
583 // the top of line values for all to-character anchored objects.
584 pAnchoredObj
->ClearCharRectAndTopOfLine();
591 const SdrMarkList
* SwFEShell::GetMarkList_() const
593 const SdrMarkList
* pMarkList
= nullptr;
594 if( Imp()->GetDrawView() != nullptr )
595 pMarkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
599 FrameTypeFlags
SwFEShell::GetSelFrameType() const
601 FrameTypeFlags eType
;
603 // get marked frame list, and check if anything is selected
604 const SdrMarkList
* pMarkList
= GetMarkList_();
605 if( pMarkList
== nullptr || pMarkList
->GetMarkCount() == 0 )
606 eType
= FrameTypeFlags::NONE
;
609 // obtain marked item as fly frame; if no fly frame, it must
611 const SwFlyFrame
* pFly
= ::GetFlyFromMarked(pMarkList
, const_cast<SwFEShell
*>(this));
612 if ( pFly
!= nullptr )
614 if( pFly
->IsFlyLayFrame() )
615 eType
= FrameTypeFlags::FLY_FREE
;
616 else if( pFly
->IsFlyAtContentFrame() )
617 eType
= FrameTypeFlags::FLY_ATCNT
;
620 OSL_ENSURE( pFly
->IsFlyInContentFrame(), "New frametype?" );
621 eType
= FrameTypeFlags::FLY_INCNT
;
625 eType
= FrameTypeFlags::DRAWOBJ
;
631 // does the draw selection contain a control?
632 bool SwFEShell::IsSelContainsControl() const
636 // basically, copy the mechanism from GetSelFrameType(), but call
637 // CheckControl... if you get a drawing object
638 const SdrMarkList
* pMarkList
= GetMarkList_();
639 if( pMarkList
!= nullptr && pMarkList
->GetMarkCount() == 1 )
641 // if we have one marked object, get the SdrObject and check
642 // whether it contains a control
643 const SdrObject
* pSdrObject
= pMarkList
->GetMark( 0 )->GetMarkedSdrObj();
644 bRet
= pSdrObject
&& ::CheckControlLayer( pSdrObject
);
649 void SwFEShell::ScrollTo( const Point
&rPt
)
651 const SwRect
aRect( rPt
, rPt
);
652 if ( IsScrollMDI( this, aRect
) &&
653 (!Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ||
654 Imp()->IsDragPossible( rPt
)) )
656 ScrollMDI( this, aRect
, SCROLLVAL
, SCROLLVAL
);
660 void SwFEShell::SetDragMode( SdrDragMode eDragMode
)
662 if ( Imp()->HasDrawView() )
663 Imp()->GetDrawView()->SetDragMode( eDragMode
);
666 SdrDragMode
SwFEShell::GetDragMode() const
668 SdrDragMode nRet
= SdrDragMode(0);
669 if ( Imp()->HasDrawView() )
671 nRet
= Imp()->GetDrawView()->GetDragMode();
676 void SwFEShell::StartCropImage()
678 if ( !Imp()->HasDrawView() )
682 SdrView
*pView
= Imp()->GetDrawView();
685 const SdrMarkList
&rMarkList
= pView
->GetMarkedObjectList();
686 if( 0 == rMarkList
.GetMarkCount() ) {
687 // No object selected
691 // If more than a single SwVirtFlyDrawObj is selected, select only the first SwVirtFlyDrawObj
692 if ( rMarkList
.GetMarkCount() > 1 )
694 for ( size_t i
= 0; i
< rMarkList
.GetMarkCount(); ++i
)
696 SdrObject
*pTmpObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
697 bool bForget
= dynamic_cast<const SwVirtFlyDrawObj
*>( pTmpObj
) != nullptr;
701 pView
->MarkObj( pTmpObj
, Imp()->GetPageView() );
707 // Activate CROP mode
708 pView
->SetEditMode( SdrViewEditMode::Edit
);
709 SetDragMode( SdrDragMode::Crop
);
712 void SwFEShell::BeginDrag( const Point
* pPt
, bool bIsShift
)
714 SdrView
*pView
= Imp()->GetDrawView();
715 if ( pView
&& pView
->AreObjectsMarked() )
717 m_pChainFrom
.reset();
719 SdrHdl
* pHdl
= pView
->PickHandle( *pPt
);
720 if (pView
->BegDragObj( *pPt
, nullptr, pHdl
))
721 pView
->GetDragMethod()->SetShiftPressed( bIsShift
);
722 ::FrameNotify( this );
726 void SwFEShell::Drag( const Point
*pPt
, bool )
728 OSL_ENSURE( Imp()->HasDrawView(), "Drag without DrawView?" );
729 if ( HasDrawViewDrag() )
732 Imp()->GetDrawView()->MovDragObj( *pPt
);
733 Imp()->GetDrawView()->ShowDragAnchor();
734 ::FrameNotify( this );
738 void SwFEShell::EndDrag()
740 OSL_ENSURE( Imp()->HasDrawView(), "EndDrag without DrawView?" );
741 SdrView
*pView
= Imp()->GetDrawView();
742 if ( !pView
->IsDragObj() )
745 for(SwViewShell
& rSh
: GetRingContainer())
748 StartUndo( SwUndoId::START
);
750 // #50778# Bug during dragging: In StartAction a HideShowXor is called.
751 // In EndDragObj() this is reversed, for no reason and even wrong.
752 // To restore consistency we should bring up the Xor again.
754 // Reanimation from the hack #50778 to fix bug #97057
755 // May be not the best solution, but the one with lowest risc at the moment.
756 // pView->ShowShownXor( GetOut() );
760 // DrawUndo on to flyframes are not stored
761 // The flys change the flag.
762 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
763 ChgAnchor( RndStdIds::FLY_AT_PARA
, true );
765 EndUndo( SwUndoId::END
);
767 for(SwViewShell
& rSh
: GetRingContainer())
770 if( auto pCursorShell
= dynamic_cast<SwCursorShell
*>(&rSh
) )
771 pCursorShell
->CallChgLnk();
774 GetDoc()->getIDocumentState().SetModified();
775 ::FrameNotify( this );
778 void SwFEShell::BreakDrag()
780 OSL_ENSURE( Imp()->HasDrawView(), "BreakDrag without DrawView?" );
781 if( HasDrawViewDrag() )
782 Imp()->GetDrawView()->BrkDragObj();
786 // If a fly is selected, pulls the crsr in the first ContentFrame
787 const SwFrameFormat
* SwFEShell::SelFlyGrabCursor()
789 if ( Imp()->HasDrawView() )
791 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
792 SwFlyFrame
*pFly
= ::GetFlyFromMarked( &rMrkList
, this );
796 SwContentFrame
*pCFrame
= pFly
->ContainsContent();
799 // --> assure, that the cursor is consistent.
802 SwPaM
*pCursor
= GetCursor();
804 if (pCFrame
->IsTextFrame())
806 *pCursor
->GetPoint() = static_cast<SwTextFrame
*>(pCFrame
)
807 ->MapViewToModelPos(TextFrameIndex(0));
811 assert(pCFrame
->IsNoTextFrame());
812 SwContentNode
*const pCNode
= static_cast<SwNoTextFrame
*>(pCFrame
)->GetNode();
813 pCursor
->GetPoint()->nNode
= *pCNode
;
814 pCursor
->GetPoint()->nContent
.Assign( pCNode
, 0 );
817 SwRect
& rChrRect
= const_cast<SwRect
&>(GetCharRect());
818 rChrRect
= pFly
->getFramePrintArea();
819 rChrRect
.Pos() += pFly
->getFrameArea().Pos();
820 GetCursorDocPos() = rChrRect
.Pos();
822 return pFly
->GetFormat();
828 // Selection to above/below (Z-Order)
829 static void lcl_NotifyNeighbours( const SdrMarkList
*pLst
)
831 // Rules for evasion have changed.
832 // 1. The environment of the fly and everything inside should be notified
833 // 2. The content of the frame itself has to be notified
834 // 3. Frames displaced by the frame have to be notified
835 // 4. Also Drawing objects can displace frames
836 for( size_t j
= 0; j
< pLst
->GetMarkCount(); ++j
)
839 bool bCheckNeighbours
= false;
840 sal_Int16 aHori
= text::HoriOrientation::NONE
;
842 SdrObject
*pO
= pLst
->GetMark( j
)->GetMarkedSdrObj();
843 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pO
))
845 SwFlyFrame
*pFly
= pVirtO
->GetFlyFrame();
847 const SwFormatHoriOrient
&rHori
= pFly
->GetFormat()->GetHoriOrient();
848 aHori
= rHori
.GetHoriOrient();
849 if( text::HoriOrientation::NONE
!= aHori
&& text::HoriOrientation::CENTER
!= aHori
&&
850 pFly
->IsFlyAtContentFrame() )
852 bCheckNeighbours
= true;
853 pFly
->InvalidatePos();
854 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pFly
);
855 aFrm
.Pos().AdjustY(1 );
858 pPage
= pFly
->FindPageFrame();
859 aRect
= pFly
->getFrameArea();
863 SwFrame
* pAnch
= static_cast<SwDrawContact
*>( GetUserCall(pO
) )->GetAnchorFrame( pO
);
866 pPage
= pAnch
->FindPageFrame();
867 // #i68520# - naming changed
868 aRect
= GetBoundRectOfAnchoredObj( pO
);
871 const size_t nCount
= pPage
->GetSortedObjs() ? pPage
->GetSortedObjs()->size() : 0;
872 for ( size_t i
= 0; i
< nCount
; ++i
)
874 SwAnchoredObject
* pAnchoredObj
= (*pPage
->GetSortedObjs())[i
];
875 SwFlyFrame
* pAct
= dynamic_cast<SwFlyFrame
*>(pAnchoredObj
);
879 SwRect
aTmpCalcPnt( pAct
->getFramePrintArea() );
880 aTmpCalcPnt
+= pAct
->getFrameArea().Pos();
881 if ( aRect
.IsOver( aTmpCalcPnt
) )
883 SwContentFrame
*pCnt
= pAct
->ContainsContent();
886 aTmpCalcPnt
= pCnt
->getFramePrintArea();
887 aTmpCalcPnt
+= pCnt
->getFrameArea().Pos();
888 if ( aRect
.IsOver( aTmpCalcPnt
) )
889 static_cast<SwFrame
*>(pCnt
)->Prepare( PrepareHint::FlyFrameAttributesChanged
);
890 pCnt
= pCnt
->GetNextContentFrame();
893 if ( bCheckNeighbours
&& pAct
->IsFlyAtContentFrame() )
895 const SwFormatHoriOrient
&rH
= pAct
->GetFormat()->GetHoriOrient();
896 if ( rH
.GetHoriOrient() == aHori
&&
897 pAct
->getFrameArea().Top() <= aRect
.Bottom() &&
898 pAct
->getFrameArea().Bottom() >= aRect
.Top() )
900 pAct
->InvalidatePos();
901 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pAct
);
902 aFrm
.Pos().AdjustY(1 );
909 void SwFEShell::SetLineEnds(SfxItemSet
& rAttr
, SdrObject
const & rObj
, sal_uInt16 nSlotId
)
911 SdrModel
& rModel(rObj
.getSdrModelFromSdrObject());
913 if ( !(nSlotId
== SID_LINE_ARROW_START
||
914 nSlotId
== SID_LINE_ARROW_END
||
915 nSlotId
== SID_LINE_ARROWS
||
916 nSlotId
== SID_LINE_ARROW_CIRCLE
||
917 nSlotId
== SID_LINE_CIRCLE_ARROW
||
918 nSlotId
== SID_LINE_ARROW_SQUARE
||
919 nSlotId
== SID_LINE_SQUARE_ARROW
||
920 nSlotId
== SID_DRAW_MEASURELINE
) )
923 // set attributes of line start and ends
926 ::basegfx::B2DPolyPolygon
aArrow( getPolygon( RID_SVXSTR_ARROW
, rModel
) );
927 if( !aArrow
.count() )
929 ::basegfx::B2DPolygon aNewArrow
;
930 aNewArrow
.append(::basegfx::B2DPoint(10.0, 0.0));
931 aNewArrow
.append(::basegfx::B2DPoint(0.0, 30.0));
932 aNewArrow
.append(::basegfx::B2DPoint(20.0, 30.0));
933 aNewArrow
.setClosed(true);
934 aArrow
.append(aNewArrow
);
938 ::basegfx::B2DPolyPolygon
aCircle( getPolygon( RID_SVXSTR_CIRCLE
, rModel
) );
939 if( !aCircle
.count() )
941 ::basegfx::B2DPolygon aNewCircle
= ::basegfx::utils::createPolygonFromEllipse(::basegfx::B2DPoint(0.0, 0.0), 250.0, 250.0);
942 aNewCircle
.setClosed(true);
943 aCircle
.append(aNewCircle
);
947 ::basegfx::B2DPolyPolygon
aSquare( getPolygon( RID_SVXSTR_SQUARE
, rModel
) );
948 if( !aSquare
.count() )
950 ::basegfx::B2DPolygon aNewSquare
;
951 aNewSquare
.append(::basegfx::B2DPoint(0.0, 0.0));
952 aNewSquare
.append(::basegfx::B2DPoint(10.0, 0.0));
953 aNewSquare
.append(::basegfx::B2DPoint(10.0, 10.0));
954 aNewSquare
.append(::basegfx::B2DPoint(0.0, 10.0));
955 aNewSquare
.setClosed(true);
956 aSquare
.append(aNewSquare
);
959 SfxItemSet
aSet( rModel
.GetItemPool() );
960 tools::Long nWidth
= 100; // (1/100th mm)
962 // determine line width and calculate with it the line end width
963 if( aSet
.GetItemState( XATTR_LINEWIDTH
) != SfxItemState::DONTCARE
)
965 tools::Long nValue
= aSet
.Get( XATTR_LINEWIDTH
).GetValue();
972 case SID_LINE_ARROWS
:
973 case SID_DRAW_MEASURELINE
:
975 // connector with arrow ends
976 rAttr
.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW
), aArrow
));
977 rAttr
.Put(XLineStartWidthItem(nWidth
));
978 rAttr
.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW
), aArrow
));
979 rAttr
.Put(XLineEndWidthItem(nWidth
));
983 case SID_LINE_ARROW_START
:
984 case SID_LINE_ARROW_CIRCLE
:
985 case SID_LINE_ARROW_SQUARE
:
987 // connector with arrow start
988 rAttr
.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW
), aArrow
));
989 rAttr
.Put(XLineStartWidthItem(nWidth
));
993 case SID_LINE_ARROW_END
:
994 case SID_LINE_CIRCLE_ARROW
:
995 case SID_LINE_SQUARE_ARROW
:
997 // connector with arrow end
998 rAttr
.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW
), aArrow
));
999 rAttr
.Put(XLineEndWidthItem(nWidth
));
1004 // and again, for the still missing ends
1007 case SID_LINE_ARROW_CIRCLE
:
1010 rAttr
.Put(XLineEndItem(SvxResId(RID_SVXSTR_CIRCLE
), aCircle
));
1011 rAttr
.Put(XLineEndWidthItem(nWidth
));
1015 case SID_LINE_CIRCLE_ARROW
:
1018 rAttr
.Put(XLineStartItem(SvxResId(RID_SVXSTR_CIRCLE
), aCircle
));
1019 rAttr
.Put(XLineStartWidthItem(nWidth
));
1023 case SID_LINE_ARROW_SQUARE
:
1026 rAttr
.Put(XLineEndItem(SvxResId(RID_SVXSTR_SQUARE
), aSquare
));
1027 rAttr
.Put(XLineEndWidthItem(nWidth
));
1031 case SID_LINE_SQUARE_ARROW
:
1034 rAttr
.Put(XLineStartItem(SvxResId(RID_SVXSTR_SQUARE
), aSquare
));
1035 rAttr
.Put(XLineStartWidthItem(nWidth
));
1042 void SwFEShell::SelectionToTop( bool bTop
)
1044 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToTop without DrawView?" );
1045 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1046 OSL_ENSURE( rMrkList
.GetMarkCount(), "No object selected." );
1048 SwFlyFrame
*pFly
= ::GetFlyFromMarked( &rMrkList
, this );
1049 if ( pFly
&& pFly
->IsFlyInContentFrame() )
1054 Imp()->GetDrawView()->PutMarkedToTop();
1056 Imp()->GetDrawView()->MovMarkedToTop();
1057 ::lcl_NotifyNeighbours( &rMrkList
);
1058 GetDoc()->getIDocumentState().SetModified();
1062 void SwFEShell::SelectionToBottom( bool bBottom
)
1064 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToBottom without DrawView?" );
1065 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1066 OSL_ENSURE( rMrkList
.GetMarkCount(), "No object selected." );
1068 SwFlyFrame
*pFly
= ::GetFlyFromMarked( &rMrkList
, this );
1069 if ( pFly
&& pFly
->IsFlyInContentFrame() )
1074 Imp()->GetDrawView()->PutMarkedToBtm();
1076 Imp()->GetDrawView()->MovMarkedToBtm();
1077 ::lcl_NotifyNeighbours( &rMrkList
);
1078 GetDoc()->getIDocumentState().SetModified();
1082 // Object above/below the document? 2 Controls, 1 Heaven, 0 Hell,
1083 // SDRLAYER_NOTFOUND Ambiguous
1084 SdrLayerID
SwFEShell::GetLayerId() const
1086 if ( !Imp()->HasDrawView() )
1087 return SDRLAYER_NOTFOUND
;
1089 SdrLayerID nRet
= SDRLAYER_NOTFOUND
;
1090 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1091 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
1093 const SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
1096 if ( nRet
== SDRLAYER_NOTFOUND
)
1097 nRet
= pObj
->GetLayer();
1098 else if ( nRet
!= pObj
->GetLayer() )
1100 return SDRLAYER_NOTFOUND
;
1106 // Object above/below the document
1107 // Note: only visible objects can be marked. Thus, objects with invisible
1108 // layer IDs have not to be considered.
1109 // If <SwFEShell> exists, layout exists!!
1110 void SwFEShell::ChangeOpaque( SdrLayerID nLayerId
)
1112 if ( !Imp()->HasDrawView() )
1115 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1116 const IDocumentDrawModelAccess
& rIDDMA
= getIDocumentDrawModelAccess();
1117 // correct type of <nControls>
1118 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
1120 SdrObject
* pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
1123 // or group objects containing controls.
1125 // consider that a member of a drawing group has been selected.
1126 const SwContact
* pContact
= ::GetUserCall( pObj
);
1127 OSL_ENSURE( pContact
&& pContact
->GetMaster(), "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!" );
1128 const bool bControlObj
= ( pContact
&& pContact
->GetMaster() )
1129 ? ::CheckControlLayer( pContact
->GetMaster() )
1130 : ::CheckControlLayer( pObj
);
1131 if ( !bControlObj
&& pObj
->GetLayer() != nLayerId
)
1133 pObj
->SetLayer( nLayerId
);
1134 InvalidateWindows( SwRect( pObj
->GetCurrentBoundRect() ) );
1135 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
1137 SwFormat
*pFormat
= pVirtO
->GetFlyFrame()->GetFormat();
1138 SvxOpaqueItem
aOpa( pFormat
->GetOpaque() );
1139 aOpa
.SetValue( nLayerId
== rIDDMA
.GetHellId() );
1140 pFormat
->SetFormatAttr( aOpa
);
1144 GetDoc()->getIDocumentState().SetModified();
1147 void SwFEShell::SelectionToHeaven()
1149 ChangeOpaque( getIDocumentDrawModelAccess().GetHeavenId() );
1152 void SwFEShell::SelectionToHell()
1154 ChangeOpaque( getIDocumentDrawModelAccess().GetHellId() );
1157 size_t SwFEShell::IsObjSelected() const
1159 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1162 return Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount();
1165 bool SwFEShell::IsFrameSelected() const
1167 if ( !Imp()->HasDrawView() )
1170 return nullptr != ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
1171 const_cast<SwFEShell
*>(this) );
1174 bool SwFEShell::IsObjSelected( const SdrObject
& rObj
) const
1176 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1179 return Imp()->GetDrawView()->IsObjMarked( &rObj
);
1182 bool SwFEShell::IsRotationOfSwGrfNodePossible() const
1184 // RotGrfFlyFrame: check if RotationMode is possible
1185 const SdrView
*pSdrView
= Imp()->GetDrawView();
1189 const SdrMarkList
& rList(pSdrView
->GetMarkedObjectList());
1191 if(1 == rList
.GetMarkCount())
1193 const SwVirtFlyDrawObj
* pVirtFlyDraw(dynamic_cast< const SwVirtFlyDrawObj
* >(rList
.GetMark(0)->GetMarkedSdrObj()));
1195 if(nullptr != pVirtFlyDraw
)
1197 return pVirtFlyDraw
->ContainsSwGrfNode();
1205 bool SwFEShell::IsObjSameLevelWithMarked(const SdrObject
* pObj
) const
1209 const SdrMarkList
& aMarkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1210 if (aMarkList
.GetMarkCount() == 0)
1214 SdrMark
* pM
=aMarkList
.GetMark(0);
1217 SdrObject
* pMarkObj
= pM
->GetMarkedSdrObj();
1218 if (pMarkObj
&& pMarkObj
->getParentSdrObjectFromSdrObject() == pObj
->getParentSdrObjectFromSdrObject())
1225 void SwFEShell::EndTextEdit()
1227 // Terminate the TextEditMode. If required (default if the object
1228 // does not contain any more text and does not carry attributes) the object
1229 // is deleted. All other objects marked are preserved.
1231 OSL_ENSURE( Imp()->HasDrawView() && Imp()->GetDrawView()->IsTextEdit(),
1232 "EndTextEdit a no Object" );
1235 SdrView
*pView
= Imp()->GetDrawView();
1236 SdrObject
*pObj
= pView
->GetTextEditObject();
1237 SdrObjUserCall
* pUserCall
= GetUserCall(pObj
);
1238 if( nullptr != pUserCall
)
1240 SdrObject
*pTmp
= static_cast<SwContact
*>(pUserCall
)->GetMaster();
1243 pUserCall
->Changed( *pTmp
, SdrUserCallType::Resize
, pTmp
->GetLastBoundRect() );
1245 if ( !pObj
->getParentSdrObjectFromSdrObject() )
1247 if ( SdrEndTextEditKind::ShouldBeDeleted
== pView
->SdrEndTextEdit(true) )
1249 if ( pView
->GetMarkedObjectList().GetMarkCount() > 1 )
1251 SdrMarkList
aSave( pView
->GetMarkedObjectList() );
1252 aSave
.DeleteMark( aSave
.FindObject( pObj
) );
1253 if ( aSave
.GetMarkCount() )
1256 pView
->MarkObj( pObj
, Imp()->GetPageView() );
1259 for ( size_t i
= 0; i
< aSave
.GetMarkCount(); ++i
)
1260 pView
->MarkObj( aSave
.GetMark( i
)->GetMarkedSdrObj(), Imp()->GetPageView() );
1267 pView
->SdrEndTextEdit();
1269 if (comphelper::LibreOfficeKit::isActive())
1270 SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_LOCK
, "rectangle", "EMPTY");
1275 bool SwFEShell::IsInsideSelectedObj( const Point
&rPt
)
1277 if( Imp()->HasDrawView() )
1279 SwDrawView
*pDView
= Imp()->GetDrawView();
1281 if( pDView
->GetMarkedObjectList().GetMarkCount() &&
1282 pDView
->IsMarkedObjHit( rPt
) )
1290 bool SwFEShell::IsObjSelectable( const Point
& rPt
)
1292 CurrShell
aCurr(this);
1293 SwDrawView
*pDView
= Imp()->GetDrawView();
1298 const auto nOld
= pDView
->GetHitTolerancePixel();
1299 pDView
->SetHitTolerancePixel( pDView
->GetMarkHdlSizePixel()/2 );
1301 bRet
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMARKABLE
) != nullptr;
1302 pDView
->SetHitTolerancePixel( nOld
);
1307 SdrObject
* SwFEShell::GetObjAt( const Point
& rPt
)
1309 SdrObject
* pRet
= nullptr;
1310 CurrShell
aCurr(this);
1311 SwDrawView
*pDView
= Imp()->GetDrawView();
1315 const auto nOld
= pDView
->GetHitTolerancePixel();
1316 pDView
->SetHitTolerancePixel( pDView
->GetMarkHdlSizePixel()/2 );
1318 pRet
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMARKABLE
);
1319 pDView
->SetHitTolerancePixel( nOld
);
1324 // Test if there is an object at that position and if it should be selected.
1325 bool SwFEShell::ShouldObjectBeSelected(const Point
& rPt
)
1327 CurrShell
aCurr(this);
1328 SwDrawView
*pDrawView
= Imp()->GetDrawView();
1334 const auto nOld(pDrawView
->GetHitTolerancePixel());
1336 pDrawView
->SetHitTolerancePixel(pDrawView
->GetMarkHdlSizePixel()/2);
1337 SdrObject
* pObj
= pDrawView
->PickObj(rPt
, pDrawView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMARKABLE
);
1338 pDrawView
->SetHitTolerancePixel(nOld
);
1343 const IDocumentDrawModelAccess
& rIDDMA
= getIDocumentDrawModelAccess();
1345 // Do not select object in background which is overlapping this text
1346 // at the given position.
1347 bool bObjInBackground( false );
1349 if ( pObj
->GetLayer() == rIDDMA
.GetHellId() )
1351 const SwAnchoredObject
* pAnchoredObj
= ::GetUserCall( pObj
)->GetAnchoredObj( pObj
);
1352 const SwFrameFormat
& rFormat
= pAnchoredObj
->GetFrameFormat();
1353 const SwFormatSurround
& rSurround
= rFormat
.GetSurround();
1354 if ( rSurround
.GetSurround() == css::text::WrapTextMode_THROUGH
)
1356 bObjInBackground
= true;
1360 if ( bObjInBackground
)
1362 const SwPageFrame
* pPageFrame
= GetLayout()->GetPageAtPos( rPt
);
1365 const SwContentFrame
* pContentFrame( pPageFrame
->ContainsContent() );
1366 while ( pContentFrame
)
1368 if ( pContentFrame
->UnionFrame().IsInside( rPt
) )
1370 const SwTextFrame
* pTextFrame
=
1371 dynamic_cast<const SwTextFrame
*>(pContentFrame
);
1374 SwPosition
aPos(GetDoc()->GetNodes());
1375 Point
aTmpPt( rPt
);
1376 if (pTextFrame
->GetKeyCursorOfst(&aPos
, aTmpPt
))
1378 SwRect aCursorCharRect
;
1379 if (pTextFrame
->GetCharRect(aCursorCharRect
,
1382 if ( aCursorCharRect
.IsOver( SwRect( pObj
->GetLastBoundRect() ) ) )
1396 pContentFrame
= pContentFrame
->GetNextContentFrame();
1401 // Don't select header / footer objects in body edition and vice-versa
1402 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
1403 if (pContact
&& !pContact
->ObjAnchoredAtPage() )
1405 const SwPosition
& rPos
= pContact
->GetContentAnchor();
1406 bool bInHdrFtr
= GetDoc()->IsInHeaderFooter( rPos
.nNode
);
1407 if (IsHeaderFooterEdit() != bInHdrFtr
)
1415 const SdrPage
* pPage
= rIDDMA
.GetDrawModel()->GetPage(0);
1416 for(size_t a
= pObj
->GetOrdNum()+1; bRet
&& a
< pPage
->GetObjCount(); ++a
)
1418 SdrObject
*pCandidate
= pPage
->GetObj(a
);
1420 SwVirtFlyDrawObj
* pDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pCandidate
);
1421 if (pDrawObj
&& pDrawObj
->GetCurrentBoundRect().IsInside(rPt
))
1434 * If an object was selected, we assume its upper-left corner
1435 * otherwise the middle of the current CharRects.
1436 * Does the object include a control or groups,
1437 * which comprise only controls
1439 static bool lcl_IsControlGroup( const SdrObject
*pObj
)
1442 if(dynamic_cast<const SdrUnoObj
*>( pObj
) != nullptr)
1444 else if( auto pObjGroup
= dynamic_cast<const SdrObjGroup
*>( pObj
) )
1447 const SdrObjList
*pLst
= pObjGroup
->GetSubList();
1448 for ( size_t i
= 0; i
< pLst
->GetObjCount(); ++i
)
1449 if( !::lcl_IsControlGroup( pLst
->GetObj( i
) ) )
1457 class MarkableObjectsOnly
: public svx::ISdrObjectFilter
1460 explicit MarkableObjectsOnly( SdrPageView
* i_pPV
)
1465 virtual bool includeObject( const SdrObject
& i_rObject
) const override
1467 return m_pPV
&& m_pPV
->GetView().IsObjMarkable( &i_rObject
, m_pPV
);
1475 const SdrObject
* SwFEShell::GetBestObject( bool bNext
, GotoObjFlags eType
, bool bFlat
, const svx::ISdrObjectFilter
* pFilter
)
1477 if( !Imp()->HasDrawView() )
1480 const SdrObject
*pBest
= nullptr,
1483 const tools::Long nTmp
= bNext
? LONG_MAX
: 0;
1484 Point
aBestPos( nTmp
, nTmp
);
1485 Point
aTopPos( nTmp
, nTmp
);
1488 bool bNoDraw((GotoObjFlags::DrawAny
& eType
) == GotoObjFlags::NONE
);
1489 bool bNoFly((GotoObjFlags::FlyAny
& eType
) == GotoObjFlags::NONE
);
1491 if( !bNoFly
&& bNoDraw
)
1493 SwFlyFrame
*pFly
= GetCurrFrame( false )->FindFlyFrame();
1495 pBest
= pFly
->GetVirtDrawObj();
1497 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1498 SdrPageView
* pPV
= Imp()->GetDrawView()->GetSdrPageView();
1500 MarkableObjectsOnly
aDefaultFilter( pPV
);
1502 pFilter
= &aDefaultFilter
;
1504 if( !pBest
|| rMrkList
.GetMarkCount() == 1 )
1506 // Determine starting point
1507 SdrObjList
* pList
= nullptr;
1508 if ( rMrkList
.GetMarkCount() )
1510 const SdrObject
* pStartObj
= rMrkList
.GetMark(0)->GetMarkedSdrObj();
1511 if( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>( pStartObj
) )
1512 aPos
= pVirtFlyDrawObj
->GetFlyFrame()->getFrameArea().Pos();
1514 aPos
= pStartObj
->GetSnapRect().TopLeft();
1516 // If an object inside a group is selected, we want to
1517 // iterate over the group members.
1518 if ( ! pStartObj
->GetUserCall() )
1519 pList
= pStartObj
->getParentSdrObjListFromSdrObject();
1523 // If no object is selected, we check if we just entered a group.
1524 // In this case we want to iterate over the group members.
1525 aPos
= GetCharRect().Center();
1526 const SdrObject
* pStartObj
= pPV
? pPV
->GetCurrentGroup() : nullptr;
1527 if ( dynamic_cast<const SdrObjGroup
*>( pStartObj
) )
1528 pList
= pStartObj
->GetSubList();
1534 // A No object has been selected and no group has been entered or
1535 // B An object has been selected and it is not inside a group
1536 pList
= getIDocumentDrawModelAccess().GetDrawModel()->GetPage( 0 );
1539 OSL_ENSURE( pList
, "No object list to iterate" );
1541 SdrObjListIter
aObjIter( pList
, bFlat
? SdrIterMode::Flat
: SdrIterMode::DeepNoGroups
);
1542 while ( aObjIter
.IsMore() )
1544 SdrObject
* pObj
= aObjIter
.Next();
1545 SwVirtFlyDrawObj
*pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
);
1546 if( ( bNoFly
&& pVirtO
) ||
1547 ( bNoDraw
&& !pVirtO
) ||
1548 // Ignore TextBoxes of draw shapes here, so that
1549 // SwFEShell::SelectObj() won't jump back on this list, meaning
1550 // we never jump to the next draw shape.
1551 (pVirtO
&& pVirtO
->IsTextBox()) ||
1552 ( eType
== GotoObjFlags::DrawSimple
&& lcl_IsControlGroup( pObj
) ) ||
1553 ( eType
== GotoObjFlags::DrawControl
&& !lcl_IsControlGroup( pObj
) ) ||
1554 !pFilter
->includeObject( *pObj
) )
1558 SwFlyFrame
*pFly
= pVirtO
->GetFlyFrame();
1559 if( GotoObjFlags::FlyAny
!= ( GotoObjFlags::FlyAny
& eType
) )
1563 case GotoObjFlags::FlyFrame
:
1564 if ( pFly
->Lower() && pFly
->Lower()->IsNoTextFrame() )
1567 case GotoObjFlags::FlyGrf
:
1568 if ( pFly
->Lower() &&
1569 (!pFly
->Lower()->IsNoTextFrame() ||
1570 !static_cast<SwNoTextFrame
*>(pFly
->Lower())->GetNode()->GetGrfNode()))
1573 case GotoObjFlags::FlyOLE
:
1574 if ( pFly
->Lower() &&
1575 (!pFly
->Lower()->IsNoTextFrame() ||
1576 !static_cast<SwNoTextFrame
*>(pFly
->Lower())->GetNode()->GetOLENode()))
1582 aCurPos
= pFly
->getFrameArea().Pos();
1585 aCurPos
= pObj
->GetSnapRect().TopLeft();
1587 // Special case if another object is on same Y.
1588 if( aCurPos
!= aPos
&& // only when it is not me
1589 aCurPos
.getY() == aPos
.getY() && // Y positions equal
1590 (bNext
? (aCurPos
.getX() > aPos
.getX()) : // lies next to me
1591 (aCurPos
.getX() < aPos
.getX())) ) // " reverse
1593 aBestPos
= Point( nTmp
, nTmp
);
1594 SdrObjListIter
aTmpIter( pList
, bFlat
? SdrIterMode::Flat
: SdrIterMode::DeepNoGroups
);
1595 while ( aTmpIter
.IsMore() )
1597 SdrObject
* pTmpObj
= aTmpIter
.Next();
1598 pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pTmpObj
);
1599 if( ( bNoFly
&& pVirtO
) || ( bNoDraw
&& !pVirtO
) )
1603 aCurPos
= pVirtO
->GetFlyFrame()->getFrameArea().Pos();
1606 aCurPos
= pTmpObj
->GetCurrentBoundRect().TopLeft();
1608 if( aCurPos
!= aPos
&& aCurPos
.Y() == aPos
.Y() &&
1609 (bNext
? (aCurPos
.getX() > aPos
.getX()) : // lies next to me
1610 (aCurPos
.getX() < aPos
.getX())) && // " reverse
1611 (bNext
? (aCurPos
.getX() < aBestPos
.getX()) : // better as best
1612 (aCurPos
.getX() > aBestPos
.getX())) ) // " reverse
1622 (bNext
? (aPos
.getY() < aCurPos
.getY()) : // only below me
1623 (aPos
.getY() > aCurPos
.getY())) && // " reverse
1624 (bNext
? (aBestPos
.getY() > aCurPos
.getY()) : // closer below
1625 (aBestPos
.getY() < aCurPos
.getY()))
1627 (aBestPos
.getY() == aCurPos
.getY() &&
1628 (bNext
? (aBestPos
.getX() > aCurPos
.getX()) : // further left
1629 (aBestPos
.getX() < aCurPos
.getX())))) // " reverse
1636 if( (bNext
? (aTopPos
.getY() > aCurPos
.getY()) : // higher as best
1637 (aTopPos
.getY() < aCurPos
.getY())) || // " reverse
1638 (aTopPos
.getY() == aCurPos
.getY() &&
1639 (bNext
? (aTopPos
.getX() > aCurPos
.getX()) : // further left
1640 (aTopPos
.getX() < aCurPos
.getX())))) // " reverse
1646 // unfortunately nothing found
1647 if( bNext
? (aBestPos
.getX() == LONG_MAX
) : (aBestPos
.getX() == 0) )
1650 SvxSearchDialogWrapper::SetSearchLabel( bNext
? SearchLabel::EndWrapped
: SearchLabel::StartWrapped
);
1657 bool SwFEShell::GotoObj( bool bNext
, GotoObjFlags eType
)
1659 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty
);
1661 const SdrObject
* pBest
= GetBestObject( bNext
, eType
);
1665 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound
);
1669 const SwVirtFlyDrawObj
*pVirtO
= dynamic_cast<const SwVirtFlyDrawObj
*>(pBest
);
1672 const SwRect
& rFrame
= pVirtO
->GetFlyFrame()->getFrameArea();
1673 SelectObj( rFrame
.Pos(), 0, const_cast<SdrObject
*>(pBest
) );
1675 MakeVisible( rFrame
);
1679 SelectObj( Point(), 0, const_cast<SdrObject
*>(pBest
) );
1681 MakeVisible( pBest
->GetCurrentBoundRect() );
1687 bool SwFEShell::BeginCreate( SdrObjKind eSdrObjectKind
, const Point
&rPos
)
1691 if ( !Imp()->HasDrawView() )
1692 Imp()->MakeDrawView();
1694 if ( GetPageNumber( rPos
) )
1696 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind
);
1697 if ( eSdrObjectKind
== OBJ_CAPTION
)
1698 bRet
= Imp()->GetDrawView()->BegCreateCaptionObj(
1699 rPos
, Size( lMinBorder
- MINFLY
, lMinBorder
- MINFLY
),
1702 bRet
= Imp()->GetDrawView()->BegCreateObj( rPos
, GetOut() );
1706 ::FrameNotify( this, FLY_DRAG_START
);
1711 bool SwFEShell::BeginCreate( SdrObjKind eSdrObjectKind
, SdrInventor eObjInventor
,
1716 if ( !Imp()->HasDrawView() )
1717 Imp()->MakeDrawView();
1719 if ( GetPageNumber( rPos
) )
1721 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind
, eObjInventor
);
1722 bRet
= Imp()->GetDrawView()->BegCreateObj( rPos
, GetOut() );
1725 ::FrameNotify( this, FLY_DRAG_START
);
1729 void SwFEShell::MoveCreate( const Point
&rPos
)
1731 OSL_ENSURE( Imp()->HasDrawView(), "MoveCreate without DrawView?" );
1732 if ( GetPageNumber( rPos
) )
1735 Imp()->GetDrawView()->MovCreateObj( rPos
);
1736 ::FrameNotify( this );
1740 bool SwFEShell::EndCreate( SdrCreateCmd eSdrCreateCmd
)
1742 // To assure undo-object from the DrawEngine is not stored,
1743 // (we create our own undo-object!), temporarily switch-off Undo
1744 OSL_ENSURE( Imp()->HasDrawView(), "EndCreate without DrawView?" );
1745 if( !Imp()->GetDrawView()->IsGroupEntered() )
1747 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
1749 bool bCreate
= Imp()->GetDrawView()->EndCreateObj( eSdrCreateCmd
);
1750 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
1754 ::FrameNotify( this, FLY_DRAG_END
);
1758 if ( eSdrCreateCmd
== SdrCreateCmd::NextPoint
)
1760 ::FrameNotify( this );
1763 return ImpEndCreate();
1766 bool SwFEShell::ImpEndCreate()
1768 OSL_ENSURE( Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1,
1769 "New object not selected." );
1771 SdrObject
& rSdrObj
= *Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
1773 if( rSdrObj
.GetSnapRect().IsEmpty() )
1775 // preferably we forget the object, only gives problems
1776 Imp()->GetDrawView()->DeleteMarked();
1777 Imp()->GetDrawView()->UnmarkAll();
1778 ::FrameNotify( this, FLY_DRAG_END
);
1782 if( rSdrObj
.getParentSdrObjectFromSdrObject() )
1784 Point
aTmpPos( rSdrObj
.GetSnapRect().TopLeft() );
1785 Point
aNewAnchor( rSdrObj
.getParentSdrObjectFromSdrObject()->GetAnchorPos() );
1786 // OD 2004-04-05 #i26791# - direct object positioning for group members
1787 rSdrObj
.NbcSetRelativePos( aTmpPos
- aNewAnchor
);
1788 rSdrObj
.NbcSetAnchorPos( aNewAnchor
);
1789 ::FrameNotify( this );
1796 Imp()->GetDrawView()->UnmarkAll();
1798 const tools::Rectangle
&rBound
= rSdrObj
.GetSnapRect();
1799 Point
aPt( rBound
.TopRight() );
1801 // alien identifier should end up on defaults
1802 // duplications possible!!
1803 sal_uInt16 nIdent
= SdrInventor::Default
== rSdrObj
.GetObjInventor()
1804 ? rSdrObj
.GetObjIdentifier()
1807 // default for controls character bound, otherwise paragraph bound.
1808 SwFormatAnchor aAnch
;
1809 const SwFrame
*pAnch
= nullptr;
1810 bool bCharBound
= false;
1811 if( dynamic_cast<const SdrUnoObj
*>( &rSdrObj
) != nullptr )
1813 SwPosition
aPos( GetDoc()->GetNodes() );
1814 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
1815 Point
aPoint( aPt
.getX(), aPt
.getY() + rBound
.GetHeight()/2 );
1816 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPoint
, &aState
);
1818 // characterbinding not allowed in readonly-content
1819 if( !aPos
.nNode
.GetNode().IsProtect() )
1821 std::pair
<Point
, bool> const tmp(aPoint
, true);
1822 pAnch
= aPos
.nNode
.GetNode().GetContentNode()->getLayoutFrame(GetLayout(), &aPos
, &tmp
);
1824 pAnch
->GetCharRect( aTmp
, aPos
);
1826 // The crsr should not be too far away
1828 tools::Rectangle
aRect( aTmp
.SVRect() );
1829 aRect
.AdjustLeft( -(MM50
*2) );
1830 aRect
.AdjustTop( -(MM50
*2) );
1831 aRect
.AdjustRight(MM50
*2 );
1832 aRect
.AdjustBottom(MM50
*2 );
1834 if( !aRect
.IsOver( rBound
) && !::GetHtmlMode( GetDoc()->GetDocShell() ))
1837 // anchor in header/footer also not allowed.
1839 bCharBound
= !GetDoc()->IsInHeaderFooter( aPos
.nNode
);
1843 aAnch
.SetType( RndStdIds::FLY_AS_CHAR
);
1844 aAnch
.SetAnchor( &aPos
);
1851 // allow native drawing objects in header/footer.
1852 // Thus, set <bBodyOnly> to <false> for these objects using value
1853 // of <nIdent> - value <0xFFFF> indicates control objects, which aren't
1854 // allowed in header/footer.
1855 //bool bBodyOnly = OBJ_NONE != nIdent;
1856 bool bBodyOnly
= 0xFFFF == nIdent
;
1857 bool bAtPage
= false;
1858 const SwFrame
* pPage
= nullptr;
1859 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
1860 Point
aPoint( aPt
);
1861 SwPosition
aPos( GetDoc()->GetNodes() );
1862 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPoint
, &aState
);
1864 // do not set in ReadnOnly-content
1865 if (aPos
.nNode
.GetNode().IsProtect())
1867 // then only page bound. Or should we
1868 // search the next not-readonly position?
1872 SwContentNode
* pCNode
= aPos
.nNode
.GetNode().GetContentNode();
1873 std::pair
<Point
, bool> const tmp(aPoint
, false);
1874 pAnch
= pCNode
? pCNode
->getLayoutFrame(GetLayout(), nullptr, &tmp
) : nullptr;
1877 // Hidden content. Anchor to the page instead
1883 const SwFlyFrame
*pTmp
= pAnch
->FindFlyFrame();
1886 const SwFrame
* pTmpFrame
= pAnch
;
1887 SwRect
aBound( rBound
);
1890 if( pTmp
->getFrameArea().IsInside( aBound
) )
1892 if( !bBodyOnly
|| !pTmp
->FindFooterOrHeader() )
1896 pTmp
= pTmp
->GetAnchorFrame()
1897 ? pTmp
->GetAnchorFrame()->FindFlyFrame()
1904 pPage
= pAnch
->FindPageFrame();
1906 // Always via FindAnchor, to assure the frame will be bound
1907 // to the previous. With GetCrsOfst we can also reach the next. THIS IS WRONG.
1908 pAnch
= ::FindAnchor( pPage
, aPt
, bBodyOnly
);
1909 if (pAnch
->IsTextFrame())
1911 std::pair
<SwTextNode
const*, sal_Int32
> const pos(
1912 static_cast<SwTextFrame
const*>(pAnch
)->MapViewToModel(TextFrameIndex(0)));
1913 aPos
.nNode
= *pos
.first
;
1917 aPos
.nNode
= *static_cast<const SwNoTextFrame
*>(pAnch
)->GetNode();
1920 // do not set in ReadnOnly-content
1921 if( aPos
.nNode
.GetNode().IsProtect() )
1922 // then only page bound. Or should we
1923 // search the next not-readonly position?
1927 aAnch
.SetType( RndStdIds::FLY_AT_PARA
);
1928 aAnch
.SetAnchor( &aPos
);
1934 pPage
= pAnch
? pAnch
->FindPageFrame() : GetLayout()->GetPageAtPos(aPoint
);
1936 aAnch
.SetType( RndStdIds::FLY_AT_PAGE
);
1937 aAnch
.SetPageNum( pPage
->GetPhyPageNum() );
1938 pAnch
= pPage
; // page becomes an anchor
1942 SfxItemSet
aSet( GetDoc()->GetAttrPool(), svl::Items
<RES_FRM_SIZE
, RES_FRM_SIZE
,
1943 RES_SURROUND
, RES_ANCHOR
>{} );
1946 // OD 2004-03-30 #i26791# - determine relative object position
1948 SwTwips nYOffset
= rBound
.Top() - pAnch
->getFrameArea().Top();
1950 if( pAnch
->IsVertical() )
1952 nXOffset
= nYOffset
;
1953 nYOffset
= pAnch
->getFrameArea().Left()+pAnch
->getFrameArea().Width()-rBound
.Right();
1955 else if( pAnch
->IsRightToLeft() )
1956 nXOffset
= pAnch
->getFrameArea().Left()+pAnch
->getFrameArea().Width()-rBound
.Right();
1958 nXOffset
= rBound
.Left() - pAnch
->getFrameArea().Left();
1959 if (pAnch
->IsTextFrame())
1961 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnch
);
1962 if (pTmp
->IsFollow())
1965 pTmp
= pTmp
->FindMaster();
1966 OSL_ENSURE(pTmp
, "Where's my Master?");
1967 // OD 2004-03-30 #i26791# - correction: add frame area height
1968 // of master frames.
1969 nYOffset
+= pTmp
->IsVertical() ?
1970 pTmp
->getFrameArea().Width() : pTmp
->getFrameArea().Height();
1971 } while (pTmp
->IsFollow());
1974 nYOffset
-= pTmp
->GetBaseVertOffsetForFly(false);
1978 if( OBJ_NONE
== nIdent
)
1980 // For OBJ_NONE a fly is inserted.
1981 const tools::Long nWidth
= rBound
.Right() - rBound
.Left();
1982 const tools::Long nHeight
= rBound
.Bottom() - rBound
.Top();
1983 aSet
.Put( SwFormatFrameSize( SwFrameSize::Minimum
, std::max( nWidth
, tools::Long(MINFLY
) ),
1984 std::max( nHeight
, tools::Long(MINFLY
) )));
1986 SwFormatHoriOrient
aHori( nXOffset
, text::HoriOrientation::NONE
, text::RelOrientation::FRAME
);
1987 SwFormatVertOrient
aVert( nYOffset
, text::VertOrientation::NONE
, text::RelOrientation::FRAME
);
1988 aSet
.Put( SwFormatSurround( css::text::WrapTextMode_PARALLEL
) );
1992 // Quickly store the square
1993 const SwRect
aFlyRect( rBound
);
1995 // Throw away generated object, now the fly can nicely
1996 // via the available SS be generated.
1997 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); // see above
1998 // #i52858# - method name changed
1999 SdrPage
*pPg
= getIDocumentDrawModelAccess().GetOrCreateDrawModel()->GetPage( 0 );
2002 SdrModel
* pTmpSdrModel
= getIDocumentDrawModelAccess().GetDrawModel();
2003 pPg
= pTmpSdrModel
->AllocPage( false );
2004 pTmpSdrModel
->InsertPage( pPg
);
2006 pPg
->RecalcObjOrdNums();
2007 SdrObject
* pRemovedObject
= pPg
->RemoveObject( rSdrObj
.GetOrdNumDirect() );
2008 SdrObject::Free( pRemovedObject
);
2009 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
2011 SwFlyFrame
* pFlyFrame
;
2012 if( NewFlyFrame( aSet
, true ) &&
2013 ::GetHtmlMode( GetDoc()->GetDocShell() ) &&
2014 nullptr != ( pFlyFrame
= GetSelectedFlyFrame() ))
2016 SfxItemSet
aHtmlSet( GetDoc()->GetAttrPool(), svl::Items
<RES_VERT_ORIENT
, RES_HORI_ORIENT
>{} );
2017 // horizontal orientation:
2018 const bool bLeftFrame
= aFlyRect
.Left() <
2019 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Left(),
2020 bLeftPrt
= aFlyRect
.Left() + aFlyRect
.Width() <
2021 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Width()/2;
2022 if( bLeftFrame
|| bLeftPrt
)
2024 aHori
.SetHoriOrient( text::HoriOrientation::LEFT
);
2025 aHori
.SetRelationOrient( bLeftFrame
? text::RelOrientation::FRAME
: text::RelOrientation::PRINT_AREA
);
2029 const bool bRightFrame
= aFlyRect
.Left() >
2030 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Width();
2031 aHori
.SetHoriOrient( text::HoriOrientation::RIGHT
);
2032 aHori
.SetRelationOrient( bRightFrame
? text::RelOrientation::FRAME
: text::RelOrientation::PRINT_AREA
);
2034 aHtmlSet
.Put( aHori
);
2035 aVert
.SetVertOrient( text::VertOrientation::TOP
);
2036 aVert
.SetRelationOrient( text::RelOrientation::PRINT_AREA
);
2037 aHtmlSet
.Put( aVert
);
2039 GetDoc()->SetAttr( aHtmlSet
, *pFlyFrame
->GetFormat() );
2044 if (rSdrObj
.GetName().isEmpty())
2046 bool bRestore
= GetDoc()->GetIDocumentUndoRedo().DoesDrawUndo();
2047 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
2048 rSdrObj
.SetName(GetUniqueShapeName());
2049 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(bRestore
);
2053 if( OBJ_CAPTION
== nIdent
)
2054 aRelNullPt
= static_cast<SdrCaptionObj
&>(rSdrObj
).GetTailPos();
2056 aRelNullPt
= rBound
.TopLeft();
2059 aSet
.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH
) );
2060 // OD 2004-03-30 #i26791# - set horizontal position
2061 SwFormatHoriOrient
aHori( nXOffset
, text::HoriOrientation::NONE
, text::RelOrientation::FRAME
);
2063 // OD 2004-03-30 #i26791# - set vertical position
2064 if( pAnch
->IsTextFrame() && static_cast<const SwTextFrame
*>(pAnch
)->IsFollow() )
2066 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnch
);
2068 pTmp
= pTmp
->FindMaster();
2069 assert(pTmp
&& "Where's my Master?");
2070 nYOffset
+= pTmp
->IsVertical() ?
2071 pTmp
->getFramePrintArea().Width() : pTmp
->getFramePrintArea().Height();
2072 } while ( pTmp
->IsFollow() );
2074 SwFormatVertOrient
aVert( nYOffset
, text::VertOrientation::NONE
, text::RelOrientation::FRAME
);
2076 SwDrawFrameFormat
* pFormat
= static_cast<SwDrawFrameFormat
*>(getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT
, &aSet
));
2077 // #i36010# - set layout direction of the position
2078 pFormat
->SetPositionLayoutDir(
2079 text::PositionLayoutDir::PositionInLayoutDirOfAnchor
);
2080 // #i44344#, #i44681# - positioning attributes already set
2081 pFormat
->PosAttrSet();
2082 pFormat
->SetName(rSdrObj
.GetName());
2084 SwDrawContact
*pContact
= new SwDrawContact( pFormat
, &rSdrObj
);
2086 pContact
->MoveObjToVisibleLayer( &rSdrObj
);
2089 OSL_ENSURE( aAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
, "wrong AnchorType" );
2090 SwTextNode
*pNd
= aAnch
.GetContentAnchor()->nNode
.GetNode().GetTextNode();
2091 SwFormatFlyCnt
aFormat( pFormat
);
2092 pNd
->InsertItem(aFormat
,
2093 aAnch
.GetContentAnchor()->nContent
.GetIndex(), 0 );
2094 SwFormatVertOrient
aVertical( pFormat
->GetVertOrient() );
2095 aVertical
.SetVertOrient( text::VertOrientation::LINE_CENTER
);
2096 pFormat
->SetFormatAttr( aVertical
);
2098 if( pAnch
->IsTextFrame() && static_cast<const SwTextFrame
*>(pAnch
)->IsFollow() )
2100 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnch
);
2102 pTmp
= pTmp
->FindMaster();
2103 OSL_ENSURE( pTmp
, "Where's my Master?" );
2104 } while( pTmp
->IsFollow() );
2108 pContact
->ConnectToLayout();
2110 // mark object at frame the object is inserted at.
2112 SdrObject
* pMarkObj
= pContact
->GetDrawObjectByAnchorFrame( *pAnch
);
2115 Imp()->GetDrawView()->MarkObj( pMarkObj
, Imp()->GetPageView() );
2119 Imp()->GetDrawView()->MarkObj( &rSdrObj
, Imp()->GetPageView() );
2124 GetDoc()->getIDocumentState().SetModified();
2127 EndAllActionAndCall();
2132 void SwFEShell::BreakCreate()
2134 OSL_ENSURE( Imp()->HasDrawView(), "BreakCreate without DrawView?" );
2135 Imp()->GetDrawView()->BrkCreateObj();
2136 ::FrameNotify( this, FLY_DRAG_END
);
2139 bool SwFEShell::IsDrawCreate() const
2141 return Imp()->HasDrawView() && Imp()->GetDrawView()->IsCreateObj();
2144 bool SwFEShell::BeginMark( const Point
&rPos
)
2146 if ( !Imp()->HasDrawView() )
2147 Imp()->MakeDrawView();
2149 if ( GetPageNumber( rPos
) )
2151 SwDrawView
* pDView
= Imp()->GetDrawView();
2153 if (pDView
->HasMarkablePoints())
2154 return pDView
->BegMarkPoints( rPos
);
2157 pDView
->BegMarkObj( rPos
);
2165 void SwFEShell::MoveMark( const Point
&rPos
)
2167 OSL_ENSURE( Imp()->HasDrawView(), "MoveMark without DrawView?" );
2169 if ( GetPageNumber( rPos
) )
2172 SwDrawView
* pDView
= Imp()->GetDrawView();
2174 if (pDView
->IsInsObjPoint())
2175 pDView
->MovInsObjPoint( rPos
);
2176 else if (pDView
->IsMarkPoints())
2177 pDView
->MovMarkPoints( rPos
);
2179 pDView
->MovAction( rPos
);
2183 bool SwFEShell::EndMark()
2186 OSL_ENSURE( Imp()->HasDrawView(), "EndMark without DrawView?" );
2188 if (Imp()->GetDrawView()->IsMarkObj())
2190 bRet
= Imp()->GetDrawView()->EndMarkObj();
2194 bool bShowHdl
= false;
2195 SwDrawView
* pDView
= Imp()->GetDrawView();
2196 // frames are not selected this way, except when
2197 // it is only one frame
2198 SdrMarkList
&rMrkList
= const_cast<SdrMarkList
&>(pDView
->GetMarkedObjectList());
2199 SwFlyFrame
* pOldSelFly
= ::GetFlyFromMarked( &rMrkList
, this );
2201 if ( rMrkList
.GetMarkCount() > 1 )
2202 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2204 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2205 if( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) != nullptr )
2211 rMrkList
.DeleteMark( i
);
2212 --i
; // no exceptions
2218 pDView
->MarkListHasChanged();
2219 pDView
->AdjustMarkHdl();
2222 if ( rMrkList
.GetMarkCount() )
2223 ::lcl_GrabCursor(this, pOldSelFly
);
2228 ::FrameNotify( this, FLY_DRAG_START
);
2232 if (Imp()->GetDrawView()->IsMarkPoints())
2233 bRet
= Imp()->GetDrawView()->EndMarkPoints();
2240 RndStdIds
SwFEShell::GetAnchorId() const
2242 RndStdIds nRet
= RndStdIds(SHRT_MAX
);
2243 if ( Imp()->HasDrawView() )
2245 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2246 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2248 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2249 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) != nullptr )
2251 nRet
= RndStdIds::UNKNOWN
;
2254 SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
2255 RndStdIds nId
= pContact
->GetFormat()->GetAnchor().GetAnchorId();
2256 if ( nRet
== RndStdIds(SHRT_MAX
) )
2258 else if ( nRet
!= nId
)
2260 nRet
= RndStdIds::UNKNOWN
;
2265 if ( nRet
== RndStdIds(SHRT_MAX
) )
2266 nRet
= RndStdIds::UNKNOWN
;
2270 void SwFEShell::ChgAnchor( RndStdIds eAnchorId
, bool bSameOnly
, bool bPosCorr
)
2272 OSL_ENSURE( Imp()->HasDrawView(), "ChgAnchor without DrawView?" );
2273 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2274 if( rMrkList
.GetMarkCount() &&
2275 !rMrkList
.GetMark( 0 )->GetMarkedSdrObj()->getParentSdrObjectFromSdrObject() )
2279 if( GetDoc()->ChgAnchor( rMrkList
, eAnchorId
, bSameOnly
, bPosCorr
))
2280 Imp()->GetDrawView()->UnmarkAll();
2284 ::FrameNotify( this );
2288 void SwFEShell::DelSelectedObj()
2290 OSL_ENSURE( Imp()->HasDrawView(), "DelSelectedObj(), no DrawView available" );
2291 if ( Imp()->HasDrawView() )
2294 Imp()->GetDrawView()->DeleteMarked();
2296 ::FrameNotify( this, FLY_DRAG_END
);
2300 // For the statusline to request the current conditions
2301 Size
SwFEShell::GetObjSize() const
2303 tools::Rectangle aRect
;
2304 if ( Imp()->HasDrawView() )
2306 if ( Imp()->GetDrawView()->IsAction() )
2307 Imp()->GetDrawView()->TakeActionRect( aRect
);
2309 aRect
= Imp()->GetDrawView()->GetAllMarkedRect();
2311 return aRect
.GetSize();
2314 Point
SwFEShell::GetAnchorObjDiff() const
2316 const SdrView
*pView
= Imp()->GetDrawView();
2317 OSL_ENSURE( pView
, "GetAnchorObjDiff without DrawView?" );
2319 tools::Rectangle aRect
;
2320 if ( Imp()->GetDrawView()->IsAction() )
2321 Imp()->GetDrawView()->TakeActionRect( aRect
);
2323 aRect
= Imp()->GetDrawView()->GetAllMarkedRect();
2325 Point
aRet( aRect
.TopLeft() );
2327 if ( IsFrameSelected() )
2329 SwFlyFrame
*pFly
= GetSelectedFlyFrame();
2330 aRet
-= pFly
->GetAnchorFrame()->getFrameArea().Pos();
2334 const SdrObject
*pObj
= pView
->GetMarkedObjectList().GetMarkCount() == 1 ?
2335 pView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj() : nullptr;
2337 aRet
-= pObj
->GetAnchorPos();
2343 Point
SwFEShell::GetObjAbsPos() const
2345 OSL_ENSURE( Imp()->GetDrawView(), "GetObjAbsPos() without DrawView?" );
2346 return Imp()->GetDrawView()->GetDragStat().GetActionRect().TopLeft();
2349 bool SwFEShell::IsGroupSelected()
2351 if ( IsObjSelected() )
2353 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2354 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2356 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2357 // consider 'virtual' drawing objects.
2358 // Thus, use corresponding method instead of checking type.
2359 if ( pObj
->IsGroupObject() &&
2360 // --> #i38505# No ungroup allowed for 3d objects
2362 RndStdIds::FLY_AS_CHAR
!= static_cast<SwDrawContact
*>(GetUserCall(pObj
))->
2363 GetFormat()->GetAnchor().GetAnchorId() )
2374 bool HasSuitableGroupingAnchor(const SdrObject
* pObj
)
2376 bool bSuitable
= true;
2377 SwFrameFormat
* pFrameFormat(::FindFrameFormat(const_cast<SdrObject
*>(pObj
)));
2380 OSL_FAIL( "<HasSuitableGroupingAnchor> - missing frame format" );
2383 else if (RndStdIds::FLY_AS_CHAR
== pFrameFormat
->GetAnchor().GetAnchorId())
2391 // Change return type.
2392 // Adjustments for drawing objects in header/footer:
2393 // allow group, only if all selected objects are in the same header/footer
2394 // or not in header/footer.
2395 bool SwFEShell::IsGroupAllowed() const
2397 bool bIsGroupAllowed
= false;
2398 if ( IsObjSelected() > 1 )
2400 bIsGroupAllowed
= true;
2401 const SdrObject
* pUpGroup
= nullptr;
2402 const SwFrame
* pHeaderFooterFrame
= nullptr;
2403 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2404 for ( size_t i
= 0; bIsGroupAllowed
&& i
< rMrkList
.GetMarkCount(); ++i
)
2406 const SdrObject
* pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2408 bIsGroupAllowed
= pObj
->getParentSdrObjectFromSdrObject() == pUpGroup
;
2410 pUpGroup
= pObj
->getParentSdrObjectFromSdrObject();
2412 if ( bIsGroupAllowed
)
2413 bIsGroupAllowed
= HasSuitableGroupingAnchor(pObj
);
2415 // check, if all selected objects are in the
2416 // same header/footer or not in header/footer.
2417 if ( bIsGroupAllowed
)
2419 const SwFrame
* pAnchorFrame
= nullptr;
2420 if ( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) )
2422 const SwFlyFrame
* pFlyFrame
= pVirtFlyDrawObj
->GetFlyFrame();
2425 pAnchorFrame
= pFlyFrame
->GetAnchorFrame();
2430 SwDrawContact
* pDrawContact
= static_cast<SwDrawContact
*>(GetUserCall( pObj
));
2433 pAnchorFrame
= pDrawContact
->GetAnchorFrame( pObj
);
2441 ( pAnchorFrame
->FindFooterOrHeader() == pHeaderFooterFrame
);
2445 pHeaderFooterFrame
= pAnchorFrame
->FindFooterOrHeader();
2452 return bIsGroupAllowed
;
2455 bool SwFEShell::IsUnGroupAllowed() const
2457 bool bIsUnGroupAllowed
= false;
2459 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2460 for (size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2462 const SdrObject
* pObj
= rMrkList
.GetMark(i
)->GetMarkedSdrObj();
2463 bIsUnGroupAllowed
= HasSuitableGroupingAnchor(pObj
);
2464 if (!bIsUnGroupAllowed
)
2468 return bIsUnGroupAllowed
;
2471 // The group gets the anchor and the contactobject of the first in the selection
2472 void SwFEShell::GroupSelection()
2474 if ( IsGroupAllowed() )
2477 StartUndo( SwUndoId::START
);
2479 GetDoc()->GroupSelection( *Imp()->GetDrawView() );
2481 EndUndo( SwUndoId::END
);
2486 // The individual objects get a copy of the anchor and the contactobject of the group
2487 void SwFEShell::UnGroupSelection()
2489 if ( IsGroupSelected() )
2492 StartUndo( SwUndoId::START
);
2494 GetDoc()->UnGroupSelection( *Imp()->GetDrawView() );
2496 EndUndo( SwUndoId::END
);
2501 void SwFEShell::MirrorSelection( bool bHorizontal
)
2503 SdrView
*pView
= Imp()->GetDrawView();
2504 if ( IsObjSelected() && pView
->IsMirrorAllowed() )
2507 pView
->MirrorAllMarkedHorizontal();
2509 pView
->MirrorAllMarkedVertical();
2513 // jump to named frame (Graphic/OLE)
2515 bool SwFEShell::GotoFly( const OUString
& rName
, FlyCntType eType
, bool bSelFrame
)
2518 static SwNodeType
const aChkArr
[ 4 ] = {
2519 /* FLYCNTTYPE_ALL */ SwNodeType::NONE
,
2520 /* FLYCNTTYPE_FRM */ SwNodeType::Text
,
2521 /* FLYCNTTYPE_GRF */ SwNodeType::Grf
,
2522 /* FLYCNTTYPE_OLE */ SwNodeType::Ole
2525 const SwFlyFrameFormat
* pFlyFormat
= mxDoc
->FindFlyByName( rName
, aChkArr
[ eType
]);
2528 CurrShell
aCurr( this );
2530 SwFlyFrame
* pFrame
= SwIterator
<SwFlyFrame
,SwFormat
>( *pFlyFormat
).First();
2535 // first make visible, to get a11y events in proper order
2537 MakeVisible( pFrame
->getFrameArea() );
2538 SelectObj( pFrame
->getFrameArea().Pos(), 0, pFrame
->GetVirtDrawObj() );
2542 SwContentFrame
*pCFrame
= pFrame
->ContainsContent();
2546 SwPaM
* pCursor
= GetCursor();
2548 if (pCFrame
->IsTextFrame())
2550 *pCursor
->GetPoint() = static_cast<SwTextFrame
*>(pCFrame
)
2551 ->MapViewToModelPos(TextFrameIndex(0));
2555 assert(pCFrame
->IsNoTextFrame());
2556 SwContentNode
*const pCNode
= static_cast<SwNoTextFrame
*>(pCFrame
)->GetNode();
2558 pCursor
->GetPoint()->nNode
= *pCNode
;
2559 pCursor
->GetPoint()->nContent
.Assign( pCNode
, 0 );
2562 SwRect
& rChrRect
= const_cast<SwRect
&>(GetCharRect());
2563 rChrRect
= pFrame
->getFramePrintArea();
2564 rChrRect
.Pos() += pFrame
->getFrameArea().Pos();
2565 GetCursorDocPos() = rChrRect
.Pos();
2574 size_t SwFEShell::GetFlyCount( FlyCntType eType
, bool bIgnoreTextBoxes
) const
2576 return GetDoc()->GetFlyCount(eType
, bIgnoreTextBoxes
);
2579 const SwFrameFormat
* SwFEShell::GetFlyNum(size_t nIdx
, FlyCntType eType
, bool bIgnoreTextBoxes
) const
2581 return GetDoc()->GetFlyNum(nIdx
, eType
, bIgnoreTextBoxes
);
2584 std::vector
<SwFrameFormat
const*> SwFEShell::GetFlyFrameFormats(
2585 FlyCntType
const eType
, bool const bIgnoreTextBoxes
)
2587 return GetDoc()->GetFlyFrameFormats(eType
, bIgnoreTextBoxes
);
2590 // show the current selected object
2591 void SwFEShell::MakeSelVisible()
2593 if ( Imp()->HasDrawView() &&
2594 Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2596 GetCurrFrame(); // just to trigger formatting in case the selected object is not formatted.
2597 MakeVisible( Imp()->GetDrawView()->GetAllMarkedRect() );
2600 SwCursorShell::MakeSelVisible();
2603 // how is the selected object protected?
2604 FlyProtectFlags
SwFEShell::IsSelObjProtected( FlyProtectFlags eType
) const
2606 FlyProtectFlags nChk
= FlyProtectFlags::NONE
;
2607 const bool bParent(eType
& FlyProtectFlags::Parent
);
2608 if( Imp()->HasDrawView() )
2610 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2611 for( size_t i
= rMrkList
.GetMarkCount(); i
; )
2613 SdrObject
*pObj
= rMrkList
.GetMark( --i
)->GetMarkedSdrObj();
2616 nChk
|= ( pObj
->IsMoveProtect() ? FlyProtectFlags::Pos
: FlyProtectFlags::NONE
) |
2617 ( pObj
->IsResizeProtect()? FlyProtectFlags::Size
: FlyProtectFlags::NONE
);
2619 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
2621 SwFlyFrame
*pFly
= pVirtO
->GetFlyFrame();
2622 if ( (FlyProtectFlags::Content
& eType
) && pFly
->GetFormat()->GetProtect().IsContentProtected() )
2623 nChk
|= FlyProtectFlags::Content
;
2625 if ( pFly
->Lower() && pFly
->Lower()->IsNoTextFrame() )
2627 SwOLENode
*pNd
= static_cast<SwNoTextFrame
*>(pFly
->Lower())->GetNode()->GetOLENode();
2628 uno::Reference
< embed::XEmbeddedObject
> xObj( pNd
? pNd
->GetOLEObj().GetOleRef() : nullptr );
2631 // TODO/LATER: use correct aspect
2632 const bool bNeverResize
= (embed::EmbedMisc::EMBED_NEVERRESIZE
& xObj
->getStatus( embed::Aspects::MSOLE_CONTENT
));
2633 if ( ( (FlyProtectFlags::Content
& eType
) || (FlyProtectFlags::Size
& eType
) ) && bNeverResize
)
2635 nChk
|= FlyProtectFlags::Size
;
2636 nChk
|= FlyProtectFlags::Fixed
;
2639 // set FlyProtectFlags::Pos if it is a Math object anchored 'as char' and baseline alignment is activated
2640 const bool bProtectMathPos
= SotExchange::IsMath( xObj
->getClassID() )
2641 && RndStdIds::FLY_AS_CHAR
== pFly
->GetFormat()->GetAnchor().GetAnchorId()
2642 && mxDoc
->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT
);
2643 if ((FlyProtectFlags::Pos
& eType
) && bProtectMathPos
)
2644 nChk
|= FlyProtectFlags::Pos
;
2652 const SwFrame
* pAnch
;
2653 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
2654 pAnch
= pVirtO
->GetFlyFrame()->GetAnchorFrame();
2657 SwDrawContact
* pTmp
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
2658 pAnch
= pTmp
? pTmp
->GetAnchorFrame( pObj
) : nullptr;
2660 if( pAnch
&& pAnch
->IsProtected() )
2667 bool SwFEShell::GetObjAttr( SfxItemSet
&rSet
) const
2669 if ( !IsObjSelected() )
2672 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2673 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2675 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2676 SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
2677 // --> make code robust
2678 OSL_ENSURE( pContact
, "<SwFEShell::GetObjAttr(..)> - missing <pContact>." );
2682 rSet
.MergeValues( pContact
->GetFormat()->GetAttrSet() );
2684 rSet
.Put( pContact
->GetFormat()->GetAttrSet() );
2690 void SwFEShell::SetObjAttr( const SfxItemSet
& rSet
)
2692 CurrShell
aCurr( this );
2694 if ( !rSet
.Count() )
2696 OSL_ENSURE( false, "SetObjAttr, empty set." );
2701 StartUndo( SwUndoId::INSATTR
);
2703 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2704 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2706 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2707 SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
2708 GetDoc()->SetAttr( rSet
, *pContact
->GetFormat() );
2711 EndUndo( SwUndoId::INSATTR
);
2712 EndAllActionAndCall();
2713 GetDoc()->getIDocumentState().SetModified();
2716 bool SwFEShell::IsAlignPossible() const
2718 return Imp()->GetDrawView()->IsAlignPossible();
2721 void SwFEShell::CheckUnboundObjects()
2723 CurrShell
aCurr( this );
2725 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2726 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2728 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2729 if ( !GetUserCall(pObj
) )
2731 const tools::Rectangle
&rBound
= pObj
->GetSnapRect();
2732 const Point
aPt( rBound
.TopLeft() );
2733 const SwFrame
*pPage
= GetLayout()->Lower();
2734 const SwFrame
*pLast
= pPage
;
2735 while ( pPage
&& !pPage
->getFrameArea().IsInside( aPt
) )
2737 if ( aPt
.Y() > pPage
->getFrameArea().Bottom() )
2739 pPage
= pPage
->GetNext();
2743 OSL_ENSURE( pPage
, "Page not found." );
2745 // Alien identifier should roll into the default,
2746 // Duplications are possible!!
2748 Imp()->GetDrawView()->GetCurrentObjInventor() == SdrInventor::Default
?
2749 Imp()->GetDrawView()->GetCurrentObjIdentifier() : 0xFFFF;
2751 SwFormatAnchor aAnch
;
2753 const SwContentFrame
*const pAnch
= ::FindAnchor(pPage
, aPt
, true);
2754 SwPosition
aPos( pAnch
->IsTextFrame()
2755 ? *static_cast<SwTextFrame
const*>(pAnch
)->GetTextNodeForParaProps()
2756 : *static_cast<SwNoTextFrame
const*>(pAnch
)->GetNode() );
2757 aAnch
.SetType( RndStdIds::FLY_AT_PARA
);
2758 aAnch
.SetAnchor( &aPos
);
2759 const_cast<SwRect
&>(GetCharRect()).Pos() = aPt
;
2762 // First the action here, to assure GetCharRect delivers current values.
2765 SfxItemSet
aSet( GetAttrPool(), svl::Items
<RES_FRM_SIZE
, RES_FRM_SIZE
,
2766 RES_SURROUND
, RES_ANCHOR
>{} );
2771 if( OBJ_CAPTION
== nIdent
)
2772 aRelNullPt
= static_cast<SdrCaptionObj
*>(pObj
)->GetTailPos();
2774 aRelNullPt
= rBound
.TopLeft();
2777 aSet
.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH
) );
2778 SwFrameFormat
* pFormat
= getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT
, &aSet
);
2780 SwDrawContact
*pContact
= new SwDrawContact(
2781 static_cast<SwDrawFrameFormat
*>(pFormat
), pObj
);
2784 pContact
->MoveObjToVisibleLayer( pObj
);
2785 pContact
->ConnectToLayout();
2792 void SwFEShell::SetCalcFieldValueHdl(Outliner
* pOutliner
)
2794 GetDoc()->SetCalcFieldValueHdl(pOutliner
);
2797 SwChainRet
SwFEShell::Chainable( SwRect
&rRect
, const SwFrameFormat
&rSource
,
2798 const Point
&rPt
) const
2802 // The source is not allowed to have a follow.
2803 const SwFormatChain
&rChain
= rSource
.GetChain();
2804 if ( rChain
.GetNext() )
2805 return SwChainRet::SOURCE_CHAINED
;
2807 SwChainRet nRet
= SwChainRet::NOT_FOUND
;
2808 if( Imp()->HasDrawView() )
2810 SdrPageView
* pPView
;
2811 SwDrawView
*pDView
= const_cast<SwDrawView
*>(Imp()->GetDrawView());
2812 const auto nOld
= pDView
->GetHitTolerancePixel();
2813 pDView
->SetHitTolerancePixel( 0 );
2814 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPView
, SdrSearchOptions::PICKMARKABLE
);
2815 SwVirtFlyDrawObj
* pDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
);
2818 SwFlyFrame
*pFly
= pDrawObj
->GetFlyFrame();
2819 rRect
= pFly
->getFrameArea();
2821 // Target and source should not be equal and the list
2822 // should not be cyclic
2823 SwFrameFormat
*pFormat
= pFly
->GetFormat();
2824 nRet
= GetDoc()->Chainable(rSource
, *pFormat
);
2826 pDView
->SetHitTolerancePixel( nOld
);
2831 void SwFEShell::Chain( SwFrameFormat
&rSource
, const SwFrameFormat
&rDest
)
2833 GetDoc()->Chain(rSource
, rDest
);
2836 SwChainRet
SwFEShell::Chain( SwFrameFormat
&rSource
, const Point
&rPt
)
2839 SwChainRet nErr
= Chainable( aDummy
, rSource
, rPt
);
2840 if ( nErr
== SwChainRet::OK
)
2843 SdrPageView
* pPView
;
2844 SwDrawView
*pDView
= Imp()->GetDrawView();
2845 const auto nOld
= pDView
->GetHitTolerancePixel();
2846 pDView
->SetHitTolerancePixel( 0 );
2847 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPView
, SdrSearchOptions::PICKMARKABLE
);
2848 pDView
->SetHitTolerancePixel( nOld
);
2849 SwFlyFrame
*pFly
= static_cast<SwVirtFlyDrawObj
*>(pObj
)->GetFlyFrame();
2851 SwFlyFrameFormat
*pFormat
= pFly
->GetFormat();
2852 GetDoc()->Chain(rSource
, *pFormat
);
2859 void SwFEShell::Unchain( SwFrameFormat
&rFormat
)
2862 GetDoc()->Unchain(rFormat
);
2866 void SwFEShell::HideChainMarker()
2868 m_pChainFrom
.reset();
2872 void SwFEShell::SetChainMarker()
2874 bool bDelFrom
= true,
2876 if ( IsFrameSelected() )
2878 SwFlyFrame
*pFly
= GetSelectedFlyFrame();
2880 if ( pFly
->GetPrevLink() )
2883 const SwFrame
*pPre
= pFly
->GetPrevLink();
2885 Point
aStart( pPre
->getFrameArea().Right(), pPre
->getFrameArea().Bottom());
2886 Point
aEnd(pFly
->getFrameArea().Pos());
2891 new SdrDropMarkerOverlay( *GetDrawView(), aStart
, aEnd
));
2894 if ( pFly
->GetNextLink() )
2897 const SwFlyFrame
*pNxt
= pFly
->GetNextLink();
2899 Point
aStart( pFly
->getFrameArea().Right(), pFly
->getFrameArea().Bottom());
2900 Point
aEnd(pNxt
->getFrameArea().Pos());
2905 new SdrDropMarkerOverlay( *GetDrawView(), aStart
, aEnd
));
2912 m_pChainFrom
.reset();
2921 tools::Long
SwFEShell::GetSectionWidth( SwFormat
const & rFormat
) const
2923 SwFrame
*pFrame
= GetCurrFrame();
2924 // Is the cursor at this moment in a SectionFrame?
2925 if( pFrame
&& pFrame
->IsInSct() )
2927 SwSectionFrame
* pSect
= pFrame
->FindSctFrame();
2930 // Is it the right one?
2931 if( pSect
->KnowsFormat( rFormat
) )
2932 return pSect
->getFrameArea().Width();
2934 pSect
= pSect
->GetUpper()->FindSctFrame();
2938 SwIterator
<SwSectionFrame
,SwFormat
> aIter( rFormat
);
2939 for ( SwSectionFrame
* pSct
= aIter
.First(); pSct
; pSct
= aIter
.Next() )
2941 if( !pSct
->IsFollow() )
2943 return pSct
->getFrameArea().Width();
2949 void SwFEShell::CreateDefaultShape( SdrObjKind eSdrObjectKind
, const tools::Rectangle
& rRect
,
2952 SdrView
* pDrawView
= GetDrawView();
2953 SdrModel
* pDrawModel
= pDrawView
->GetModel();
2954 SdrObject
* pObj
= SdrObjFactory::MakeNewObject(
2956 SdrInventor::Default
,
2961 tools::Rectangle
aRect(rRect
);
2962 if(OBJ_CARC
== eSdrObjectKind
|| OBJ_CCUT
== eSdrObjectKind
)
2965 if(aRect
.GetWidth() > aRect
.GetHeight())
2967 aRect
= tools::Rectangle(
2968 Point(aRect
.Left() + ((aRect
.GetWidth() - aRect
.GetHeight()) / 2), aRect
.Top()),
2969 Size(aRect
.GetHeight(), aRect
.GetHeight()));
2973 aRect
= tools::Rectangle(
2974 Point(aRect
.Left(), aRect
.Top() + ((aRect
.GetHeight() - aRect
.GetWidth()) / 2)),
2975 Size(aRect
.GetWidth(), aRect
.GetWidth()));
2978 pObj
->SetLogicRect(aRect
);
2980 Point aStart
= aRect
.TopLeft();
2981 Point aEnd
= aRect
.BottomRight();
2983 if(dynamic_cast<const SdrCircObj
*>( pObj
) != nullptr)
2985 SfxItemSet
aAttr(pDrawModel
->GetItemPool());
2986 aAttr
.Put(makeSdrCircStartAngleItem(9000));
2987 aAttr
.Put(makeSdrCircEndAngleItem(0));
2988 pObj
->SetMergedItemSet(aAttr
);
2990 else if(dynamic_cast<const SdrPathObj
*>( pObj
) != nullptr)
2992 basegfx::B2DPolyPolygon aPoly
;
2994 switch(eSdrObjectKind
)
2999 basegfx::B2DPolygon aInnerPoly
;
3001 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Bottom()));
3003 const basegfx::B2DPoint
aCenterBottom(aRect
.Center().getX(), aRect
.Bottom());
3004 aInnerPoly
.appendBezierSegment(
3007 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Center().getY()));
3009 const basegfx::B2DPoint
aCenterTop(aRect
.Center().getX(), aRect
.Top());
3010 aInnerPoly
.appendBezierSegment(
3013 basegfx::B2DPoint(aRect
.Right(), aRect
.Top()));
3015 aInnerPoly
.setClosed(true);
3016 aPoly
.append(aInnerPoly
);
3022 basegfx::B2DPolygon aInnerPoly
;
3024 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Bottom()));
3026 aInnerPoly
.appendBezierSegment(
3027 basegfx::B2DPoint(aRect
.Left(), aRect
.Top()),
3028 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Top()),
3029 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Center().getY()));
3031 aInnerPoly
.appendBezierSegment(
3032 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Bottom()),
3033 basegfx::B2DPoint(aRect
.Right(), aRect
.Bottom()),
3034 basegfx::B2DPoint(aRect
.Right(), aRect
.Top()));
3036 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Right(), aRect
.Bottom()));
3037 aInnerPoly
.setClosed(true);
3038 aPoly
.append(aInnerPoly
);
3044 basegfx::B2DPolygon aInnerPoly
;
3045 sal_Int32
nWdt(aRect
.GetWidth());
3046 sal_Int32
nHgt(aRect
.GetHeight());
3048 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Bottom()));
3049 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 30) / 100, aRect
.Top() + (nHgt
* 70) / 100));
3050 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Top() + (nHgt
* 15) / 100));
3051 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 65) / 100, aRect
.Top()));
3052 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + nWdt
, aRect
.Top() + (nHgt
* 30) / 100));
3053 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 80) / 100, aRect
.Top() + (nHgt
* 50) / 100));
3054 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 80) / 100, aRect
.Top() + (nHgt
* 75) / 100));
3055 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Bottom(), aRect
.Right()));
3057 if(OBJ_PLIN
== eSdrObjectKind
)
3059 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Bottom()));
3063 aInnerPoly
.setClosed(true);
3066 aPoly
.append(aInnerPoly
);
3071 sal_Int32
nYMiddle((aRect
.Top() + aRect
.Bottom()) / 2);
3072 basegfx::B2DPolygon aTempPoly
;
3073 aTempPoly
.append(basegfx::B2DPoint(aRect
.TopLeft().getX(), nYMiddle
));
3074 aTempPoly
.append(basegfx::B2DPoint(aRect
.BottomRight().getX(), nYMiddle
));
3075 aPoly
.append(aTempPoly
);
3077 SfxItemSet
aAttr(pObj
->getSdrModelFromSdrObject().GetItemPool());
3078 SetLineEnds(aAttr
, *pObj
, nSlotId
);
3079 pObj
->SetMergedItemSet(aAttr
);
3086 static_cast<SdrPathObj
*>(pObj
)->SetPathPoly(aPoly
);
3088 else if(auto pMeasureObj
= dynamic_cast<SdrMeasureObj
*>( pObj
))
3090 sal_Int32
nYMiddle((aRect
.Top() + aRect
.Bottom()) / 2);
3091 pMeasureObj
->SetPoint(Point(aStart
.X(), nYMiddle
), 0);
3092 pMeasureObj
->SetPoint(Point(aEnd
.X(), nYMiddle
), 1);
3094 SfxItemSet
aAttr(pObj
->getSdrModelFromSdrObject().GetItemPool());
3095 SetLineEnds(aAttr
, *pObj
, nSlotId
);
3096 pObj
->SetMergedItemSet(aAttr
);
3098 else if(auto pCationObj
= dynamic_cast<SdrCaptionObj
*>( pObj
))
3100 bool bVerticalText
= ( SID_DRAW_TEXT_VERTICAL
== nSlotId
||
3101 SID_DRAW_CAPTION_VERTICAL
== nSlotId
);
3102 static_cast<SdrTextObj
*>(pObj
)->SetVerticalWriting(bVerticalText
);
3105 SfxItemSet
aSet(pObj
->GetMergedItemSet());
3106 aSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER
));
3107 aSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT
));
3108 pObj
->SetMergedItemSet(aSet
);
3111 pCationObj
->SetLogicRect(aRect
);
3112 pCationObj
->SetTailPos(
3113 aRect
.TopLeft() - Point(aRect
.GetWidth() / 2, aRect
.GetHeight() / 2));
3115 else if(auto pText
= dynamic_cast<SdrTextObj
*>( pObj
))
3117 pText
->SetLogicRect(aRect
);
3119 bool bVertical
= (SID_DRAW_TEXT_VERTICAL
== nSlotId
);
3120 bool bMarquee
= (SID_DRAW_TEXT_MARQUEE
== nSlotId
);
3122 pText
->SetVerticalWriting(bVertical
);
3126 SfxItemSet
aSet(pDrawModel
->GetItemPool());
3127 aSet
.Put(makeSdrTextAutoGrowWidthItem(true));
3128 aSet
.Put(makeSdrTextAutoGrowHeightItem(false));
3129 aSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP
));
3130 aSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT
));
3131 pText
->SetMergedItemSet(aSet
);
3136 SfxItemSet
aSet(pDrawModel
->GetItemPool(), svl::Items
<SDRATTR_MISC_FIRST
, SDRATTR_MISC_LAST
>{});
3137 aSet
.Put( makeSdrTextAutoGrowWidthItem( false ) );
3138 aSet
.Put( makeSdrTextAutoGrowHeightItem( false ) );
3139 aSet
.Put( SdrTextAniKindItem( SdrTextAniKind::Slide
) );
3140 aSet
.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left
) );
3141 aSet
.Put( SdrTextAniCountItem( 1 ) );
3142 aSet
.Put( SdrTextAniAmountItem( static_cast<sal_Int16
>(GetWin()->PixelToLogic(Size(2,1)).Width())) );
3143 pObj
->SetMergedItemSetAndBroadcast(aSet
);
3146 SdrPageView
* pPageView
= pDrawView
->GetSdrPageView();
3147 SdrCreateView::SetupObjLayer(pPageView
, pDrawView
->GetActiveLayer(), pObj
);
3148 // switch undo off or this combined with ImpEndCreate will cause two undos
3149 // see comment made in SwFEShell::EndCreate (we create our own undo-object!)
3150 const bool bUndo(GetDoc()->GetIDocumentUndoRedo().DoesUndo());
3151 GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
3152 pDrawView
->InsertObjectAtView(pObj
, *pPageView
);
3153 GetDoc()->GetIDocumentUndoRedo().DoUndo(bUndo
);
3158 /** SwFEShell::GetShapeBackgrd
3159 method determines background color of the page the selected drawing
3160 object is on and returns this color.
3161 If no color is found, because no drawing object is selected or ...,
3162 color COL_BLACK (default color on constructing object of class Color)
3165 @returns an object of class Color
3167 Color
SwFEShell::GetShapeBackgrd() const
3171 // check, if a draw view exists
3172 OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
3173 if( Imp()->GetDrawView() )
3175 // determine list of selected objects
3176 const SdrMarkList
* pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
3177 // check, if exactly one object is selected.
3178 OSL_ENSURE( pMrkList
->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!");
3179 if ( pMrkList
->GetMarkCount() == 1)
3181 // get selected object
3182 const SdrObject
*pSdrObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
3183 // check, if selected object is a shape (drawing object)
3184 OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj
) == nullptr, "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
3185 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj
) == nullptr )
3187 // determine page frame of the frame the shape is anchored.
3188 const SwFrame
* pAnchorFrame
=
3189 static_cast<SwDrawContact
*>(GetUserCall(pSdrObj
))->GetAnchorFrame( pSdrObj
);
3190 OSL_ENSURE( pAnchorFrame
, "inconsistent model - no anchor at shape!");
3193 const SwPageFrame
* pPageFrame
= pAnchorFrame
->FindPageFrame();
3194 OSL_ENSURE( pPageFrame
, "inconsistent model - no page!");
3197 aRetColor
= pPageFrame
->GetDrawBackgrdColor();
3207 /** Is default horizontal text direction for selected drawing object right-to-left
3208 Because drawing objects only painted for each page only, the default
3209 horizontal text direction of a drawing object is given by the corresponding
3212 @returns boolean, indicating, if the horizontal text direction of the
3213 page, the selected drawing object is on, is right-to-left.
3215 bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const
3219 // check, if a draw view exists
3220 OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
3221 if( Imp()->GetDrawView() )
3223 // determine list of selected objects
3224 const SdrMarkList
* pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
3225 // check, if exactly one object is selected.
3226 OSL_ENSURE( pMrkList
->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!");
3227 if ( pMrkList
->GetMarkCount() == 1)
3229 // get selected object
3230 const SdrObject
*pSdrObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
3231 // check, if selected object is a shape (drawing object)
3232 OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj
) == nullptr, "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
3233 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj
) == nullptr )
3235 // determine page frame of the frame the shape is anchored.
3236 const SwFrame
* pAnchorFrame
=
3237 static_cast<SwDrawContact
*>(GetUserCall(pSdrObj
))->GetAnchorFrame( pSdrObj
);
3238 OSL_ENSURE( pAnchorFrame
, "inconsistent model - no anchor at shape!");
3241 const SwPageFrame
* pPageFrame
= pAnchorFrame
->FindPageFrame();
3242 OSL_ENSURE( pPageFrame
, "inconsistent model - no page!");
3245 bRet
= pPageFrame
->IsRightToLeft();
3255 Point
SwFEShell::GetRelativePagePosition(const Point
& rDocPos
)
3258 const SwFrame
*pPage
= GetLayout()->Lower();
3259 while ( pPage
&& !pPage
->getFrameArea().IsInside( rDocPos
) )
3261 pPage
= pPage
->GetNext();
3265 aRet
= rDocPos
- pPage
->getFrameArea().TopLeft();
3270 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */