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/constructhelper.hxx>
22 #include <svx/strings.hrc>
23 #include <svx/sdrobjectfilter.hxx>
24 #include <svx/svddrgmt.hxx>
25 #include <svx/svditer.hxx>
26 #include <svx/svdobj.hxx>
27 #include <svx/svdouno.hxx>
28 #include <svx/svdogrp.hxx>
29 #include <svx/svdocirc.hxx>
30 #include <svx/svdopath.hxx>
31 #include <svx/sxciaitm.hxx>
32 #include <svx/svdocapt.hxx>
33 #include <svx/xlnwtit.hxx>
34 #include <svx/xlnstwit.hxx>
35 #include <svx/xlnedwit.hxx>
36 #include <svx/xlnedit.hxx>
37 #include <svx/xlnstit.hxx>
38 #include <svx/svdomeas.hxx>
39 #include <svx/sdtagitm.hxx>
40 #include <svx/sdtacitm.hxx>
41 #include <svx/sdtaaitm.hxx>
42 #include <editeng/opaqitem.hxx>
43 #include <editeng/protitem.hxx>
44 #include <svx/svdpage.hxx>
45 #include <svx/svdpagv.hxx>
46 #include <svx/dialmgr.hxx>
47 #include <tools/globname.hxx>
48 #include <sot/exchange.hxx>
49 #include <IDocumentDrawModelAccess.hxx>
50 #include <IDocumentSettingAccess.hxx>
51 #include <DocumentSettingManager.hxx>
52 #include <IDocumentState.hxx>
53 #include <IDocumentLayoutAccess.hxx>
54 #include <drawdoc.hxx>
55 #include <textboxhelper.hxx>
58 #include <frmtool.hxx>
59 #include <fmtfsize.hxx>
60 #include <fmtanchr.hxx>
61 #include <fmtornt.hxx>
62 #include <fmtsrnd.hxx>
63 #include <fmtcntnt.hxx>
64 #include <fmtflcnt.hxx>
65 #include <fmtcnct.hxx>
66 #include <swmodule.hxx>
68 #include <rootfrm.hxx>
69 #include <pagefrm.hxx>
70 #include <sectfrm.hxx>
73 #include <IDocumentUndoRedo.hxx>
75 #include <dflyobj.hxx>
76 #include <dcontact.hxx>
77 #include <viewimp.hxx>
83 #include <viewopt.hxx>
85 #include <notxtfrm.hxx>
88 #include <sortedobjs.hxx>
89 #include <HandleAnchorNodeChg.hxx>
90 #include <basegfx/polygon/b2dpolygon.hxx>
91 #include <comphelper/lok.hxx>
92 #include <sfx2/lokhelper.hxx>
93 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
95 #include <flyfrms.hxx>
96 #include <basegfx/polygon/b2dpolygontools.hxx>
97 #include <svx/svxids.hrc>
98 #include <osl/diagnose.h>
100 #include <com/sun/star/embed/EmbedMisc.hpp>
101 #include <com/sun/star/embed/Aspects.hpp>
102 #include <com/sun/star/embed/XEmbeddedObject.hpp>
104 #include <svx/srchdlg.hxx>
108 using namespace com::sun::star
;
110 SwFlyFrame
*GetFlyFromMarked( const SdrMarkList
*pLst
, SwViewShell
*pSh
)
113 pLst
= pSh
->HasDrawView() ? &pSh
->Imp()->GetDrawView()->GetMarkedObjectList():nullptr;
115 if ( pLst
&& pLst
->GetMarkCount() == 1 )
117 SdrObject
*pO
= pLst
->GetMark( 0 )->GetMarkedSdrObj();
118 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pO
))
119 return pVirtO
->GetFlyFrame();
124 static void lcl_GrabCursor( SwFEShell
* pSh
, SwFlyFrame
* pOldSelFly
, SwFrameFormat
* pNewDrawFormat
= nullptr)
126 const SwFrameFormat
*pFlyFormat
= pSh
->SelFlyGrabCursor();
127 if( pFlyFormat
&& !pSh
->ActionPend() &&
128 (!pOldSelFly
|| pOldSelFly
->GetFormat() != pFlyFormat
) )
130 // now call set macro if applicable
131 pSh
->GetFlyMacroLnk().Call( static_cast<const SwFlyFrameFormat
*>(pFlyFormat
) );
132 // if a dialog was started inside a macro, then
133 // MouseButtonUp arrives at macro and not to us. Therefore
134 // flag is always set here and will never be switched to
135 // respective Shell !!!!!!!
137 g_bNoInterrupt
= false;
139 else if( !pFlyFormat
|| RES_DRAWFRMFMT
== pFlyFormat
->Which() )
141 // --> assure consistent cursor
146 // If we selected a draw shape format, move the cursor to its anchor position.
147 // SetCursor() may pick something inside, which is not wanted: code later assumes that
148 // the cursor is at the anchor point if a shape is selected.
149 const SwPosition
* pContentAnchor
= pNewDrawFormat
->GetAnchor().GetContentAnchor();
152 pSh
->SetSelection(SwPaM(*pContentAnchor
));
157 pSh
->SetCursor( pSh
->Imp()->GetDrawView()->GetAllMarkedRect().TopLeft(), true);
162 bool SwFEShell::SelectObj( const Point
& rPt
, sal_uInt8 nFlag
, SdrObject
*pObj
)
164 SwDrawView
*pDView
= Imp()->GetDrawView();
167 CurrShell
aCurr( this );
168 StartAction(); // action is necessary to assure only one AttrChgdNotify
169 // (e.g. due to Unmark->MarkListHasChgd) arrives
171 const SdrMarkList
&rMrkList
= pDView
->GetMarkedObjectList();
172 const bool bHadSelection
= rMrkList
.GetMarkCount();
173 const bool bAddSelect
= 0 != (SW_ADD_SELECT
& nFlag
);
174 const bool bEnterGroup
= 0 != (SW_ENTER_GROUP
& nFlag
);
175 SwFlyFrame
* pOldSelFly
= nullptr;
176 const Point
aOldPos( pDView
->GetAllMarkedRect().TopLeft() );
180 // call Unmark when !bAddSelect or if fly was selected
181 bool bUnmark
= !bAddSelect
;
183 if ( rMrkList
.GetMarkCount() == 1 )
185 // if fly was selected, deselect it first
186 pOldSelFly
= ::GetFlyFromMarked( &rMrkList
, this );
189 const sal_uInt16 nType
= GetCntType();
190 if( nType
!= CNT_TXT
|| (SW_LEAVE_FRAME
& nFlag
) ||
191 ( pOldSelFly
->GetFormat()->GetProtect().IsContentProtected()
192 && !IsReadOnlyAvailable() ))
194 // If a fly is deselected, which contains graphic, OLE or
195 // otherwise, the cursor should be removed from it.
196 // Similar if a fly with protected content is deselected.
197 // For simplicity we put the cursor next to the upper-left
199 Point
aPt( pOldSelFly
->getFrameArea().Pos() );
200 aPt
.setX(aPt
.getX() - 1);
201 bool bUnLockView
= !IsViewLocked();
203 SetCursor( aPt
, true );
207 if ( nType
& CNT_GRF
&&
208 static_cast<SwNoTextFrame
*>(pOldSelFly
->Lower())->HasAnimation() )
210 GetWin()->Invalidate( pOldSelFly
->getFrameArea().SVRect() );
214 if ( SdrDragMode::Crop
== GetDragMode() )
215 SetDragMode( SdrDragMode::Move
);
224 pOldSelFly
->SelectionHasChanged(this);
235 OSL_ENSURE( !bEnterGroup
, "SW_ENTER_GROUP is not supported" );
236 pDView
->MarkObj( pObj
, Imp()->GetPageView() );
240 // tolerance limit of Drawing-SS
241 const auto nHdlSizePixel
= Imp()->GetDrawView()->GetMarkHdlSizePixel();
242 const short nMinMove
= static_cast<short>(GetOut()->PixelToLogic(Size(nHdlSizePixel
/2, 0)).Width());
243 pDView
->MarkObj( rPt
, nMinMove
, bAddSelect
, bEnterGroup
);
246 const bool bRet
= 0 != rMrkList
.GetMarkCount();
248 if ( rMrkList
.GetMarkCount() > 1 )
250 // It sucks if Drawing objects were selected and now
251 // additionally a fly is selected.
252 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
254 SdrObject
*pTmpObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
255 bool bForget
= dynamic_cast<const SwVirtFlyDrawObj
*>( pTmpObj
) != nullptr;
259 pDView
->MarkObj( pTmpObj
, Imp()->GetPageView(), bAddSelect
, bEnterGroup
);
265 if (rMrkList
.GetMarkCount() == 1)
267 SwFlyFrame
* pSelFly
= ::GetFlyFromMarked(&rMrkList
, this);
268 if (pSelFly
&& pSelFly
->IsFlySplitAllowed())
270 auto pMaster
= static_cast<SwFlyAtContentFrame
*>(pSelFly
);
271 while (pMaster
->IsFollow())
273 pMaster
= pMaster
->GetPrecede();
275 if (pMaster
!= pSelFly
)
277 // A follow fly frame is selected, select the master instead. Selection of a follow
278 // would not be ideal, since one can't customize its vertical position (always
279 // starts at the top of the page).
281 pDView
->MarkObj(pMaster
->DrawObj(), Imp()->GetPageView(), bAddSelect
, bEnterGroup
);
286 if ( rMrkList
.GetMarkCount() == 1 )
288 SwFlyFrame
*pSelFly
= ::GetFlyFromMarked( &rMrkList
, this );
290 pSelFly
->SelectionHasChanged(this);
293 SwFrameFormat
* pNewDrawFormat
= nullptr;
294 if (!(nFlag
& SW_ALLOW_TEXTBOX
))
296 // If the fly frame is a textbox of a shape, then select the shape instead.
297 for (size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
299 SdrObject
* pObject
= rMrkList
.GetMark(i
)->GetMarkedSdrObj();
300 SwContact
* pContact
= GetUserCall(pObject
);
306 SwFrameFormat
* pFormat
= pContact
->GetFormat();
307 if (SwFrameFormat
* pShapeFormat
= SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_FLYFRMFMT
))
309 SdrObject
* pShape
= pShapeFormat
->FindSdrObject();
311 pDView
->MarkObj(pShape
, Imp()->GetPageView(), bAddSelect
, bEnterGroup
);
312 // Remember that this frame format was marked for selection.
313 pNewDrawFormat
= pShapeFormat
;
321 ::lcl_GrabCursor(this, pOldSelFly
, pNewDrawFormat
);
322 if ( GetCntType() & CNT_GRF
)
324 const SwFlyFrame
*pTmp
= GetFlyFromMarked( &rMrkList
, this );
325 OSL_ENSURE( pTmp
, "Graphic without Fly" );
326 if ( pTmp
&& static_cast<const SwNoTextFrame
*>(pTmp
->Lower())->HasAnimation() )
327 static_cast<const SwNoTextFrame
*>(pTmp
->Lower())->StopAnimation( GetOut() );
330 else if ( !pOldSelFly
&& bHadSelection
)
331 SetCursor( aOldPos
, true);
333 if( bRet
|| !bHadSelection
)
336 // update status line
337 ::FrameNotify( this, bRet
? FLY_DRAG_START
: FLY_DRAG_END
);
344 * Description: MoveAnchor( nDir ) looked for an another Anchor for
345 * the selected drawing object (or fly frame) in the given direction.
346 * An object "as character" doesn't moves anyway.
347 * A page bounded object could move to the previous/next page with up/down,
348 * an object bounded "at paragraph" moves to the previous/next paragraph, too.
349 * An object bounded "at character" moves to the previous/next paragraph
350 * with up/down and to the previous/next character with left/right.
351 * If the anchor for at paragraph/character bounded objects has vertical or
352 * right_to_left text direction, the directions for up/down/left/right will
353 * interpreted accordingly.
354 * An object bounded "at fly" takes the center of the actual anchor and looks
355 * for the nearest fly frame in the given direction.
358 static bool LessX( Point
const & aPt1
, Point
const & aPt2
, bool bOld
)
360 return aPt1
.getX() < aPt2
.getX()
361 || ( aPt1
.getX() == aPt2
.getX()
362 && ( aPt1
.getY() < aPt2
.getY()
363 || ( aPt1
.getY() == aPt2
.getY() && bOld
) ) );
365 static bool LessY( Point
const & aPt1
, Point
const & aPt2
, bool bOld
)
367 return aPt1
.getY() < aPt2
.getY()
368 || ( aPt1
.getY() == aPt2
.getY()
369 && ( aPt1
.getX() < aPt2
.getX()
370 || ( aPt1
.getX() == aPt2
.getX() && bOld
) ) );
373 bool SwFEShell::MoveAnchor( SwMove nDir
)
375 if (!Imp()->GetDrawView())
377 const SdrMarkList
& pMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
378 if (1 != pMrkList
.GetMarkCount())
381 SdrObject
*pObj
= pMrkList
.GetMark( 0 )->GetMarkedSdrObj();
382 SwDrawContact
* pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
387 SwFlyFrame
* pFly
= nullptr;
388 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
390 pFly
= pVirtO
->GetFlyFrame();
391 pOld
= pFly
->AnchorFrame();
394 pOld
= pContact
->GetAnchorFrame( pObj
);
398 SwFrame
* pNew
= pOld
;
400 SwAnchoredObject
* pAnchoredObj
= pContact
->GetAnchoredObj( pObj
);
401 SwFrameFormat
* pFormat
= pAnchoredObj
->GetFrameFormat();
402 SwFormatAnchor
aAnch( pFormat
->GetAnchor() );
403 RndStdIds nAnchorId
= aAnch
.GetAnchorId();
404 if ( RndStdIds::FLY_AS_CHAR
== nAnchorId
)
406 if( pOld
->IsVertical() )
408 if( pOld
->IsTextFrame() )
411 case SwMove::UP
: nDir
= SwMove::LEFT
; break;
412 case SwMove::DOWN
: nDir
= SwMove::RIGHT
; break;
413 case SwMove::LEFT
: nDir
= SwMove::DOWN
; break;
414 case SwMove::RIGHT
: nDir
= SwMove::UP
; break;
416 if( pOld
->IsRightToLeft() )
418 if( nDir
== SwMove::LEFT
)
419 nDir
= SwMove::RIGHT
;
420 else if( nDir
== SwMove::RIGHT
)
425 switch ( nAnchorId
) {
426 case RndStdIds::FLY_AT_PAGE
:
428 OSL_ENSURE( pOld
->IsPageFrame(), "Wrong anchor, page expected." );
429 if( SwMove::UP
== nDir
)
430 pNew
= pOld
->GetPrev();
431 else if( SwMove::DOWN
== nDir
)
432 pNew
= pOld
->GetNext();
433 if( pNew
&& pNew
!= pOld
)
435 aAnch
.SetPageNum( static_cast<SwPageFrame
*>(pNew
)->GetPhyPageNum() );
440 case RndStdIds::FLY_AT_CHAR
:
442 OSL_ENSURE(pOld
->IsTextFrame(), "Wrong anchor, text frame expected.");
443 if( SwMove::LEFT
== nDir
|| SwMove::RIGHT
== nDir
)
445 SwPosition pos
= *aAnch
.GetContentAnchor();
446 SwTextFrame
*const pOldFrame(static_cast<SwTextFrame
*>(pOld
));
447 TextFrameIndex
const nAct(pOldFrame
->MapModelToViewPos(pos
));
448 if( SwMove::LEFT
== nDir
)
453 pos
= pOldFrame
->MapViewToModelPos(nAct
- TextFrameIndex(1));
460 TextFrameIndex
const nMax(pOldFrame
->GetText().getLength());
464 pos
= pOldFrame
->MapViewToModelPos(nAct
+ TextFrameIndex(1));
469 if( pos
!= *aAnch
.GetContentAnchor())
470 aAnch
.SetAnchor( &pos
);
474 case RndStdIds::FLY_AT_PARA
:
476 OSL_ENSURE(pOld
->IsTextFrame(), "Wrong anchor, text frame expected.");
477 if( SwMove::UP
== nDir
)
478 pNew
= pOld
->FindPrev();
479 else if( SwMove::DOWN
== nDir
)
480 pNew
= pOld
->FindNext();
481 if( pNew
&& pNew
!= pOld
&& pNew
->IsContentFrame() )
483 SwTextFrame
*const pNewFrame(static_cast<SwTextFrame
*>(pNew
));
484 SwPosition
const pos
= pNewFrame
->MapViewToModelPos(
486 (bRet
&& pNewFrame
->GetText().getLength() != 0)
487 ? pNewFrame
->GetText().getLength() - 1
489 aAnch
.SetAnchor( &pos
);
492 else if( SwMove::UP
== nDir
|| SwMove::DOWN
== nDir
)
496 case RndStdIds::FLY_AT_FLY
:
498 OSL_ENSURE( pOld
->IsFlyFrame(), "Wrong anchor, fly frame expected.");
499 SwPageFrame
* pPage
= pOld
->FindPageFrame();
500 OSL_ENSURE( pPage
, "Where's my page?" );
501 SwFlyFrame
* pNewFly
= nullptr;
502 if( pPage
->GetSortedObjs() )
505 Point
aCenter( pOld
->getFrameArea().Left() + pOld
->getFrameArea().Width()/2,
506 pOld
->getFrameArea().Top() + pOld
->getFrameArea().Height()/2 );
508 for(SwAnchoredObject
* pAnchObj
: *pPage
->GetSortedObjs())
510 if( auto pTmp
= pAnchObj
->DynCastFlyFrame() )
516 const SwFlyFrame
* pCheck
= pFly
? pTmp
: nullptr;
521 const SwFrame
*pNxt
= pCheck
->GetAnchorFrame();
522 pCheck
= pNxt
? pNxt
->FindFlyFrame() : nullptr;
524 if( pCheck
|| pTmp
->IsProtected() )
526 Point
aNew( pTmp
->getFrameArea().Left() +
527 pTmp
->getFrameArea().Width()/2,
528 pTmp
->getFrameArea().Top() +
529 pTmp
->getFrameArea().Height()/2 );
530 bool bAccept
= false;
534 bAccept
= LessX( aCenter
, aNew
, bOld
)
536 LessX( aNew
, aBest
, false ) );
541 bAccept
= LessX( aNew
, aCenter
, !bOld
)
543 LessX( aBest
, aNew
, true ) );
548 bAccept
= LessY( aNew
, aCenter
, !bOld
)
550 LessY( aBest
, aNew
, true ) );
555 bAccept
= LessY( aCenter
, aNew
, bOld
)
557 LessY( aNew
, aBest
, false ) );
573 SwPosition
aPos( *pNewFly
->GetFormat()->
574 GetContent().GetContentIdx());
575 aAnch
.SetAnchor( &aPos
);
585 // --> handle change of anchor node:
586 // if count of the anchor frame also change, the fly frames have to be
587 // re-created. Thus, delete all fly frames except the <this> before the
588 // anchor attribute is change and re-create them afterwards.
590 std::unique_ptr
<SwHandleAnchorNodeChg
> pHandleAnchorNodeChg
;
591 SwFlyFrameFormat
* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat
*>(pFormat
) );
592 if ( pFlyFrameFormat
)
594 pHandleAnchorNodeChg
.reset(
595 new SwHandleAnchorNodeChg( *pFlyFrameFormat
, aAnch
));
597 pFormat
->GetDoc()->SetAttr( aAnch
, *pFormat
);
599 // #i28701# - no call of method
600 // <CheckCharRectAndTopOfLine()> for to-character anchored
601 // Writer fly frame needed. This method call can cause a
602 // format of the anchor frame, which is no longer intended.
603 // Instead clear the anchor character rectangle and
604 // the top of line values for all to-character anchored objects.
605 pAnchoredObj
->ClearCharRectAndTopOfLine();
612 const SdrMarkList
* SwFEShell::GetMarkList_() const
614 const SdrMarkList
* pMarkList
= nullptr;
615 if( Imp()->GetDrawView() != nullptr )
616 pMarkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
620 FrameTypeFlags
SwFEShell::GetSelFrameType() const
622 FrameTypeFlags eType
;
624 // get marked frame list, and check if anything is selected
625 const SdrMarkList
* pMarkList
= GetMarkList_();
626 if( pMarkList
== nullptr || pMarkList
->GetMarkCount() == 0 )
627 eType
= FrameTypeFlags::NONE
;
630 // obtain marked item as fly frame; if no fly frame, it must
632 const SwFlyFrame
* pFly
= ::GetFlyFromMarked(pMarkList
, const_cast<SwFEShell
*>(this));
633 if ( pFly
!= nullptr )
635 if( pFly
->IsFlyLayFrame() )
636 eType
= FrameTypeFlags::FLY_FREE
;
637 else if( pFly
->IsFlyAtContentFrame() )
638 eType
= FrameTypeFlags::FLY_ATCNT
;
641 OSL_ENSURE( pFly
->IsFlyInContentFrame(), "New frametype?" );
642 eType
= FrameTypeFlags::FLY_INCNT
;
646 eType
= FrameTypeFlags::DRAWOBJ
;
652 // does the draw selection contain a control?
653 bool SwFEShell::IsSelContainsControl() const
657 // basically, copy the mechanism from GetSelFrameType(), but call
658 // CheckControl... if you get a drawing object
659 const SdrMarkList
* pMarkList
= GetMarkList_();
660 if( pMarkList
!= nullptr && pMarkList
->GetMarkCount() == 1 )
662 // if we have one marked object, get the SdrObject and check
663 // whether it contains a control
664 const SdrObject
* pSdrObject
= pMarkList
->GetMark( 0 )->GetMarkedSdrObj();
665 bRet
= pSdrObject
&& ::CheckControlLayer( pSdrObject
);
670 void SwFEShell::ScrollTo( const Point
&rPt
)
672 const SwRect
aRect( rPt
, rPt
);
673 if ( IsScrollMDI( this, aRect
) &&
674 (!Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ||
675 Imp()->IsDragPossible( rPt
)) )
677 ScrollMDI( this, aRect
, SCROLLVAL
, SCROLLVAL
);
681 void SwFEShell::SetDragMode( SdrDragMode eDragMode
)
683 if ( Imp()->HasDrawView() )
684 Imp()->GetDrawView()->SetDragMode( eDragMode
);
687 SdrDragMode
SwFEShell::GetDragMode() const
689 SdrDragMode nRet
= SdrDragMode(0);
690 if ( Imp()->HasDrawView() )
692 nRet
= Imp()->GetDrawView()->GetDragMode();
697 void SwFEShell::StartCropImage()
699 if ( !Imp()->HasDrawView() )
703 SdrView
*pView
= Imp()->GetDrawView();
706 const SdrMarkList
&rMarkList
= pView
->GetMarkedObjectList();
707 if( 0 == rMarkList
.GetMarkCount() ) {
708 // No object selected
712 // If more than a single SwVirtFlyDrawObj is selected, select only the first SwVirtFlyDrawObj
713 if ( rMarkList
.GetMarkCount() > 1 )
715 for ( size_t i
= 0; i
< rMarkList
.GetMarkCount(); ++i
)
717 SdrObject
*pTmpObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
718 bool bForget
= dynamic_cast<const SwVirtFlyDrawObj
*>( pTmpObj
) != nullptr;
722 pView
->MarkObj( pTmpObj
, Imp()->GetPageView() );
728 // Activate CROP mode
729 pView
->SetEditMode( SdrViewEditMode::Edit
);
730 SetDragMode( SdrDragMode::Crop
);
733 void SwFEShell::BeginDrag( const Point
* pPt
, bool bIsShift
)
735 SdrView
*pView
= Imp()->GetDrawView();
736 if ( pView
&& pView
->GetMarkedObjectList().GetMarkCount() != 0 )
738 m_pChainFrom
.reset();
740 SdrHdl
* pHdl
= pView
->PickHandle( *pPt
);
741 if (pView
->BegDragObj( *pPt
, nullptr, pHdl
))
742 pView
->GetDragMethod()->SetShiftPressed( bIsShift
);
743 ::FrameNotify( this );
747 void SwFEShell::Drag( const Point
*pPt
, bool )
749 OSL_ENSURE( Imp()->HasDrawView(), "Drag without DrawView?" );
750 if ( HasDrawViewDrag() )
753 Imp()->GetDrawView()->MovDragObj( *pPt
);
754 Imp()->GetDrawView()->ShowDragAnchor();
755 ::FrameNotify( this );
759 void SwFEShell::EndDrag()
761 OSL_ENSURE( Imp()->HasDrawView(), "EndDrag without DrawView?" );
762 SdrView
*pView
= Imp()->GetDrawView();
763 if ( !pView
->IsDragObj() )
766 for(SwViewShell
& rSh
: GetRingContainer())
769 StartUndo( SwUndoId::START
);
771 // #50778# Bug during dragging: In StartAction a HideShowXor is called.
772 // In EndDragObj() this is reversed, for no reason and even wrong.
773 // To restore consistency we should bring up the Xor again.
775 // Reanimation from the hack #50778 to fix bug #97057
776 // May be not the best solution, but the one with lowest risc at the moment.
777 // pView->ShowShownXor( GetOut() );
781 // DrawUndo on to flyframes are not stored
782 // The flys change the flag.
783 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
784 ChgAnchor( RndStdIds::FLY_AT_PARA
, true );
786 EndUndo( SwUndoId::END
);
788 for(SwViewShell
& rSh
: GetRingContainer())
791 if( auto pCursorShell
= dynamic_cast<SwCursorShell
*>(&rSh
) )
792 pCursorShell
->CallChgLnk();
795 GetDoc()->getIDocumentState().SetModified();
796 ::FrameNotify( this );
799 void SwFEShell::BreakDrag()
801 OSL_ENSURE( Imp()->HasDrawView(), "BreakDrag without DrawView?" );
802 if( HasDrawViewDrag() )
803 Imp()->GetDrawView()->BrkDragObj();
807 // If a fly is selected, pulls the crsr in the first ContentFrame
808 const SwFrameFormat
* SwFEShell::SelFlyGrabCursor()
810 if ( Imp()->HasDrawView() )
812 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
813 SwFlyFrame
*pFly
= ::GetFlyFromMarked( &rMrkList
, this );
817 SwContentFrame
*pCFrame
= pFly
->ContainsContent();
820 // --> assure, that the cursor is consistent.
823 SwPaM
*pCursor
= GetCursor();
825 if (pCFrame
->IsTextFrame())
827 *pCursor
->GetPoint() = static_cast<SwTextFrame
*>(pCFrame
)
828 ->MapViewToModelPos(TextFrameIndex(0));
832 assert(pCFrame
->IsNoTextFrame());
833 SwContentNode
*const pCNode
= static_cast<SwNoTextFrame
*>(pCFrame
)->GetNode();
834 pCursor
->GetPoint()->Assign(*pCNode
);
837 SwRect
& rChrRect
= const_cast<SwRect
&>(GetCharRect());
838 rChrRect
= pFly
->getFramePrintArea();
839 rChrRect
.Pos() += pFly
->getFrameArea().Pos();
840 GetCursorDocPos() = rChrRect
.Pos();
842 return pFly
->GetFormat();
848 // Selection to above/below (Z-Order)
849 static void lcl_NotifyNeighbours( const SdrMarkList
*pLst
)
851 // Rules for evasion have changed.
852 // 1. The environment of the fly and everything inside should be notified
853 // 2. The content of the frame itself has to be notified
854 // 3. Frames displaced by the frame have to be notified
855 // 4. Also Drawing objects can displace frames
856 for( size_t j
= 0; j
< pLst
->GetMarkCount(); ++j
)
859 bool bCheckNeighbours
= false;
860 sal_Int16 aHori
= text::HoriOrientation::NONE
;
862 SdrObject
*pO
= pLst
->GetMark( j
)->GetMarkedSdrObj();
863 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pO
))
865 SwFlyFrame
*pFly
= pVirtO
->GetFlyFrame();
867 const SwFormatHoriOrient
&rHori
= pFly
->GetFormat()->GetHoriOrient();
868 aHori
= rHori
.GetHoriOrient();
869 if( text::HoriOrientation::NONE
!= aHori
&& text::HoriOrientation::CENTER
!= aHori
&&
870 pFly
->IsFlyAtContentFrame() )
872 bCheckNeighbours
= true;
873 pFly
->InvalidatePos();
874 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pFly
);
875 aFrm
.Pos().AdjustY(1 );
878 pPage
= pFly
->FindPageFrame();
879 aRect
= pFly
->getFrameArea();
883 SwDrawContact
* pContact
= static_cast<SwDrawContact
*>(GetUserCall(pO
));
887 SwFrame
* pAnch
= pContact
->GetAnchorFrame( pO
);
890 pPage
= pAnch
->FindPageFrame();
891 // #i68520# - naming changed
892 aRect
= GetBoundRectOfAnchoredObj( pO
);
895 const size_t nCount
= pPage
->GetSortedObjs() ? pPage
->GetSortedObjs()->size() : 0;
896 for ( size_t i
= 0; i
< nCount
; ++i
)
898 SwAnchoredObject
* pAnchoredObj
= (*pPage
->GetSortedObjs())[i
];
899 SwFlyFrame
* pAct
= pAnchoredObj
->DynCastFlyFrame();
903 SwRect
aTmpCalcPnt( pAct
->getFramePrintArea() );
904 aTmpCalcPnt
+= pAct
->getFrameArea().Pos();
905 if ( aRect
.Overlaps( aTmpCalcPnt
) )
907 SwContentFrame
*pCnt
= pAct
->ContainsContent();
910 aTmpCalcPnt
= pCnt
->getFramePrintArea();
911 aTmpCalcPnt
+= pCnt
->getFrameArea().Pos();
912 if ( aRect
.Overlaps( aTmpCalcPnt
) )
913 static_cast<SwFrame
*>(pCnt
)->Prepare( PrepareHint::FlyFrameAttributesChanged
);
914 pCnt
= pCnt
->GetNextContentFrame();
917 if ( bCheckNeighbours
&& pAct
->IsFlyAtContentFrame() )
919 const SwFormatHoriOrient
&rH
= pAct
->GetFormat()->GetHoriOrient();
920 if ( rH
.GetHoriOrient() == aHori
&&
921 pAct
->getFrameArea().Top() <= aRect
.Bottom() &&
922 pAct
->getFrameArea().Bottom() >= aRect
.Top() )
924 pAct
->InvalidatePos();
925 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pAct
);
926 aFrm
.Pos().AdjustY(1 );
933 void SwFEShell::SetLineEnds(SfxItemSet
& rAttr
, SdrObject
const & rObj
, sal_uInt16 nSlotId
)
935 ConstructHelper::SetLineEnds(rAttr
, rObj
, nSlotId
, 100);
938 void SwFEShell::SelectionToTop( bool bTop
)
940 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToTop without DrawView?" );
941 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
942 OSL_ENSURE( rMrkList
.GetMarkCount(), "No object selected." );
944 SwFlyFrame
*pFly
= ::GetFlyFromMarked( &rMrkList
, this );
945 if ( pFly
&& pFly
->IsFlyInContentFrame() )
950 Imp()->GetDrawView()->PutMarkedToTop();
952 Imp()->GetDrawView()->MovMarkedToTop();
953 ::lcl_NotifyNeighbours( &rMrkList
);
955 // Does the selection contain a textbox?
956 for (size_t i
= 0; i
< rMrkList
.GetMarkCount(); i
++)
957 if (auto pObj
= rMrkList
.GetMark(i
)->GetMarkedSdrObj())
958 // Get the textbox-shape
959 if (auto pFormat
= FindFrameFormat(pObj
))
961 // If it has not textframe skip...
962 if (!SwTextBoxHelper::isTextBox(pFormat
, RES_DRAWFRMFMT
, pObj
))
964 // If it has a textframe so it is a textbox, get its page
966 = pFormat
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel())
967 // Not really understood why everything is on page 0...
968 // but it is easier to handle sdrobjects, that's true
969 if (auto pPage
= pDrwModel
->GetPage(0))
971 // nShift: it means how many layers the pObj have to be shifted up,
972 // in order not to interfere with other shapes and textboxes.
974 // - The next shape has textframe: This shape have to shifted with
976 // - The next shape has not got textframe: This shape have to be
977 // shifted only one layer up.
978 // - The next shape is null:
979 // - This shape is already at heaven: Only the textframe have
981 sal_uInt32 nShift
= 0;
982 // Get the one level higher object (note: can be nullptr!)
983 const auto pNextObj
= pPage
->SetObjectOrdNum(pObj
->GetOrdNum() + 1, pObj
->GetOrdNum() + 1);
984 // If there is a higher object (not null)...
987 // One level shift is necessary
989 // If this object is a textbox, two level increasing needed
990 // (one for the shape and one for the frame)
991 if (auto pNextFormat
= FindFrameFormat(pNextObj
))
992 if (SwTextBoxHelper::isTextBox(pNextFormat
, RES_DRAWFRMFMT
, pNextObj
)
993 || SwTextBoxHelper::isTextBox(pNextFormat
, RES_FLYFRMFMT
))
996 // Set the new z-order.
997 pPage
->SetObjectOrdNum(pObj
->GetOrdNum(), pObj
->GetOrdNum() + nShift
);
999 // The shape is on the right level, correct the layer of the frame
1000 SwTextBoxHelper::DoTextBoxZOrderCorrection(pFormat
, pObj
);
1003 GetDoc()->getIDocumentState().SetModified();
1007 void SwFEShell::SelectionToBottom( bool bBottom
)
1009 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToBottom without DrawView?" );
1010 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1011 OSL_ENSURE( rMrkList
.GetMarkCount(), "No object selected." );
1013 SwFlyFrame
*pFly
= ::GetFlyFromMarked( &rMrkList
, this );
1014 if ( pFly
&& pFly
->IsFlyInContentFrame() )
1019 Imp()->GetDrawView()->PutMarkedToBtm();
1021 Imp()->GetDrawView()->MovMarkedToBtm();
1022 ::lcl_NotifyNeighbours( &rMrkList
);
1024 // If the selection has textbox
1025 for(size_t i
= 0; i
< rMrkList
.GetMarkCount(); i
++)
1026 if (auto pObj
= rMrkList
.GetMark(i
)->GetMarkedSdrObj())
1027 // Get the shape of the textbox
1028 if (auto pFormat
= FindFrameFormat(pObj
))
1030 // If the shape has not textframes skip.
1031 if (!SwTextBoxHelper::isTextBox(pFormat
, RES_DRAWFRMFMT
, pObj
))
1033 // If has, move the shape to correct level with...
1035 = pFormat
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel())
1036 if (auto pPage
= pDrwModel
->GetPage(0))
1038 const auto pNextObj
= pPage
->SetObjectOrdNum(pObj
->GetOrdNum() - 1, pObj
->GetOrdNum() - 1);
1039 // If there is a lower object (not null)...
1042 // If the lower has no textframe, just do nothing, else move by one lower
1043 if (auto pNextFormat
= FindFrameFormat(pNextObj
))
1044 if (SwTextBoxHelper::isTextBox(pNextFormat
, RES_DRAWFRMFMT
, pNextObj
)
1045 || SwTextBoxHelper::isTextBox(pNextFormat
, RES_FLYFRMFMT
))
1046 pPage
->SetObjectOrdNum(pObj
->GetOrdNum(), pObj
->GetOrdNum() - 1);
1049 // And set correct layer for the selected textbox.
1050 SwTextBoxHelper::DoTextBoxZOrderCorrection(pFormat
, pObj
);
1053 GetDoc()->getIDocumentState().SetModified();
1057 // Object above/below the document? 2 Controls, 1 Heaven, 0 Hell,
1058 // SDRLAYER_NOTFOUND Ambiguous
1059 SdrLayerID
SwFEShell::GetLayerId() const
1061 if ( !Imp()->HasDrawView() )
1062 return SDRLAYER_NOTFOUND
;
1064 SdrLayerID nRet
= SDRLAYER_NOTFOUND
;
1065 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1066 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
1068 const SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
1071 if ( nRet
== SDRLAYER_NOTFOUND
)
1072 nRet
= pObj
->GetLayer();
1073 else if ( nRet
!= pObj
->GetLayer() )
1075 return SDRLAYER_NOTFOUND
;
1081 // Object above/below the document
1082 // Note: only visible objects can be marked. Thus, objects with invisible
1083 // layer IDs have not to be considered.
1084 // If <SwFEShell> exists, layout exists!!
1085 void SwFEShell::ChangeOpaque( SdrLayerID nLayerId
)
1087 if ( !Imp()->HasDrawView() )
1090 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1091 const IDocumentDrawModelAccess
& rIDDMA
= getIDocumentDrawModelAccess();
1092 // correct type of <nControls>
1093 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
1095 SdrObject
* pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
1098 // or group objects containing controls.
1100 // consider that a member of a drawing group has been selected.
1101 const SwContact
* pContact
= ::GetUserCall( pObj
);
1102 OSL_ENSURE( pContact
&& pContact
->GetMaster(), "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!" );
1103 const bool bControlObj
= ( pContact
&& pContact
->GetMaster() )
1104 ? ::CheckControlLayer( pContact
->GetMaster() )
1105 : ::CheckControlLayer( pObj
);
1106 if ( !bControlObj
&& pObj
->GetLayer() != nLayerId
)
1108 pObj
->SetLayer( nLayerId
);
1109 InvalidateWindows( SwRect( pObj
->GetCurrentBoundRect() ) );
1110 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
1112 SwFormat
*pFormat
= pVirtO
->GetFlyFrame()->GetFormat();
1113 SvxOpaqueItem
aOpa( pFormat
->GetOpaque() );
1114 aOpa
.SetValue( nLayerId
== rIDDMA
.GetHellId() );
1115 pFormat
->SetFormatAttr( aOpa
);
1116 // If pObj has textframe, put its textframe to the right level
1117 if (auto pTextBx
= FindFrameFormat(pObj
))
1118 SwTextBoxHelper::DoTextBoxZOrderCorrection(pTextBx
, pObj
);
1122 GetDoc()->getIDocumentState().SetModified();
1125 void SwFEShell::SelectionToHeaven()
1127 ChangeOpaque( getIDocumentDrawModelAccess().GetHeavenId() );
1130 void SwFEShell::SelectionToHell()
1132 ChangeOpaque( getIDocumentDrawModelAccess().GetHellId() );
1135 size_t SwFEShell::IsObjSelected() const
1137 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1140 return Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount();
1143 bool SwFEShell::IsFrameSelected() const
1145 if ( !Imp()->HasDrawView() )
1148 return nullptr != ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
1149 const_cast<SwFEShell
*>(this) );
1152 bool SwFEShell::IsObjSelected( const SdrObject
& rObj
) const
1154 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1157 return Imp()->GetDrawView()->IsObjMarked( &rObj
);
1160 bool SwFEShell::IsRotationOfSwGrfNodePossible() const
1162 // RotGrfFlyFrame: check if RotationMode is possible
1163 const SdrView
*pSdrView
= Imp()->GetDrawView();
1167 const SdrMarkList
& rList(pSdrView
->GetMarkedObjectList());
1169 if(1 == rList
.GetMarkCount())
1171 const SwVirtFlyDrawObj
* pVirtFlyDraw(dynamic_cast< const SwVirtFlyDrawObj
* >(rList
.GetMark(0)->GetMarkedSdrObj()));
1173 if(nullptr != pVirtFlyDraw
)
1175 return pVirtFlyDraw
->ContainsSwGrfNode();
1183 bool SwFEShell::IsObjSameLevelWithMarked(const SdrObject
* pObj
) const
1187 const SdrMarkList
& aMarkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1188 if (aMarkList
.GetMarkCount() == 0)
1192 SdrMark
* pM
=aMarkList
.GetMark(0);
1195 SdrObject
* pMarkObj
= pM
->GetMarkedSdrObj();
1196 if (pMarkObj
&& pMarkObj
->getParentSdrObjectFromSdrObject() == pObj
->getParentSdrObjectFromSdrObject())
1203 void SwFEShell::EndTextEdit()
1205 // Terminate the TextEditMode. If required (default if the object
1206 // does not contain any more text and does not carry attributes) the object
1207 // is deleted. All other objects marked are preserved.
1209 OSL_ENSURE( Imp()->HasDrawView() && Imp()->GetDrawView()->IsTextEdit(),
1210 "EndTextEdit a no Object" );
1213 SdrView
*pView
= Imp()->GetDrawView();
1214 SdrObject
*pObj
= pView
->GetTextEditObject();
1215 SdrObjUserCall
* pUserCall
= GetUserCall(pObj
);
1216 if( nullptr != pUserCall
)
1218 SdrObject
*pTmp
= static_cast<SwContact
*>(pUserCall
)->GetMaster();
1221 pUserCall
->Changed( *pTmp
, SdrUserCallType::Resize
, pTmp
->GetLastBoundRect() );
1223 if ( !pObj
->getParentSdrObjectFromSdrObject() )
1225 if ( SdrEndTextEditKind::ShouldBeDeleted
== pView
->SdrEndTextEdit(true) )
1227 if ( pView
->GetMarkedObjectList().GetMarkCount() > 1 )
1229 SdrMarkList
aSave( pView
->GetMarkedObjectList() );
1230 aSave
.DeleteMark( aSave
.FindObject( pObj
) );
1231 if ( aSave
.GetMarkCount() )
1234 pView
->MarkObj( pObj
, Imp()->GetPageView() );
1237 for ( size_t i
= 0; i
< aSave
.GetMarkCount(); ++i
)
1238 pView
->MarkObj( aSave
.GetMark( i
)->GetMarkedSdrObj(), Imp()->GetPageView() );
1245 pView
->SdrEndTextEdit();
1247 if (comphelper::LibreOfficeKit::isActive())
1248 SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_LOCK
, "rectangle", "EMPTY"_ostr
);
1253 bool SwFEShell::IsInsideSelectedObj( const Point
&rPt
)
1255 if( Imp()->HasDrawView() )
1257 SwDrawView
*pDView
= Imp()->GetDrawView();
1259 if( pDView
->GetMarkedObjectList().GetMarkCount() &&
1260 pDView
->IsMarkedObjHit( rPt
) )
1268 bool SwFEShell::IsObjSelectable( const Point
& rPt
)
1270 CurrShell
aCurr(this);
1271 SwDrawView
*pDView
= Imp()->GetDrawView();
1276 const auto nOld
= pDView
->GetHitTolerancePixel();
1277 pDView
->SetHitTolerancePixel( pDView
->GetMarkHdlSizePixel()/2 );
1279 bRet
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMARKABLE
) != nullptr;
1280 pDView
->SetHitTolerancePixel( nOld
);
1285 SdrObject
* SwFEShell::GetObjAt( const Point
& rPt
)
1287 SdrObject
* pRet
= nullptr;
1288 CurrShell
aCurr(this);
1289 SwDrawView
*pDView
= Imp()->GetDrawView();
1293 const auto nOld
= pDView
->GetHitTolerancePixel();
1294 pDView
->SetHitTolerancePixel( pDView
->GetMarkHdlSizePixel()/2 );
1296 pRet
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMARKABLE
);
1297 pDView
->SetHitTolerancePixel( nOld
);
1302 // Test if there is an object at that position and if it should be selected.
1303 bool SwFEShell::ShouldObjectBeSelected(const Point
& rPt
, bool *pSelectFrameInsteadOfCroppedImage
)
1305 CurrShell
aCurr(this);
1306 SwDrawView
*pDrawView
= Imp()->GetDrawView();
1312 const auto nOld(pDrawView
->GetHitTolerancePixel());
1313 sal_uInt16 nHitTol
= pDrawView
->getHitTolLog();
1315 pDrawView
->SetHitTolerancePixel(pDrawView
->GetMarkHdlSizePixel()/2);
1316 SdrObject
* pObj
= pDrawView
->PickObj(rPt
, nHitTol
, pPV
, SdrSearchOptions::PICKMARKABLE
);
1317 pDrawView
->SetHitTolerancePixel(nOld
);
1322 const IDocumentDrawModelAccess
& rIDDMA
= getIDocumentDrawModelAccess();
1324 // Do not select object in background which is overlapping this text
1325 // at the given position.
1326 bool bObjInBackground( false );
1328 if ( pObj
->GetLayer() == rIDDMA
.GetHellId() )
1330 if (const SwContact
* pContact
= ::GetUserCall( pObj
))
1332 const SwAnchoredObject
* pAnchoredObj
= pContact
->GetAnchoredObj( pObj
);
1333 const SwFrameFormat
* pFormat
= pAnchoredObj
->GetFrameFormat();
1334 const SwFormatSurround
& rSurround
= pFormat
->GetSurround();
1335 if ( rSurround
.GetSurround() == css::text::WrapTextMode_THROUGH
)
1337 bObjInBackground
= true;
1342 if ( bObjInBackground
)
1344 const SwPageFrame
* pPageFrame
= GetLayout()->GetPageAtPos( rPt
);
1347 const SwContentFrame
* pContentFrame( pPageFrame
->ContainsContent() );
1348 while ( pContentFrame
)
1350 if ( pContentFrame
->UnionFrame().Contains( rPt
) )
1352 const SwTextFrame
* pTextFrame
= pContentFrame
->DynCastTextFrame();
1355 SwPosition
aPos(GetDoc()->GetNodes());
1356 Point
aTmpPt( rPt
);
1357 if (pTextFrame
->GetKeyCursorOfst(&aPos
, aTmpPt
))
1359 SwRect aCursorCharRect
;
1360 if (pTextFrame
->GetCharRect(aCursorCharRect
,
1363 if ( aCursorCharRect
.Overlaps( SwRect( pObj
->GetLastBoundRect() ) ) )
1377 pContentFrame
= pContentFrame
->GetNextContentFrame();
1382 // Don't select header / footer objects in body edition and vice-versa
1383 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
1384 if (pContact
&& !pContact
->ObjAnchoredAtPage() )
1386 const SwNode
& rAnchorNode
= pContact
->GetAnchorNode();
1387 bool bInHdrFtr
= GetDoc()->IsInHeaderFooter( rAnchorNode
);
1388 if (IsHeaderFooterEdit() != bInHdrFtr
)
1396 const SdrPage
* pPage
= rIDDMA
.GetDrawModel()->GetPage(0);
1397 for(auto it
= pPage
->begin() + pObj
->GetOrdNum() + 1; it
!= pPage
->end(); ++it
)
1399 SdrObject
*pCandidate
= it
->get();
1401 SwVirtFlyDrawObj
* pDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pCandidate
);
1402 if (pDrawObj
&& pDrawObj
->GetCurrentBoundRect().Contains(rPt
))
1410 // within table row, where image cropped by the fixed table row height,
1411 // click position must be in the cell, where the image anchored as character
1412 if ( bRet
&& pContact
&& pContact
->ObjAnchoredAsChar() )
1414 if ( const SwTableBox
*pBox
= pContact
->GetAnchorNode().GetTableBox() )
1416 SwIterator
<SwRowFrame
, SwFormat
> aIter( *pBox
->GetUpper()->GetFrameFormat() );
1417 bool bContainsClickPosition
= false;
1418 for (SwRowFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
1420 const SwRect
& rRect
= pFrame
->getFrameArea();
1421 // click inside the cell which contains the cropped image
1422 if ( rRect
.Contains( rPt
) )
1424 // click next to the right cell border
1425 if ( pSelectFrameInsteadOfCroppedImage
&&
1426 !rRect
.Contains( Point(rPt
.X() + 2 * nHitTol
, rPt
.Y()) ) )
1428 *pSelectFrameInsteadOfCroppedImage
= true;
1430 bContainsClickPosition
= true;
1433 else if ( pSelectFrameInsteadOfCroppedImage
&& (
1434 // Click outside of the right border
1435 rRect
.Contains( Point(rPt
.X() - 2 * nHitTol
, rPt
.Y()) ) ||
1436 // or handle the right border of bottom cells covered by the cropped
1437 // image instead putting the cursor inside the cell (see tdf#160842).
1438 // Click inside the same table, or outside its right border
1439 ( pFrame
->GetUpper() && pFrame
->GetUpper()->getFrameArea().Contains(
1440 Point(rPt
.X() - 2 * nHitTol
, rPt
.Y()) ) &&
1441 // and the click inside is next to the right table border
1442 !rRect
.Contains( Point(rPt
.X() + 2 * nHitTol
, rRect
.Bottom()) )
1445 *pSelectFrameInsteadOfCroppedImage
= true;
1446 bContainsClickPosition
= true;
1449 if ( !bContainsClickPosition
)
1460 * If an object was selected, we assume its upper-left corner
1461 * otherwise the middle of the current CharRects.
1462 * Does the object include a control or groups,
1463 * which comprise only controls
1465 static bool lcl_IsControlGroup( const SdrObject
*pObj
)
1468 if(dynamic_cast<const SdrUnoObj
*>( pObj
) != nullptr)
1470 else if( auto pObjGroup
= dynamic_cast<const SdrObjGroup
*>( pObj
) )
1473 const SdrObjList
*pLst
= pObjGroup
->GetSubList();
1474 for (const rtl::Reference
<SdrObject
>& pChildObj
: *pLst
)
1475 if( !::lcl_IsControlGroup( pChildObj
.get() ) )
1483 class MarkableObjectsOnly
: public svx::ISdrObjectFilter
1486 explicit MarkableObjectsOnly( SdrPageView
* i_pPV
)
1491 virtual bool includeObject( const SdrObject
& i_rObject
) const override
1493 return m_pPV
&& m_pPV
->GetView().IsObjMarkable( &i_rObject
, m_pPV
);
1501 const SdrObject
* SwFEShell::GetBestObject(bool bNext
, GotoObjFlags eType
, bool bFlat
,
1502 const svx::ISdrObjectFilter
* pFilter
,
1508 if( !Imp()->HasDrawView() )
1511 const SdrObject
*pBest
= nullptr,
1514 const tools::Long nTmp
= bNext
? LONG_MAX
: 0;
1515 Point
aBestPos( nTmp
, nTmp
);
1516 Point
aTopPos( nTmp
, nTmp
);
1519 bool bNoDraw((GotoObjFlags::DrawAny
& eType
) == GotoObjFlags::NONE
);
1520 bool bNoFly((GotoObjFlags::FlyAny
& eType
) == GotoObjFlags::NONE
);
1522 if( !bNoFly
&& bNoDraw
)
1524 SwFlyFrame
*pFly
= GetCurrFrame( false )->FindFlyFrame();
1526 pBest
= pFly
->GetVirtDrawObj();
1528 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1529 SdrPageView
* pPV
= Imp()->GetDrawView()->GetSdrPageView();
1531 MarkableObjectsOnly
aDefaultFilter( pPV
);
1533 pFilter
= &aDefaultFilter
;
1535 if( !pBest
|| rMrkList
.GetMarkCount() == 1 )
1537 // Determine starting point
1538 SdrObjList
* pList
= nullptr;
1539 if ( rMrkList
.GetMarkCount() )
1541 const SdrObject
* pStartObj
= rMrkList
.GetMark(0)->GetMarkedSdrObj();
1542 if( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>( pStartObj
) )
1543 aPos
= pVirtFlyDrawObj
->GetFlyFrame()->getFrameArea().Pos();
1545 aPos
= pStartObj
->GetSnapRect().TopLeft();
1547 // If an object inside a group is selected, we want to
1548 // iterate over the group members.
1549 if ( ! pStartObj
->GetUserCall() )
1550 pList
= pStartObj
->getParentSdrObjListFromSdrObject();
1554 // If no object is selected, we check if we just entered a group.
1555 // In this case we want to iterate over the group members.
1556 aPos
= GetCharRect().Center();
1557 const SdrObject
* pStartObj
= pPV
? pPV
->GetCurrentGroup() : nullptr;
1558 if ( dynamic_cast<const SdrObjGroup
*>( pStartObj
) )
1559 pList
= pStartObj
->GetSubList();
1565 // A No object has been selected and no group has been entered or
1566 // B An object has been selected and it is not inside a group
1567 pList
= getIDocumentDrawModelAccess().GetDrawModel()->GetPage( 0 );
1570 OSL_ENSURE( pList
, "No object list to iterate" );
1572 SdrObjListIter
aObjIter( pList
, bFlat
? SdrIterMode::Flat
: SdrIterMode::DeepNoGroups
);
1573 while ( aObjIter
.IsMore() )
1575 SdrObject
* pObj
= aObjIter
.Next();
1576 SwVirtFlyDrawObj
*pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
);
1577 if( ( bNoFly
&& pVirtO
) ||
1578 ( bNoDraw
&& !pVirtO
) ||
1579 // Ignore TextBoxes of draw shapes here, so that
1580 // SwFEShell::SelectObj() won't jump back on this list, meaning
1581 // we never jump to the next draw shape.
1582 (pVirtO
&& pVirtO
->IsTextBox()) ||
1583 ( eType
== GotoObjFlags::DrawSimple
&& lcl_IsControlGroup( pObj
) ) ||
1584 ( eType
== GotoObjFlags::DrawControl
&& !lcl_IsControlGroup( pObj
) ) ||
1585 !pFilter
->includeObject( *pObj
) )
1589 SwFlyFrame
*pFly
= pVirtO
->GetFlyFrame();
1590 if( GotoObjFlags::FlyAny
!= ( GotoObjFlags::FlyAny
& eType
) )
1594 case GotoObjFlags::FlyFrame
:
1595 if ( pFly
->Lower() && pFly
->Lower()->IsNoTextFrame() )
1598 case GotoObjFlags::FlyGrf
:
1599 if ( pFly
->Lower() &&
1600 (!pFly
->Lower()->IsNoTextFrame() ||
1601 !static_cast<SwNoTextFrame
*>(pFly
->Lower())->GetNode()->GetGrfNode()))
1604 case GotoObjFlags::FlyOLE
:
1605 if ( pFly
->Lower() &&
1606 (!pFly
->Lower()->IsNoTextFrame() ||
1607 !static_cast<SwNoTextFrame
*>(pFly
->Lower())->GetNode()->GetOLENode()))
1613 aCurPos
= pFly
->getFrameArea().Pos();
1616 aCurPos
= pObj
->GetSnapRect().TopLeft();
1618 // Special case if another object is on same Y.
1619 if( aCurPos
!= aPos
&& // only when it is not me
1620 aCurPos
.getY() == aPos
.getY() && // Y positions equal
1621 (bNext
? (aCurPos
.getX() > aPos
.getX()) : // lies next to me
1622 (aCurPos
.getX() < aPos
.getX())) ) // " reverse
1624 aBestPos
= Point( nTmp
, nTmp
);
1625 SdrObjListIter
aTmpIter( pList
, bFlat
? SdrIterMode::Flat
: SdrIterMode::DeepNoGroups
);
1626 while ( aTmpIter
.IsMore() )
1628 SdrObject
* pTmpObj
= aTmpIter
.Next();
1629 pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pTmpObj
);
1630 if( ( bNoFly
&& pVirtO
) || ( bNoDraw
&& !pVirtO
) )
1634 aCurPos
= pVirtO
->GetFlyFrame()->getFrameArea().Pos();
1637 aCurPos
= pTmpObj
->GetCurrentBoundRect().TopLeft();
1639 if( aCurPos
!= aPos
&& aCurPos
.Y() == aPos
.Y() &&
1640 (bNext
? (aCurPos
.getX() > aPos
.getX()) : // lies next to me
1641 (aCurPos
.getX() < aPos
.getX())) && // " reverse
1642 (bNext
? (aCurPos
.getX() < aBestPos
.getX()) : // better as best
1643 (aCurPos
.getX() > aBestPos
.getX())) ) // " reverse
1653 (bNext
? (aPos
.getY() < aCurPos
.getY()) : // only below me
1654 (aPos
.getY() > aCurPos
.getY())) && // " reverse
1655 (bNext
? (aBestPos
.getY() > aCurPos
.getY()) : // closer below
1656 (aBestPos
.getY() < aCurPos
.getY()))
1658 (aBestPos
.getY() == aCurPos
.getY() &&
1659 (bNext
? (aBestPos
.getX() > aCurPos
.getX()) : // further left
1660 (aBestPos
.getX() < aCurPos
.getX())))) // " reverse
1667 if( (bNext
? (aTopPos
.getY() > aCurPos
.getY()) : // higher as best
1668 (aTopPos
.getY() < aCurPos
.getY())) || // " reverse
1669 (aTopPos
.getY() == aCurPos
.getY() &&
1670 (bNext
? (aTopPos
.getX() > aCurPos
.getX()) : // further left
1671 (aTopPos
.getX() < aCurPos
.getX())))) // " reverse
1677 // unfortunately nothing found
1678 if( bNext
? (aBestPos
.getX() == LONG_MAX
) : (aBestPos
.getX() == 0) )
1681 if (pbWrapped
&& pBest
)
1689 bool SwFEShell::GotoObj( bool bNext
, GotoObjFlags eType
)
1691 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty
);
1693 bool bWrapped(false);
1694 const SdrObject
* pBest
= GetBestObject(bNext
, eType
, true, nullptr, &bWrapped
);
1698 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound
);
1702 const SwVirtFlyDrawObj
*pVirtO
= dynamic_cast<const SwVirtFlyDrawObj
*>(pBest
);
1705 const SwRect
& rFrame
= pVirtO
->GetFlyFrame()->getFrameArea();
1706 SelectObj( rFrame
.Pos(), 0, const_cast<SdrObject
*>(pBest
) );
1708 MakeVisible( rFrame
);
1712 SelectObj( Point(), 0, const_cast<SdrObject
*>(pBest
) );
1714 MakeVisible( SwRect(pBest
->GetCurrentBoundRect()) );
1719 SvxSearchDialogWrapper::SetSearchLabel(bNext
? SearchLabel::EndWrapped
:
1720 SearchLabel::StartWrapped
);
1725 bool SwFEShell::BeginCreate( SdrObjKind eSdrObjectKind
, const Point
&rPos
)
1729 if ( !Imp()->HasDrawView() )
1730 Imp()->MakeDrawView();
1732 if ( GetPageNumber( rPos
) )
1734 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind
);
1735 if ( eSdrObjectKind
== SdrObjKind::Caption
)
1736 bRet
= Imp()->GetDrawView()->BegCreateCaptionObj(
1737 rPos
, Size( lMinBorder
- MINFLY
, lMinBorder
- MINFLY
),
1740 bRet
= Imp()->GetDrawView()->BegCreateObj( rPos
, GetOut() );
1744 ::FrameNotify( this, FLY_DRAG_START
);
1749 bool SwFEShell::BeginCreate( SdrObjKind eSdrObjectKind
, SdrInventor eObjInventor
,
1754 if ( !Imp()->HasDrawView() )
1755 Imp()->MakeDrawView();
1757 if ( GetPageNumber( rPos
) )
1759 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind
, eObjInventor
);
1760 bRet
= Imp()->GetDrawView()->BegCreateObj( rPos
, GetOut() );
1763 ::FrameNotify( this, FLY_DRAG_START
);
1767 void SwFEShell::MoveCreate( const Point
&rPos
)
1769 OSL_ENSURE( Imp()->HasDrawView(), "MoveCreate without DrawView?" );
1770 if ( GetPageNumber( rPos
) )
1773 Imp()->GetDrawView()->MovCreateObj( rPos
);
1774 ::FrameNotify( this );
1778 bool SwFEShell::EndCreate( SdrCreateCmd eSdrCreateCmd
)
1780 // To assure undo-object from the DrawEngine is not stored,
1781 // (we create our own undo-object!), temporarily switch-off Undo
1782 OSL_ENSURE( Imp()->HasDrawView(), "EndCreate without DrawView?" );
1783 if( !Imp()->GetDrawView()->IsGroupEntered() )
1785 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
1787 bool bCreate
= Imp()->GetDrawView()->EndCreateObj( eSdrCreateCmd
);
1788 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
1792 ::FrameNotify( this, FLY_DRAG_END
);
1796 if ( eSdrCreateCmd
== SdrCreateCmd::NextPoint
)
1798 ::FrameNotify( this );
1801 return ImpEndCreate();
1804 bool SwFEShell::ImpEndCreate()
1806 if (Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() == 0)
1809 SdrObject
& rSdrObj
= *Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
1811 if( rSdrObj
.GetSnapRect().IsEmpty() )
1813 // preferably we forget the object, only gives problems
1814 Imp()->GetDrawView()->DeleteMarked();
1815 Imp()->GetDrawView()->UnmarkAll();
1816 ::FrameNotify( this, FLY_DRAG_END
);
1820 if( rSdrObj
.getParentSdrObjectFromSdrObject() )
1822 Point
aTmpPos( rSdrObj
.GetSnapRect().TopLeft() );
1823 Point
aNewAnchor( rSdrObj
.getParentSdrObjectFromSdrObject()->GetAnchorPos() );
1824 // OD 2004-04-05 #i26791# - direct object positioning for group members
1825 rSdrObj
.NbcSetRelativePos( aTmpPos
- aNewAnchor
);
1826 rSdrObj
.NbcSetAnchorPos( aNewAnchor
);
1827 ::FrameNotify( this );
1831 LockPaint(LockPaintReason::EndSdrCreate
);
1834 Imp()->GetDrawView()->UnmarkAll();
1836 const tools::Rectangle
&rBound
= rSdrObj
.GetSnapRect();
1837 Point
aPt( rBound
.TopRight() );
1839 // default for controls character bound, otherwise paragraph bound.
1840 SwFormatAnchor aAnch
;
1841 const SwFrame
*pAnch
= nullptr;
1842 bool bCharBound
= false;
1843 if( dynamic_cast<const SdrUnoObj
*>( &rSdrObj
) != nullptr )
1845 SwPosition
aPos( GetDoc()->GetNodes() );
1846 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
1847 Point
aPoint( aPt
.getX(), aPt
.getY() + rBound
.GetHeight()/2 );
1848 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPoint
, &aState
);
1850 // characterbinding not allowed in readonly-content
1851 if( !aPos
.GetNode().IsProtect() )
1853 std::pair
<Point
, bool> const tmp(aPoint
, true);
1854 pAnch
= aPos
.GetNode().GetContentNode()->getLayoutFrame(GetLayout(), &aPos
, &tmp
);
1856 pAnch
->GetCharRect( aTmp
, aPos
);
1858 // The crsr should not be too far away
1860 constexpr tools::Long constTwips_1cm
= o3tl::toTwips(1, o3tl::Length::cm
);
1861 tools::Rectangle
aRect( aTmp
.SVRect() );
1862 // Extend by 1 cm in each direction
1863 aRect
.AdjustLeft(-constTwips_1cm
);
1864 aRect
.AdjustTop(-constTwips_1cm
);
1865 aRect
.AdjustRight(constTwips_1cm
);
1866 aRect
.AdjustBottom(constTwips_1cm
);
1868 if( !aRect
.Overlaps( rBound
) && !::GetHtmlMode( GetDoc()->GetDocShell() ))
1871 // anchor in header/footer also not allowed.
1873 bCharBound
= !GetDoc()->IsInHeaderFooter( aPos
.GetNode() );
1877 aAnch
.SetType( RndStdIds::FLY_AS_CHAR
);
1878 aAnch
.SetAnchor( &aPos
);
1885 // allow native drawing objects in header/footer.
1886 // Thus, set <bBodyOnly> to <false> for these objects using value
1887 // of <nIdent> - value <0xFFFF> indicates control objects, which aren't
1888 // allowed in header/footer.
1889 //bool bBodyOnly = OBJ_NONE != nIdent;
1890 bool bBodyOnly
= SdrInventor::Default
!= rSdrObj
.GetObjInventor();
1891 bool bAtPage
= false;
1892 const SwFrame
* pPage
= nullptr;
1893 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
1894 Point
aPoint( aPt
);
1895 SwPosition
aPos( GetDoc()->GetNodes() );
1896 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPoint
, &aState
);
1898 // do not set in ReadnOnly-content
1899 if (aPos
.GetNode().IsProtect())
1901 // then only page bound. Or should we
1902 // search the next not-readonly position?
1906 SwContentNode
* pCNode
= aPos
.GetNode().GetContentNode();
1907 std::pair
<Point
, bool> const tmp(aPoint
, false);
1908 pAnch
= pCNode
? pCNode
->getLayoutFrame(GetLayout(), nullptr, &tmp
) : nullptr;
1911 // Hidden content. Anchor to the page instead
1917 const SwFlyFrame
*pTmp
= pAnch
->FindFlyFrame();
1920 const SwFrame
* pTmpFrame
= pAnch
;
1921 SwRect
aBound( rBound
);
1924 if( pTmp
->getFrameArea().Contains( aBound
) )
1926 if( !bBodyOnly
|| !pTmp
->FindFooterOrHeader() )
1930 pTmp
= pTmp
->GetAnchorFrame()
1931 ? pTmp
->GetAnchorFrame()->FindFlyFrame()
1938 pPage
= pAnch
->FindPageFrame();
1940 // Always via FindAnchor, to assure the frame will be bound
1941 // to the previous. With GetCrsOfst we can also reach the next. THIS IS WRONG.
1942 pAnch
= ::FindAnchor( pPage
, aPt
, bBodyOnly
);
1943 if (pAnch
->IsTextFrame())
1945 std::pair
<SwTextNode
const*, sal_Int32
> const pos(
1946 static_cast<SwTextFrame
const*>(pAnch
)->MapViewToModel(TextFrameIndex(0)));
1947 aPos
.Assign( *pos
.first
);
1951 aPos
.Assign( *static_cast<const SwNoTextFrame
*>(pAnch
)->GetNode() );
1954 // do not set in ReadnOnly-content
1955 if( aPos
.GetNode().IsProtect() )
1956 // then only page bound. Or should we
1957 // search the next not-readonly position?
1961 aAnch
.SetType( RndStdIds::FLY_AT_PARA
);
1962 aAnch
.SetAnchor( &aPos
);
1968 pPage
= pAnch
? pAnch
->FindPageFrame() : GetLayout()->GetPageAtPos(aPoint
);
1970 aAnch
.SetType( RndStdIds::FLY_AT_PAGE
);
1971 aAnch
.SetPageNum( pPage
->GetPhyPageNum() );
1972 pAnch
= pPage
; // page becomes an anchor
1976 SfxItemSetFixed
<RES_FRM_SIZE
, RES_FRM_SIZE
,
1977 RES_SURROUND
, RES_ANCHOR
> aSet( GetDoc()->GetAttrPool() );
1980 // OD 2004-03-30 #i26791# - determine relative object position
1982 SwTwips nYOffset
= rBound
.Top() - pAnch
->getFrameArea().Top();
1984 if( pAnch
->IsVertical() )
1986 nXOffset
= nYOffset
;
1987 nYOffset
= pAnch
->getFrameArea().Left()+pAnch
->getFrameArea().Width()-rBound
.Right();
1989 else if( pAnch
->IsRightToLeft() )
1990 nXOffset
= pAnch
->getFrameArea().Left()+pAnch
->getFrameArea().Width()-rBound
.Right();
1992 nXOffset
= rBound
.Left() - pAnch
->getFrameArea().Left();
1993 if (pAnch
->IsTextFrame())
1995 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnch
);
1996 if (pTmp
->IsFollow())
1999 pTmp
= pTmp
->FindMaster();
2000 OSL_ENSURE(pTmp
, "Where's my Master?");
2001 // OD 2004-03-30 #i26791# - correction: add frame area height
2002 // of master frames.
2003 nYOffset
+= pTmp
->IsVertical() ?
2004 pTmp
->getFrameArea().Width() : pTmp
->getFrameArea().Height();
2005 } while (pTmp
->IsFollow());
2008 nYOffset
-= pTmp
->GetBaseVertOffsetForFly(false);
2012 if (SdrInventor::Default
== rSdrObj
.GetObjInventor() && rSdrObj
.GetObjIdentifier() == SdrObjKind::NewFrame
)
2014 // For OBJ_NONE a fly is inserted.
2015 const tools::Long nWidth
= rBound
.Right() - rBound
.Left();
2016 const tools::Long nHeight
= rBound
.Bottom() - rBound
.Top();
2017 aSet
.Put( SwFormatFrameSize( SwFrameSize::Minimum
, std::max( nWidth
, tools::Long(MINFLY
) ),
2018 std::max( nHeight
, tools::Long(MINFLY
) )));
2020 SwFormatHoriOrient
aHori( nXOffset
, text::HoriOrientation::NONE
, text::RelOrientation::FRAME
);
2021 SwFormatVertOrient
aVert( nYOffset
, text::VertOrientation::NONE
, text::RelOrientation::FRAME
);
2022 aSet
.Put( SwFormatSurround( css::text::WrapTextMode_PARALLEL
) );
2026 // Quickly store the square
2027 const SwRect
aFlyRect( rBound
);
2029 // Throw away generated object, now the fly can nicely
2030 // via the available SS be generated.
2031 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); // see above
2032 // #i52858# - method name changed
2033 SdrPage
*pPg
= getIDocumentDrawModelAccess().GetOrCreateDrawModel()->GetPage( 0 );
2036 SdrModel
* pTmpSdrModel
= getIDocumentDrawModelAccess().GetDrawModel();
2037 auto pNewPage
= pTmpSdrModel
->AllocPage( false );
2038 pTmpSdrModel
->InsertPage( pNewPage
.get() );
2039 pPg
= pNewPage
.get();
2041 pPg
->RecalcObjOrdNums();
2042 pPg
->RemoveObject( rSdrObj
.GetOrdNumDirect() );
2043 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
2045 SwFlyFrame
* pFlyFrame
;
2046 if( NewFlyFrame( aSet
, true ) &&
2047 ::GetHtmlMode( GetDoc()->GetDocShell() ) &&
2048 nullptr != ( pFlyFrame
= GetSelectedFlyFrame() ))
2050 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_HORI_ORIENT
> aHtmlSet( GetDoc()->GetAttrPool() );
2051 // horizontal orientation:
2052 const bool bLeftFrame
= aFlyRect
.Left() <
2053 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Left(),
2054 bLeftPrt
= aFlyRect
.Left() + aFlyRect
.Width() <
2055 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Width()/2;
2056 if( bLeftFrame
|| bLeftPrt
)
2058 aHori
.SetHoriOrient( text::HoriOrientation::LEFT
);
2059 aHori
.SetRelationOrient( bLeftFrame
? text::RelOrientation::FRAME
: text::RelOrientation::PRINT_AREA
);
2063 const bool bRightFrame
= aFlyRect
.Left() >
2064 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Width();
2065 aHori
.SetHoriOrient( text::HoriOrientation::RIGHT
);
2066 aHori
.SetRelationOrient( bRightFrame
? text::RelOrientation::FRAME
: text::RelOrientation::PRINT_AREA
);
2068 aHtmlSet
.Put( aHori
);
2069 aVert
.SetVertOrient( text::VertOrientation::TOP
);
2070 aVert
.SetRelationOrient( text::RelOrientation::PRINT_AREA
);
2071 aHtmlSet
.Put( aVert
);
2073 GetDoc()->SetAttr( aHtmlSet
, *pFlyFrame
->GetFormat() );
2078 if (rSdrObj
.GetName().isEmpty())
2080 bool bRestore
= GetDoc()->GetIDocumentUndoRedo().DoesDrawUndo();
2081 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
2082 rSdrObj
.MakeNameUnique();
2083 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(bRestore
);
2087 aSet
.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH
) );
2088 // OD 2004-03-30 #i26791# - set horizontal position
2089 SwFormatHoriOrient
aHori( nXOffset
, text::HoriOrientation::NONE
, text::RelOrientation::FRAME
);
2091 // OD 2004-03-30 #i26791# - set vertical position
2092 if( pAnch
->IsTextFrame() && static_cast<const SwTextFrame
*>(pAnch
)->IsFollow() )
2094 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnch
);
2096 pTmp
= pTmp
->FindMaster();
2097 assert(pTmp
&& "Where's my Master?");
2098 nYOffset
+= pTmp
->IsVertical() ?
2099 pTmp
->getFramePrintArea().Width() : pTmp
->getFramePrintArea().Height();
2100 } while ( pTmp
->IsFollow() );
2102 SwFormatVertOrient
aVert( nYOffset
, text::VertOrientation::NONE
, text::RelOrientation::FRAME
);
2104 SwDrawFrameFormat
* pFormat
= static_cast<SwDrawFrameFormat
*>(getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT
, &aSet
));
2105 // #i36010# - set layout direction of the position
2106 pFormat
->SetPositionLayoutDir(
2107 text::PositionLayoutDir::PositionInLayoutDirOfAnchor
);
2108 // #i44344#, #i44681# - positioning attributes already set
2109 pFormat
->PosAttrSet();
2110 pFormat
->SetFormatName(rSdrObj
.GetName());
2112 SwDrawContact
*pContact
= new SwDrawContact( pFormat
, &rSdrObj
);
2114 pContact
->MoveObjToVisibleLayer( &rSdrObj
);
2117 OSL_ENSURE( aAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
, "wrong AnchorType" );
2118 SwTextNode
*pNd
= aAnch
.GetAnchorNode()->GetTextNode();
2119 SwFormatFlyCnt
aFormat( pFormat
);
2120 pNd
->InsertItem(aFormat
,
2121 aAnch
.GetAnchorContentOffset(), 0 );
2122 SwFormatVertOrient
aVertical( pFormat
->GetVertOrient() );
2123 aVertical
.SetVertOrient( text::VertOrientation::LINE_CENTER
);
2124 pFormat
->SetFormatAttr( aVertical
);
2126 if( pAnch
->IsTextFrame() && static_cast<const SwTextFrame
*>(pAnch
)->IsFollow() )
2128 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnch
);
2130 pTmp
= pTmp
->FindMaster();
2131 assert(pTmp
&& "Where's my Master?");
2132 } while( pTmp
->IsFollow() );
2136 pContact
->ConnectToLayout();
2138 // mark object at frame the object is inserted at.
2140 SdrObject
* pMarkObj
= pContact
->GetDrawObjectByAnchorFrame( *pAnch
);
2143 Imp()->GetDrawView()->MarkObj( pMarkObj
, Imp()->GetPageView() );
2147 Imp()->GetDrawView()->MarkObj( &rSdrObj
, Imp()->GetPageView() );
2152 GetDoc()->getIDocumentState().SetModified();
2155 EndAllActionAndCall();
2160 void SwFEShell::BreakCreate()
2162 OSL_ENSURE( Imp()->HasDrawView(), "BreakCreate without DrawView?" );
2163 Imp()->GetDrawView()->BrkCreateObj();
2164 ::FrameNotify( this, FLY_DRAG_END
);
2167 bool SwFEShell::IsDrawCreate() const
2169 return Imp()->HasDrawView() && Imp()->GetDrawView()->IsCreateObj();
2172 bool SwFEShell::BeginMark( const Point
&rPos
)
2174 if ( !Imp()->HasDrawView() )
2175 Imp()->MakeDrawView();
2177 if ( GetPageNumber( rPos
) )
2179 SwDrawView
* pDView
= Imp()->GetDrawView();
2181 if (pDView
->HasMarkablePoints())
2182 return pDView
->BegMarkPoints( rPos
);
2185 pDView
->BegMarkObj( rPos
);
2193 void SwFEShell::MoveMark( const Point
&rPos
)
2195 OSL_ENSURE( Imp()->HasDrawView(), "MoveMark without DrawView?" );
2197 if ( GetPageNumber( rPos
) )
2200 SwDrawView
* pDView
= Imp()->GetDrawView();
2202 if (pDView
->IsInsObjPoint())
2203 pDView
->MovInsObjPoint( rPos
);
2204 else if (pDView
->IsMarkPoints())
2205 pDView
->MovMarkPoints( rPos
);
2207 pDView
->MovAction( rPos
);
2211 bool SwFEShell::EndMark()
2214 OSL_ENSURE( Imp()->HasDrawView(), "EndMark without DrawView?" );
2216 if (Imp()->GetDrawView()->IsMarkObj())
2218 bRet
= Imp()->GetDrawView()->EndMarkObj();
2222 bool bShowHdl
= false;
2223 SwDrawView
* pDView
= Imp()->GetDrawView();
2224 // frames are not selected this way, except when
2225 // it is only one frame
2226 SdrMarkList
&rMrkList
= const_cast<SdrMarkList
&>(pDView
->GetMarkedObjectList());
2227 SwFlyFrame
* pOldSelFly
= ::GetFlyFromMarked( &rMrkList
, this );
2229 if ( rMrkList
.GetMarkCount() > 1 )
2230 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2232 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2233 if( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) != nullptr )
2239 rMrkList
.DeleteMark( i
);
2240 --i
; // no exceptions
2246 pDView
->MarkListHasChanged();
2247 pDView
->AdjustMarkHdl();
2250 if ( rMrkList
.GetMarkCount() )
2251 ::lcl_GrabCursor(this, pOldSelFly
);
2256 ::FrameNotify( this, FLY_DRAG_START
);
2260 if (Imp()->GetDrawView()->IsMarkPoints())
2261 bRet
= Imp()->GetDrawView()->EndMarkPoints();
2268 RndStdIds
SwFEShell::GetAnchorId() const
2270 RndStdIds nRet
= RndStdIds(SHRT_MAX
);
2271 if ( Imp()->HasDrawView() )
2273 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2274 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2276 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2277 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) != nullptr )
2279 nRet
= RndStdIds::UNKNOWN
;
2282 if (SwDrawContact
* pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
)))
2284 RndStdIds nId
= pContact
->GetFormat()->GetAnchor().GetAnchorId();
2285 if (nRet
== RndStdIds(SHRT_MAX
))
2287 else if (nRet
!= nId
)
2289 nRet
= RndStdIds::UNKNOWN
;
2295 if ( nRet
== RndStdIds(SHRT_MAX
) )
2296 nRet
= RndStdIds::UNKNOWN
;
2300 void SwFEShell::ChgAnchor( RndStdIds eAnchorId
, bool bSameOnly
, bool bPosCorr
)
2302 OSL_ENSURE( Imp()->HasDrawView(), "ChgAnchor without DrawView?" );
2303 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2304 if( rMrkList
.GetMarkCount() &&
2305 !rMrkList
.GetMark( 0 )->GetMarkedSdrObj()->getParentSdrObjectFromSdrObject() )
2309 if( GetDoc()->ChgAnchor( rMrkList
, eAnchorId
, bSameOnly
, bPosCorr
))
2310 Imp()->GetDrawView()->UnmarkAll();
2314 ::FrameNotify( this );
2318 void SwFEShell::DelSelectedObj()
2320 OSL_ENSURE( Imp()->HasDrawView(), "DelSelectedObj(), no DrawView available" );
2321 if ( Imp()->HasDrawView() )
2324 Imp()->GetDrawView()->DeleteMarked();
2326 ::FrameNotify( this, FLY_DRAG_END
);
2330 // For the statusline to request the current conditions
2331 Size
SwFEShell::GetObjSize() const
2333 tools::Rectangle aRect
;
2334 if ( Imp()->HasDrawView() )
2336 if ( Imp()->GetDrawView()->IsAction() )
2337 Imp()->GetDrawView()->TakeActionRect( aRect
);
2339 aRect
= Imp()->GetDrawView()->GetAllMarkedRect();
2341 return aRect
.GetSize();
2344 Point
SwFEShell::GetAnchorObjDiff() const
2346 const SdrView
*pView
= Imp()->GetDrawView();
2347 assert(pView
&& "GetAnchorObjDiff without DrawView?");
2349 tools::Rectangle aRect
;
2350 if ( Imp()->GetDrawView()->IsAction() )
2351 Imp()->GetDrawView()->TakeActionRect( aRect
);
2353 aRect
= Imp()->GetDrawView()->GetAllMarkedRect();
2355 Point
aRet( aRect
.TopLeft() );
2357 if ( IsFrameSelected() )
2359 SwFlyFrame
*pFly
= GetSelectedFlyFrame();
2360 aRet
-= pFly
->GetAnchorFrame()->getFrameArea().Pos();
2364 const SdrObject
*pObj
= pView
->GetMarkedObjectList().GetMarkCount() == 1 ?
2365 pView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj() : nullptr;
2367 aRet
-= pObj
->GetAnchorPos();
2373 Point
SwFEShell::GetObjAbsPos() const
2375 OSL_ENSURE( Imp()->GetDrawView(), "GetObjAbsPos() without DrawView?" );
2376 return Imp()->GetDrawView()->GetDragStat().GetActionRect().TopLeft();
2379 bool SwFEShell::IsGroupSelected(bool bAllowDiagams
)
2381 if ( IsObjSelected() )
2383 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2384 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2386 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2387 // consider 'virtual' drawing objects.
2388 // Thus, use corresponding method instead of checking type.
2389 if ( pObj
->IsGroupObject() &&
2390 // --> #i38505# No ungroup allowed for 3d objects
2391 !pObj
->Is3DObj() && GetUserCall(pObj
) &&
2392 RndStdIds::FLY_AS_CHAR
!= static_cast<SwDrawContact
*>(GetUserCall(pObj
))->
2393 GetFormat()->GetAnchor().GetAnchorId() )
2397 // Don't allow enter Diagrams
2398 if(pObj
->isDiagram())
2413 bool HasSuitableGroupingAnchor(const SdrObject
* pObj
)
2415 bool bSuitable
= true;
2416 SwFrameFormat
* pFrameFormat(::FindFrameFormat(const_cast<SdrObject
*>(pObj
)));
2419 OSL_FAIL( "<HasSuitableGroupingAnchor> - missing frame format" );
2422 else if (RndStdIds::FLY_AS_CHAR
== pFrameFormat
->GetAnchor().GetAnchorId())
2430 // Change return type.
2431 // Adjustments for drawing objects in header/footer:
2432 // allow group, only if all selected objects are in the same header/footer
2433 // or not in header/footer.
2434 bool SwFEShell::IsGroupAllowed() const
2436 bool bIsGroupAllowed
= false;
2437 if ( IsObjSelected() > 1 )
2439 bIsGroupAllowed
= true;
2440 const SdrObject
* pUpGroup
= nullptr;
2441 const SwFrame
* pHeaderFooterFrame
= nullptr;
2442 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2443 for ( size_t i
= 0; bIsGroupAllowed
&& i
< rMrkList
.GetMarkCount(); ++i
)
2445 const SdrObject
* pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2447 bIsGroupAllowed
= pObj
->getParentSdrObjectFromSdrObject() == pUpGroup
;
2449 pUpGroup
= pObj
->getParentSdrObjectFromSdrObject();
2451 if ( bIsGroupAllowed
)
2452 bIsGroupAllowed
= HasSuitableGroupingAnchor(pObj
);
2454 // check, if all selected objects are in the
2455 // same header/footer or not in header/footer.
2456 if ( bIsGroupAllowed
)
2458 const SwFrame
* pAnchorFrame
= nullptr;
2459 if ( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) )
2461 const SwFlyFrame
* pFlyFrame
= pVirtFlyDrawObj
->GetFlyFrame();
2464 pAnchorFrame
= pFlyFrame
->GetAnchorFrame();
2469 SwDrawContact
* pDrawContact
= static_cast<SwDrawContact
*>(GetUserCall( pObj
));
2472 pAnchorFrame
= pDrawContact
->GetAnchorFrame( pObj
);
2480 ( pAnchorFrame
->FindFooterOrHeader() == pHeaderFooterFrame
);
2484 pHeaderFooterFrame
= pAnchorFrame
->FindFooterOrHeader();
2491 return bIsGroupAllowed
;
2494 bool SwFEShell::IsUnGroupAllowed() const
2496 bool bIsUnGroupAllowed
= false;
2498 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2499 for (size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2501 const SdrObject
* pObj
= rMrkList
.GetMark(i
)->GetMarkedSdrObj();
2502 bIsUnGroupAllowed
= HasSuitableGroupingAnchor(pObj
);
2503 if (!bIsUnGroupAllowed
)
2507 return bIsUnGroupAllowed
;
2510 // The group gets the anchor and the contactobject of the first in the selection
2511 void SwFEShell::GroupSelection()
2513 if ( IsGroupAllowed() )
2516 StartUndo( SwUndoId::START
);
2518 GetDoc()->GroupSelection( *Imp()->GetDrawView() );
2520 EndUndo( SwUndoId::END
);
2525 // The individual objects get a copy of the anchor and the contactobject of the group
2526 void SwFEShell::UnGroupSelection()
2528 if ( IsGroupSelected(true) )
2531 StartUndo( SwUndoId::START
);
2533 GetDoc()->UnGroupSelection( *Imp()->GetDrawView() );
2535 EndUndo( SwUndoId::END
);
2540 void SwFEShell::MirrorSelection( bool bHorizontal
)
2542 SdrView
*pView
= Imp()->GetDrawView();
2543 if ( IsObjSelected() && pView
->IsMirrorAllowed() )
2546 pView
->MirrorAllMarkedHorizontal();
2548 pView
->MirrorAllMarkedVertical();
2552 // jump to named frame (Graphic/OLE)
2554 bool SwFEShell::GotoFly( const OUString
& rName
, FlyCntType eType
, bool bSelFrame
)
2557 static SwNodeType
const aChkArr
[ 4 ] = {
2558 /* FLYCNTTYPE_ALL */ SwNodeType::NONE
,
2559 /* FLYCNTTYPE_FRM */ SwNodeType::Text
,
2560 /* FLYCNTTYPE_GRF */ SwNodeType::Grf
,
2561 /* FLYCNTTYPE_OLE */ SwNodeType::Ole
2564 const SwFlyFrameFormat
* pFlyFormat
= mxDoc
->FindFlyByName( rName
, aChkArr
[ eType
]);
2567 CurrShell
aCurr( this );
2569 SwFlyFrame
* pFrame
= SwIterator
<SwFlyFrame
,SwFormat
>( *pFlyFormat
).First();
2574 // first make visible, to get a11y events in proper order
2576 MakeVisible( pFrame
->getFrameArea() );
2577 SelectObj( pFrame
->getFrameArea().Pos(), 0, pFrame
->GetVirtDrawObj() );
2581 SwContentFrame
*pCFrame
= pFrame
->ContainsContent();
2585 SwPaM
* pCursor
= GetCursor();
2587 if (pCFrame
->IsTextFrame())
2589 *pCursor
->GetPoint() = static_cast<SwTextFrame
*>(pCFrame
)
2590 ->MapViewToModelPos(TextFrameIndex(0));
2594 assert(pCFrame
->IsNoTextFrame());
2595 SwContentNode
*const pCNode
= static_cast<SwNoTextFrame
*>(pCFrame
)->GetNode();
2597 pCursor
->GetPoint()->Assign(*pCNode
);
2600 SwRect
& rChrRect
= const_cast<SwRect
&>(GetCharRect());
2601 rChrRect
= pFrame
->getFramePrintArea();
2602 rChrRect
.Pos() += pFrame
->getFrameArea().Pos();
2603 GetCursorDocPos() = rChrRect
.Pos();
2612 size_t SwFEShell::GetFlyCount( FlyCntType eType
, bool bIgnoreTextBoxes
) const
2614 return GetDoc()->GetFlyCount(eType
, bIgnoreTextBoxes
);
2617 std::vector
<SwFrameFormat
const*> SwFEShell::GetFlyFrameFormats(
2618 FlyCntType
const eType
, bool const bIgnoreTextBoxes
)
2620 return GetDoc()->GetFlyFrameFormats(eType
, bIgnoreTextBoxes
);
2623 // show the current selected object
2624 void SwFEShell::MakeSelVisible()
2626 if ( Imp()->HasDrawView() &&
2627 Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2629 GetCurrFrame(); // just to trigger formatting in case the selected object is not formatted.
2630 MakeVisible( SwRect(Imp()->GetDrawView()->GetAllMarkedRect()) );
2633 SwCursorShell::MakeSelVisible();
2636 // how is the selected object protected?
2637 FlyProtectFlags
SwFEShell::IsSelObjProtected( FlyProtectFlags eType
) const
2639 FlyProtectFlags nChk
= FlyProtectFlags::NONE
;
2640 const bool bParent(eType
& FlyProtectFlags::Parent
);
2641 if( Imp()->HasDrawView() )
2643 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2644 for( size_t i
= rMrkList
.GetMarkCount(); i
; )
2646 SdrObject
*pObj
= rMrkList
.GetMark( --i
)->GetMarkedSdrObj();
2654 nChk
|= ( pObj
->IsMoveProtect() ? FlyProtectFlags::Pos
: FlyProtectFlags::NONE
) |
2655 ( pObj
->IsResizeProtect()? FlyProtectFlags::Size
: FlyProtectFlags::NONE
);
2657 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
2659 SwFlyFrame
*pFly
= pVirtO
->GetFlyFrame();
2660 if ( (FlyProtectFlags::Content
& eType
) && pFly
->GetFormat()->GetProtect().IsContentProtected() )
2661 nChk
|= FlyProtectFlags::Content
;
2663 if ( pFly
->Lower() && pFly
->Lower()->IsNoTextFrame() )
2665 SwOLENode
*pNd
= static_cast<SwNoTextFrame
*>(pFly
->Lower())->GetNode()->GetOLENode();
2666 uno::Reference
< embed::XEmbeddedObject
> xObj( pNd
? pNd
->GetOLEObj().GetOleRef() : nullptr );
2669 // TODO/LATER: use correct aspect
2670 const bool bNeverResize
= (embed::EmbedMisc::EMBED_NEVERRESIZE
& xObj
->getStatus( embed::Aspects::MSOLE_CONTENT
));
2671 if ( ( (FlyProtectFlags::Content
& eType
) || (FlyProtectFlags::Size
& eType
) ) && bNeverResize
)
2673 nChk
|= FlyProtectFlags::Size
;
2674 nChk
|= FlyProtectFlags::Fixed
;
2677 // set FlyProtectFlags::Pos if it is a Math object anchored 'as char' and baseline alignment is activated
2678 const bool bProtectMathPos
= SotExchange::IsMath( xObj
->getClassID() )
2679 && RndStdIds::FLY_AS_CHAR
== pFly
->GetFormat()->GetAnchor().GetAnchorId()
2680 && mxDoc
->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT
);
2681 if ((FlyProtectFlags::Pos
& eType
) && bProtectMathPos
)
2682 nChk
|= FlyProtectFlags::Pos
;
2690 const SwFrame
* pAnch
;
2691 if (SwVirtFlyDrawObj
* pVirtO
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
2692 pAnch
= pVirtO
->GetFlyFrame()->GetAnchorFrame();
2695 SwDrawContact
* pTmp
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
2696 pAnch
= pTmp
? pTmp
->GetAnchorFrame( pObj
) : nullptr;
2698 if( pAnch
&& pAnch
->IsProtected() )
2705 bool SwFEShell::GetObjAttr( SfxItemSet
&rSet
) const
2707 if ( !IsObjSelected() )
2710 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2711 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2713 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2714 SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
2715 OSL_ENSURE( pContact
, "<SwFEShell::GetObjAttr(..)> - missing <pContact>." );
2719 rSet
.MergeValues( pContact
->GetFormat()->GetAttrSet() );
2721 rSet
.Put( pContact
->GetFormat()->GetAttrSet() );
2727 void SwFEShell::SetObjAttr( const SfxItemSet
& rSet
)
2729 CurrShell
aCurr( this );
2731 if ( !rSet
.Count() )
2733 OSL_ENSURE( false, "SetObjAttr, empty set." );
2738 StartUndo( SwUndoId::INSATTR
);
2740 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2741 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2743 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2744 if (SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
)))
2745 GetDoc()->SetAttr( rSet
, *pContact
->GetFormat() );
2748 EndUndo( SwUndoId::INSATTR
);
2749 EndAllActionAndCall();
2750 GetDoc()->getIDocumentState().SetModified();
2753 bool SwFEShell::IsAlignPossible() const
2755 return Imp()->GetDrawView()->IsAlignPossible();
2758 void SwFEShell::CheckUnboundObjects()
2760 CurrShell
aCurr( this );
2762 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
2763 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
2765 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
2766 if ( !GetUserCall(pObj
) )
2768 const tools::Rectangle
&rBound
= pObj
->GetSnapRect();
2769 const Point
aPt( rBound
.TopLeft() );
2770 const SwFrame
*pPage
= GetLayout()->Lower();
2771 const SwFrame
*pLast
= pPage
;
2772 while ( pPage
&& !pPage
->getFrameArea().Contains( aPt
) )
2774 if ( aPt
.Y() > pPage
->getFrameArea().Bottom() )
2776 pPage
= pPage
->GetNext();
2780 OSL_ENSURE( pPage
, "Page not found." );
2782 SwFormatAnchor aAnch
;
2784 const SwContentFrame
*const pAnch
= ::FindAnchor(pPage
, aPt
, true);
2785 SwPosition
aPos( pAnch
->IsTextFrame()
2786 ? *static_cast<SwTextFrame
const*>(pAnch
)->GetTextNodeForParaProps()
2787 : *static_cast<SwNoTextFrame
const*>(pAnch
)->GetNode() );
2788 aAnch
.SetType( RndStdIds::FLY_AT_PARA
);
2789 aAnch
.SetAnchor( &aPos
);
2790 const_cast<SwRect
&>(GetCharRect()).Pos() = aPt
;
2793 // First the action here, to assure GetCharRect delivers current values.
2796 SfxItemSetFixed
<RES_FRM_SIZE
, RES_FRM_SIZE
,
2797 RES_SURROUND
, RES_ANCHOR
> aSet( GetAttrPool() );
2799 aSet
.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH
) );
2800 SwFrameFormat
* pFormat
= getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT
, &aSet
);
2802 SwDrawContact
*pContact
= new SwDrawContact(
2803 static_cast<SwDrawFrameFormat
*>(pFormat
), pObj
);
2806 pContact
->MoveObjToVisibleLayer( pObj
);
2807 pContact
->ConnectToLayout();
2814 void SwFEShell::SetCalcFieldValueHdl(Outliner
* pOutliner
)
2816 GetDoc()->SetCalcFieldValueHdl(pOutliner
);
2819 SwChainRet
SwFEShell::Chainable( SwRect
&rRect
, const SwFrameFormat
&rSource
,
2820 const Point
&rPt
) const
2824 // The source is not allowed to have a follow.
2825 const SwFormatChain
&rChain
= rSource
.GetChain();
2826 if ( rChain
.GetNext() )
2827 return SwChainRet::SOURCE_CHAINED
;
2829 SwChainRet nRet
= SwChainRet::NOT_FOUND
;
2830 if( Imp()->HasDrawView() )
2832 SdrPageView
* pPView
;
2833 SwDrawView
*pDView
= const_cast<SwDrawView
*>(Imp()->GetDrawView());
2834 const auto nOld
= pDView
->GetHitTolerancePixel();
2835 pDView
->SetHitTolerancePixel( 0 );
2836 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPView
, SdrSearchOptions::PICKMARKABLE
);
2837 SwVirtFlyDrawObj
* pDrawObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
);
2840 SwFlyFrame
*pFly
= pDrawObj
->GetFlyFrame();
2841 rRect
= pFly
->getFrameArea();
2843 // Target and source should not be equal and the list
2844 // should not be cyclic
2845 SwFrameFormat
*pFormat
= pFly
->GetFormat();
2846 nRet
= GetDoc()->Chainable(rSource
, *pFormat
);
2848 pDView
->SetHitTolerancePixel( nOld
);
2853 void SwFEShell::Chain( SwFrameFormat
&rSource
, const SwFrameFormat
&rDest
)
2855 GetDoc()->Chain(rSource
, rDest
);
2858 SwChainRet
SwFEShell::Chain( SwFrameFormat
&rSource
, const Point
&rPt
)
2861 SwChainRet nErr
= Chainable( aDummy
, rSource
, rPt
);
2862 if ( nErr
== SwChainRet::OK
)
2865 SdrPageView
* pPView
;
2866 SwDrawView
*pDView
= Imp()->GetDrawView();
2867 const auto nOld
= pDView
->GetHitTolerancePixel();
2868 pDView
->SetHitTolerancePixel( 0 );
2869 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPView
, SdrSearchOptions::PICKMARKABLE
);
2870 pDView
->SetHitTolerancePixel( nOld
);
2871 SwFlyFrame
*pFly
= static_cast<SwVirtFlyDrawObj
*>(pObj
)->GetFlyFrame();
2873 SwFlyFrameFormat
*pFormat
= pFly
->GetFormat();
2874 GetDoc()->Chain(rSource
, *pFormat
);
2881 void SwFEShell::Unchain( SwFrameFormat
&rFormat
)
2884 GetDoc()->Unchain(rFormat
);
2888 void SwFEShell::HideChainMarker()
2890 m_pChainFrom
.reset();
2894 void SwFEShell::SetChainMarker()
2896 bool bDelFrom
= true,
2898 if ( IsFrameSelected() )
2900 SwFlyFrame
*pFly
= GetSelectedFlyFrame();
2902 if ( pFly
->GetPrevLink() )
2905 const SwFrame
*pPre
= pFly
->GetPrevLink();
2907 Point
aStart( pPre
->getFrameArea().Right(), pPre
->getFrameArea().Bottom());
2908 Point
aEnd(pFly
->getFrameArea().Pos());
2913 new SdrDropMarkerOverlay( *GetDrawView(), aStart
, aEnd
));
2916 if ( pFly
->GetNextLink() )
2919 const SwFlyFrame
*pNxt
= pFly
->GetNextLink();
2921 Point
aStart( pFly
->getFrameArea().Right(), pFly
->getFrameArea().Bottom());
2922 Point
aEnd(pNxt
->getFrameArea().Pos());
2927 new SdrDropMarkerOverlay( *GetDrawView(), aStart
, aEnd
));
2934 m_pChainFrom
.reset();
2943 tools::Long
SwFEShell::GetSectionWidth( SwFormat
const & rFormat
) const
2945 SwFrame
*pFrame
= GetCurrFrame();
2946 // Is the cursor at this moment in a SectionFrame?
2947 if( pFrame
&& pFrame
->IsInSct() )
2949 SwSectionFrame
* pSect
= pFrame
->FindSctFrame();
2952 // Is it the right one?
2953 if( pSect
->KnowsFormat( rFormat
) )
2954 return pSect
->getFrameArea().Width();
2956 pSect
= pSect
->GetUpper()->FindSctFrame();
2960 SwIterator
<SwSectionFrame
,SwFormat
> aIter( rFormat
);
2961 for ( SwSectionFrame
* pSct
= aIter
.First(); pSct
; pSct
= aIter
.Next() )
2963 if( !pSct
->IsFollow() )
2965 return pSct
->getFrameArea().Width();
2971 void SwFEShell::CreateDefaultShape( SdrObjKind eSdrObjectKind
, const tools::Rectangle
& rRect
,
2974 SdrView
* pDrawView
= GetDrawView();
2975 SdrModel
& rDrawModel
= pDrawView
->GetModel();
2976 rtl::Reference
<SdrObject
> pObj
= SdrObjFactory::MakeNewObject(
2978 SdrInventor::Default
,
2983 tools::Rectangle
aRect(rRect
);
2984 if(SdrObjKind::CircleArc
== eSdrObjectKind
|| SdrObjKind::CircleCut
== eSdrObjectKind
)
2987 if(aRect
.GetWidth() > aRect
.GetHeight())
2989 aRect
= tools::Rectangle(
2990 Point(aRect
.Left() + ((aRect
.GetWidth() - aRect
.GetHeight()) / 2), aRect
.Top()),
2991 Size(aRect
.GetHeight(), aRect
.GetHeight()));
2995 aRect
= tools::Rectangle(
2996 Point(aRect
.Left(), aRect
.Top() + ((aRect
.GetHeight() - aRect
.GetWidth()) / 2)),
2997 Size(aRect
.GetWidth(), aRect
.GetWidth()));
3000 pObj
->SetLogicRect(aRect
);
3002 Point aStart
= aRect
.TopLeft();
3003 Point aEnd
= aRect
.BottomRight();
3005 if(dynamic_cast<const SdrCircObj
*>( pObj
.get()) != nullptr)
3007 SfxItemSet
aAttr(rDrawModel
.GetItemPool());
3008 aAttr
.Put(makeSdrCircStartAngleItem(9000_deg100
));
3009 aAttr
.Put(makeSdrCircEndAngleItem(0_deg100
));
3010 pObj
->SetMergedItemSet(aAttr
);
3012 else if(auto pPathObj
= dynamic_cast<SdrPathObj
*>( pObj
.get()))
3014 basegfx::B2DPolyPolygon aPoly
;
3016 switch(eSdrObjectKind
)
3018 case SdrObjKind::PathLine
:
3019 case SdrObjKind::PathFill
:
3021 basegfx::B2DPolygon aInnerPoly
;
3023 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Bottom()));
3025 const basegfx::B2DPoint
aCenterBottom(aRect
.Center().getX(), aRect
.Bottom());
3026 aInnerPoly
.appendBezierSegment(
3029 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Center().getY()));
3031 const basegfx::B2DPoint
aCenterTop(aRect
.Center().getX(), aRect
.Top());
3032 aInnerPoly
.appendBezierSegment(
3035 basegfx::B2DPoint(aRect
.Right(), aRect
.Top()));
3037 aInnerPoly
.setClosed(true);
3038 aPoly
.append(aInnerPoly
);
3041 case SdrObjKind::FreehandLine
:
3042 case SdrObjKind::FreehandFill
:
3044 basegfx::B2DPolygon aInnerPoly
;
3046 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Bottom()));
3048 aInnerPoly
.appendBezierSegment(
3049 basegfx::B2DPoint(aRect
.Left(), aRect
.Top()),
3050 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Top()),
3051 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Center().getY()));
3053 aInnerPoly
.appendBezierSegment(
3054 basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Bottom()),
3055 basegfx::B2DPoint(aRect
.Right(), aRect
.Bottom()),
3056 basegfx::B2DPoint(aRect
.Right(), aRect
.Top()));
3058 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Right(), aRect
.Bottom()));
3059 aInnerPoly
.setClosed(true);
3060 aPoly
.append(aInnerPoly
);
3063 case SdrObjKind::Polygon
:
3064 case SdrObjKind::PolyLine
:
3066 basegfx::B2DPolygon aInnerPoly
;
3067 sal_Int32
nWdt(aRect
.GetWidth());
3068 sal_Int32
nHgt(aRect
.GetHeight());
3070 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Bottom()));
3071 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 30) / 100, aRect
.Top() + (nHgt
* 70) / 100));
3072 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left(), aRect
.Top() + (nHgt
* 15) / 100));
3073 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 65) / 100, aRect
.Top()));
3074 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + nWdt
, aRect
.Top() + (nHgt
* 30) / 100));
3075 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 80) / 100, aRect
.Top() + (nHgt
* 50) / 100));
3076 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Left() + (nWdt
* 80) / 100, aRect
.Top() + (nHgt
* 75) / 100));
3077 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Bottom(), aRect
.Right()));
3079 if(SdrObjKind::PolyLine
== eSdrObjectKind
)
3081 aInnerPoly
.append(basegfx::B2DPoint(aRect
.Center().getX(), aRect
.Bottom()));
3085 aInnerPoly
.setClosed(true);
3088 aPoly
.append(aInnerPoly
);
3091 case SdrObjKind::Line
:
3093 sal_Int32
nYMiddle((aRect
.Top() + aRect
.Bottom()) / 2);
3094 basegfx::B2DPolygon aTempPoly
;
3095 aTempPoly
.append(basegfx::B2DPoint(aRect
.TopLeft().getX(), nYMiddle
));
3096 aTempPoly
.append(basegfx::B2DPoint(aRect
.BottomRight().getX(), nYMiddle
));
3097 aPoly
.append(aTempPoly
);
3099 SfxItemSet
aAttr(pObj
->getSdrModelFromSdrObject().GetItemPool());
3100 SetLineEnds(aAttr
, *pObj
, nSlotId
);
3101 pObj
->SetMergedItemSet(aAttr
);
3108 pPathObj
->SetPathPoly(aPoly
);
3110 else if(auto pMeasureObj
= dynamic_cast<SdrMeasureObj
*>( pObj
.get()))
3112 sal_Int32
nYMiddle((aRect
.Top() + aRect
.Bottom()) / 2);
3113 pMeasureObj
->SetPoint(Point(aStart
.X(), nYMiddle
), 0);
3114 pMeasureObj
->SetPoint(Point(aEnd
.X(), nYMiddle
), 1);
3116 SfxItemSet
aAttr(pObj
->getSdrModelFromSdrObject().GetItemPool());
3117 SetLineEnds(aAttr
, *pObj
, nSlotId
);
3118 pObj
->SetMergedItemSet(aAttr
);
3120 else if(auto pCaptionObj
= dynamic_cast<SdrCaptionObj
*>( pObj
.get()))
3122 bool bVerticalText
= ( SID_DRAW_TEXT_VERTICAL
== nSlotId
||
3123 SID_DRAW_CAPTION_VERTICAL
== nSlotId
);
3124 pCaptionObj
->SetVerticalWriting(bVerticalText
);
3127 SfxItemSet
aSet(pObj
->GetMergedItemSet());
3128 aSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER
));
3129 aSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT
));
3130 pObj
->SetMergedItemSet(aSet
);
3133 pCaptionObj
->SetLogicRect(aRect
);
3134 pCaptionObj
->SetTailPos(
3135 aRect
.TopLeft() - Point(aRect
.GetWidth() / 2, aRect
.GetHeight() / 2));
3137 else if(auto pText
= DynCastSdrTextObj( pObj
.get()))
3139 pText
->SetLogicRect(aRect
);
3141 bool bVertical
= (SID_DRAW_TEXT_VERTICAL
== nSlotId
);
3142 bool bMarquee
= (SID_DRAW_TEXT_MARQUEE
== nSlotId
);
3144 pText
->SetVerticalWriting(bVertical
);
3148 SfxItemSet
aSet(rDrawModel
.GetItemPool());
3149 aSet
.Put(makeSdrTextAutoGrowWidthItem(true));
3150 aSet
.Put(makeSdrTextAutoGrowHeightItem(false));
3151 aSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP
));
3152 aSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT
));
3153 pText
->SetMergedItemSet(aSet
);
3158 SfxItemSetFixed
<SDRATTR_MISC_FIRST
, SDRATTR_MISC_LAST
> aSet(rDrawModel
.GetItemPool());
3159 aSet
.Put( makeSdrTextAutoGrowWidthItem( false ) );
3160 aSet
.Put( makeSdrTextAutoGrowHeightItem( false ) );
3161 aSet
.Put( SdrTextAniKindItem( SdrTextAniKind::Slide
) );
3162 aSet
.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left
) );
3163 aSet
.Put( SdrTextAniCountItem( 1 ) );
3164 aSet
.Put( SdrTextAniAmountItem( static_cast<sal_Int16
>(GetWin()->PixelToLogic(Size(2,1)).Width())) );
3165 pObj
->SetMergedItemSetAndBroadcast(aSet
);
3168 SdrPageView
* pPageView
= pDrawView
->GetSdrPageView();
3169 SdrCreateView::SetupObjLayer(pPageView
, pDrawView
->GetActiveLayer(), pObj
.get());
3170 // switch undo off or this combined with ImpEndCreate will cause two undos
3171 // see comment made in SwFEShell::EndCreate (we create our own undo-object!)
3172 const bool bUndo(GetDoc()->GetIDocumentUndoRedo().DoesUndo());
3173 GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
3174 pDrawView
->InsertObjectAtView(pObj
.get(), *pPageView
);
3175 GetDoc()->GetIDocumentUndoRedo().DoUndo(bUndo
);
3180 /** SwFEShell::GetShapeBackground
3181 method determines background color of the page the selected drawing
3182 object is on and returns this color.
3183 If no color is found, because no drawing object is selected or ...,
3184 color COL_BLACK (default color on constructing object of class Color)
3187 @returns an object of class Color
3189 Color
SwFEShell::GetShapeBackground() const
3193 // check, if a draw view exists
3194 OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackground - no draw view!");
3195 if( Imp()->GetDrawView() )
3197 // determine list of selected objects
3198 const SdrMarkList
* pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
3199 // check, if exactly one object is selected.
3200 OSL_ENSURE( pMrkList
->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackground - no selected object!");
3201 if ( pMrkList
->GetMarkCount() == 1)
3203 // get selected object
3204 const SdrObject
*pSdrObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
3205 // check, if selected object is a shape (drawing object)
3206 OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj
) == nullptr, "wrong usage of SwFEShell::GetShapeBackground - selected object is not a drawing object!");
3207 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj
) == nullptr )
3209 if (SwDrawContact
* pDrawContact
= static_cast<SwDrawContact
*>(GetUserCall(pSdrObj
)))
3211 // determine page frame of the frame the shape is anchored.
3212 const SwFrame
* pAnchorFrame
= pDrawContact
->GetAnchorFrame(pSdrObj
);
3213 OSL_ENSURE(pAnchorFrame
, "inconsistent model - no anchor at shape!");
3216 const SwPageFrame
* pPageFrame
= pAnchorFrame
->FindPageFrame();
3217 OSL_ENSURE(pPageFrame
, "inconsistent model - no page!");
3220 aRetColor
= pPageFrame
->GetDrawBackgroundColor();
3231 /** Is default horizontal text direction for selected drawing object right-to-left
3232 Because drawing objects only painted for each page only, the default
3233 horizontal text direction of a drawing object is given by the corresponding
3236 @returns boolean, indicating, if the horizontal text direction of the
3237 page, the selected drawing object is on, is right-to-left.
3239 bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const
3241 // check, if a draw view exists
3242 OSL_ENSURE(Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackground - no draw view!");
3243 if (!Imp()->GetDrawView())
3246 // determine list of selected objects
3247 const SdrMarkList
& rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
3249 // check, if exactly one object is selected.
3250 OSL_ENSURE(rMrkList
.GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackground - no selected object!");
3251 if (rMrkList
.GetMarkCount() != 1)
3254 // get selected object
3255 const SdrObject
*pSdrObj
= rMrkList
.GetMark(0)->GetMarkedSdrObj();
3257 // check, if selected object is a shape (drawing object)
3258 OSL_ENSURE(dynamic_cast<const SwVirtFlyDrawObj
*>(pSdrObj
) == nullptr, "wrong usage of SwFEShell::GetShapeBackground - selected object is not a drawing object!");
3259 if (dynamic_cast<const SwVirtFlyDrawObj
*>(pSdrObj
) != nullptr)
3262 // determine page frame of the frame the shape is anchored.
3263 const SwContact
* pContact
= GetUserCall(pSdrObj
);
3264 OSL_ENSURE(pContact
, "<SwFEShell::IsShapeDefaultHoriTextDirR2L(..)> - missing contact!");
3268 const SwFrame
* pAnchorFrame
= static_cast<const SwDrawContact
*>(pContact
)->GetAnchorFrame(pSdrObj
);
3269 OSL_ENSURE(pAnchorFrame
, "inconsistent model - no anchor at shape!");
3273 const SwPageFrame
* pPageFrame
= pAnchorFrame
->FindPageFrame();
3274 OSL_ENSURE(pPageFrame
, "inconsistent model - no page!");
3278 return pPageFrame
->IsRightToLeft();
3281 Point
SwFEShell::GetRelativePagePosition(const Point
& rDocPos
)
3284 const SwFrame
*pPage
= GetLayout()->Lower();
3285 while ( pPage
&& !pPage
->getFrameArea().Contains( rDocPos
) )
3287 pPage
= pPage
->GetNext();
3291 aRet
= rDocPos
- pPage
->getFrameArea().TopLeft();
3296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */