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 <o3tl/any.hxx>
22 #include <svl/itemiter.hxx>
23 #include <vcl/imapobj.hxx>
24 #include <editeng/protitem.hxx>
25 #include <svx/svdogrp.hxx>
26 #include <svx/svdouno.hxx>
27 #include <tools/globname.hxx>
28 #include <sot/exchange.hxx>
29 #include <com/sun/star/form/FormButtonType.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/embed/XEmbeddedObject.hpp>
32 #include <comphelper/types.hxx>
33 #include <osl/diagnose.h>
34 #include <comphelper/scopeguard.hxx>
35 #include <fmtanchr.hxx>
36 #include <fmtcntnt.hxx>
37 #include <fmtornt.hxx>
39 #include <fmtfsize.hxx>
41 #include <rootfrm.hxx>
42 #include <pagefrm.hxx>
45 #include <viewimp.hxx>
48 #include <IDocumentDrawModelAccess.hxx>
49 #include <IDocumentUndoRedo.hxx>
50 #include <IDocumentState.hxx>
51 #include <IDocumentLayoutAccess.hxx>
52 #include <IDocumentRedlineAccess.hxx>
53 #include <redline.hxx>
55 #include <dflyobj.hxx>
56 #include <dcontact.hxx>
60 #include <swtable.hxx>
62 #include <flyfrms.hxx>
66 #include <txatbase.hxx>
68 #include <notxtfrm.hxx>
69 #include <HandleAnchorNodeChg.hxx>
71 #include <fmtsrnd.hxx>
74 #include <fmtcnct.hxx>
75 #include <frameformats.hxx>
76 #include <textboxhelper.hxx>
79 using namespace ::com::sun::star
;
81 // Based on the request, changes to the specific layouts will be made, to
83 static bool lcl_SetNewFlyPos( const SwNode
& rNode
, SwFormatAnchor
& rAnchor
,
87 const SwStartNode
* pStNode
= rNode
.FindFlyStartNode();
90 SwPosition
aPos( *pStNode
);
91 rAnchor
.SetAnchor( &aPos
);
96 const SwContentNode
*pCntNd
= rNode
.GetContentNode();
97 std::pair
<Point
, bool> const tmp(rPt
, false);
98 const SwContentFrame
* pCFrame
= pCntNd
? pCntNd
->getLayoutFrame(
99 pCntNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
100 nullptr, &tmp
) : nullptr;
101 const SwPageFrame
*pPg
= pCFrame
? pCFrame
->FindPageFrame() : nullptr;
103 rAnchor
.SetPageNum( pPg
? pPg
->GetPhyPageNum() : 1 );
104 rAnchor
.SetType( RndStdIds::FLY_AT_PAGE
);
109 static bool lcl_FindAnchorPos(
112 const SwFrame
& rFrame
,
116 SwFormatAnchor
aNewAnch( rSet
.Get( RES_ANCHOR
) );
117 RndStdIds nNew
= aNewAnch
.GetAnchorId();
118 const SwFrame
*pNewAnch
;
120 //determine new anchor
121 Point
aTmpPnt( rPt
);
124 case RndStdIds::FLY_AS_CHAR
: // also include this?
125 case RndStdIds::FLY_AT_PARA
:
126 case RndStdIds::FLY_AT_CHAR
: // LAYER_IMPL
128 // starting from the upper-left corner of the Fly,
129 // search nearest ContentFrame
130 const SwFrame
* pFrame
= rFrame
.IsFlyFrame() ? static_cast<const SwFlyFrame
&>(rFrame
).GetAnchorFrame()
132 pNewAnch
= ::FindAnchor( pFrame
, aTmpPnt
);
133 if( pNewAnch
->IsProtected() )
138 SwPosition
aPos( pNewAnch
->IsTextFrame()
139 ? *static_cast<SwTextFrame
const*>(pNewAnch
)->GetTextNodeForParaProps()
140 : *static_cast<const SwNoTextFrame
*>(pNewAnch
)->GetNode() );
141 if ((RndStdIds::FLY_AT_CHAR
== nNew
) || (RndStdIds::FLY_AS_CHAR
== nNew
))
143 // textnode should be found, as only in those
144 // a content bound frame can be anchored
145 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
146 aTmpPnt
.setX(aTmpPnt
.getX() - 1); // do not land in the fly!
147 if( !pNewAnch
->GetModelPositionForViewPoint( &aPos
, aTmpPnt
, &aState
) )
149 assert(pNewAnch
->IsTextFrame()); // because AT_CHAR/AS_CHAR
150 SwTextFrame
const*const pTextFrame(
151 static_cast<SwTextFrame
const*>(pNewAnch
));
152 if( pNewAnch
->getFrameArea().Bottom() < aTmpPnt
.Y() )
154 aPos
= pTextFrame
->MapViewToModelPos(TextFrameIndex(0));
158 aPos
= pTextFrame
->MapViewToModelPos(
159 TextFrameIndex(pTextFrame
->GetText().getLength()));
164 if ( SwCursorShell::PosInsideInputField( aPos
) )
166 aPos
.SetContent( SwCursorShell::StartOfInputFieldAtPos( aPos
) );
170 aNewAnch
.SetAnchor( &aPos
);
174 case RndStdIds::FLY_AT_FLY
: // LAYER_IMPL
176 // starting from the upper-left corner of the Fly
177 // search nearest SwFlyFrame
178 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
179 SwPosition
aPos( rDoc
.GetNodes() );
180 aTmpPnt
.setX(aTmpPnt
.getX() - 1); // do not land in the fly!
181 rDoc
.getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( &aPos
, aTmpPnt
, &aState
);
182 pNewAnch
= ::FindAnchor(
183 aPos
.GetNode().GetContentNode()->getLayoutFrame(rFrame
.getRootFrame(), nullptr, nullptr),
184 aTmpPnt
)->FindFlyFrame();
186 if( pNewAnch
&& &rFrame
!= pNewAnch
&& !pNewAnch
->IsProtected() )
188 aPos
.Assign( *static_cast<const SwFlyFrame
*>(pNewAnch
)->GetFormat()->GetContent().
190 aNewAnch
.SetAnchor( &aPos
);
195 nNew
= RndStdIds::FLY_AT_PAGE
;
196 aNewAnch
.SetType( nNew
);
199 case RndStdIds::FLY_AT_PAGE
:
200 pNewAnch
= rFrame
.FindPageFrame();
201 aNewAnch
.SetPageNum( pNewAnch
->GetPhyPageNum() );
205 OSL_ENSURE( false, "Wrong Id for new anchor." );
208 rSet
.Put( aNewAnch
);
212 //! also used in unoframe.cxx
214 bool sw_ChkAndSetNewAnchor(
215 const SwFlyFrame
& rFly
,
218 const SwFrameFormat
& rFormat
= *rFly
.GetFormat();
219 const SwFormatAnchor
&rOldAnch
= rFormat
.GetAnchor();
220 const RndStdIds nOld
= rOldAnch
.GetAnchorId();
222 RndStdIds nNew
= rSet
.Get( RES_ANCHOR
).GetAnchorId();
227 SwDoc
* pDoc
= const_cast<SwDoc
*>(rFormat
.GetDoc());
229 #if OSL_DEBUG_LEVEL > 0
230 OSL_ENSURE( !(nNew
== RndStdIds::FLY_AT_PAGE
&&
231 (RndStdIds::FLY_AT_PARA
==nOld
|| RndStdIds::FLY_AT_CHAR
==nOld
|| RndStdIds::FLY_AS_CHAR
==nOld
) &&
232 pDoc
->IsInHeaderFooter( *rOldAnch
.GetAnchorNode() )),
233 "forbidden anchor change in Head/Foot." );
236 return ::lcl_FindAnchorPos( *pDoc
, rFly
.getFrameArea().Pos(), rFly
, rSet
);
239 void SwFEShell::SelectFlyFrame( SwFlyFrame
& rFrame
)
241 CurrShell
aCurr( this );
243 // The frame is new, thus select it.
244 // !! Always select the frame, if it's not selected.
245 // - it could be a new "old" one because the anchor was changed
246 // - "old" frames have had to be selected previously otherwise they could
247 // not have been changed
248 // The frames should not be selected by the document position, because
249 // it should have been selected!
250 SwViewShellImp
*pImpl
= Imp();
254 OSL_ENSURE( rFrame
.IsFlyFrame(), "SelectFlyFrame wants a Fly" );
256 // nothing to be done if the Fly already was selected
257 if (GetSelectedFlyFrame() == &rFrame
)
260 // assure the anchor is drawn
261 if( rFrame
.IsFlyInContentFrame() && rFrame
.GetAnchorFrame() )
262 rFrame
.GetAnchorFrame()->SetCompletePaint();
264 if( pImpl
->GetDrawView()->GetMarkedObjectList().GetMarkCount() != 0 )
265 pImpl
->GetDrawView()->UnmarkAll();
267 pImpl
->GetDrawView()->MarkObj( rFrame
.GetVirtDrawObj(),
268 pImpl
->GetPageView() );
270 rFrame
.SelectionHasChanged(this);
277 void SwFEShell::UnfloatFlyFrame()
279 GetIDocumentUndoRedo().StartUndo(SwUndoId::DELLAYFMT
, nullptr);
280 comphelper::ScopeGuard
g([this]
281 { GetIDocumentUndoRedo().EndUndo(SwUndoId::DELLAYFMT
, nullptr); });
283 SwFlyFrame
* pFly
= GetSelectedFlyFrame();
289 SwFrameFormat
* pFlyFormat
= pFly
->GetFrameFormat();
290 const SwFormatContent
& rContent
= pFlyFormat
->GetContent();
291 const SwNodeIndex
* pFlyStart
= rContent
.GetContentIdx();
297 const SwEndNode
* pFlyEnd
= pFlyStart
->GetNode().EndOfSectionNode();
303 // Create an empty paragraph after the table, so the frame's SwNodes section is non-empty after
304 // MoveNodeRange(). Undo would ensure it's non-empty and then node offsets won't match.
305 IDocumentContentOperations
& rIDCO
= GetDoc()->getIDocumentContentOperations();
307 SwNodeIndex
aInsertIndex(*pFlyEnd
);
309 SwPosition
aInsertPos(aInsertIndex
);
311 rIDCO
.AppendTextNode(aInsertPos
);
312 // Make sure that a layout frame is created for the node, so the fly frame is not deleted,
313 // during MoveNodeRange(), either.
317 SwNodeRange
aRange(pFlyStart
->GetNode(), SwNodeOffset(1), *pFlyEnd
, SwNodeOffset(-1));
318 const SwFormatAnchor
& rAnchor
= pFlyFormat
->GetAnchor();
319 SwNode
* pAnchor
= rAnchor
.GetAnchorNode();
325 // Move the content outside of the text frame.
326 SwNodeIndex
aInsertPos(*pAnchor
);
327 rIDCO
.MoveNodeRange(aRange
, aInsertPos
.GetNode(), SwMoveFlags::CREATEUNDOOBJ
);
329 // Remove the fly frame frame.
330 IDocumentLayoutAccess
& rIDLA
= pFlyFormat
->getIDocumentLayoutAccess();
331 rIDLA
.DelLayoutFormat(pFlyFormat
);
335 SwFlyFrame
* SwFEShell::GetSelectedFlyFrame() const
337 if ( Imp()->HasDrawView() )
339 // A Fly is only accessible if it is selected
340 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
341 if( rMrkList
.GetMarkCount() != 1 )
344 SdrObject
*pO
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
346 SwVirtFlyDrawObj
*pFlyObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pO
);
348 return pFlyObj
? pFlyObj
->GetFlyFrame() : nullptr;
353 // Get current fly in which the cursor is positioned
354 SwFlyFrame
* SwFEShell::GetCurrFlyFrame(const bool bCalcFrame
) const
356 SwContentFrame
*pContent
= GetCurrFrame(bCalcFrame
);
357 return pContent
? pContent
->FindFlyFrame() : nullptr;
360 // Get selected fly, but if none Get current fly in which the cursor is positioned
361 SwFlyFrame
* SwFEShell::GetSelectedOrCurrFlyFrame() const
363 SwFlyFrame
*pFly
= GetSelectedFlyFrame();
366 return GetCurrFlyFrame();
369 // Returns non-null pointer, if the current Fly could be anchored to another one (so it is inside)
370 const SwFrameFormat
* SwFEShell::IsFlyInFly()
372 CurrShell
aCurr( this );
374 if ( !Imp()->HasDrawView() )
377 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
378 if ( !rMrkList
.GetMarkCount() )
380 SwFlyFrame
*pFly
= GetCurrFlyFrame(false);
383 return pFly
->GetFormat();
385 else if ( rMrkList
.GetMarkCount() != 1 )
388 SdrObject
*pObj
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
389 SwContact
* pContact
= GetUserCall( pObj
);
393 SwFrameFormat
*pFormat
= FindFrameFormat( pObj
);
394 if( pFormat
&& RndStdIds::FLY_AT_FLY
== pFormat
->GetAnchor().GetAnchorId() )
397 if (SwVirtFlyDrawObj
* pFlyObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
399 pFly
= pFlyObj
->GetFlyFrame()->GetAnchorFrame();
403 pFly
= static_cast<SwDrawContact
*>(pContact
)->GetAnchorFrame(pObj
);
406 assert(pFly
&& "IsFlyInFly: Where's my anchor?");
407 OSL_ENSURE( pFly
->IsFlyFrame(), "IsFlyInFly: Funny anchor!" );
408 return static_cast<const SwFlyFrame
*>(pFly
)->GetFormat();
411 Point aTmpPos
= pObj
->GetCurrentBoundRect().TopLeft();
415 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
416 SwNodeIndex
aSwNodeIndex( GetDoc()->GetNodes() );
417 SwPosition
aPos( aSwNodeIndex
);
418 Point
aPoint( aTmpPos
);
419 aPoint
.setX(aPoint
.getX() - 1); //do not land in the fly!!
420 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPoint
, &aState
);
421 // determine text frame by left-top-corner of object
422 SwContentNode
*pNd
= aPos
.GetNode().GetContentNode();
423 std::pair
<Point
, bool> const tmp(aTmpPos
, false);
424 pTextFrame
= pNd
? pNd
->getLayoutFrame(GetLayout(), nullptr, &tmp
) : nullptr;
426 const SwFrame
*pTmp
= pTextFrame
? ::FindAnchor(pTextFrame
, aTmpPos
) : nullptr;
427 const SwFlyFrame
*pFly
= pTmp
? pTmp
->FindFlyFrame() : nullptr;
429 return pFly
->GetFormat();
433 void SwFEShell::SetFlyPos( const Point
& rAbsPos
)
435 CurrShell
aCurr( this );
437 // Determine reference point in document coordinates
438 SwFlyFrame
*pFly
= GetCurrFlyFrame(false);
442 //SwSaveHdl aSaveX( Imp() );
444 // Set an anchor starting from the absolute position for paragraph bound Flys
445 // Anchor and new RelPos will be calculated and set by the Fly
446 if ( pFly
->IsFlyAtContentFrame() )
448 if(pFly
->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame
* >(pFly
)->isTransformableSwFrame())
450 // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used),
451 // we need to correct the absolute position (rAbsPos) which was created in
452 // transformed coordinates to untransformed state
453 TransformableSwFrame
* pTransformableSwFrame(static_cast<SwFlyFreeFrame
*>(pFly
)->getTransformableSwFrame());
454 const SwRect
aUntransformedFrameArea(pTransformableSwFrame
->getUntransformedFrameArea());
455 const Point
aNewAbsPos(
456 rAbsPos
.X() + aUntransformedFrameArea
.Left() - pFly
->getFrameArea().Left(),
457 rAbsPos
.Y() + aUntransformedFrameArea
.Top() - pFly
->getFrameArea().Top());
458 static_cast<SwFlyAtContentFrame
*>(pFly
)->SetAbsPos(aNewAbsPos
);
462 static_cast<SwFlyAtContentFrame
*>(pFly
)->SetAbsPos( rAbsPos
);
467 const SwFrame
*pAnch
= pFly
->GetAnchorFrame();
468 Point
aOrient( pAnch
->getFrameArea().Pos() );
470 if ( pFly
->IsFlyInContentFrame() )
471 aOrient
.setX(rAbsPos
.getX());
474 aOrient
.setX(rAbsPos
.getX() - aOrient
.getX());
475 aOrient
.setY(rAbsPos
.getY() - aOrient
.getY());
476 pFly
->ChgRelPos( aOrient
);
478 CallChgLnk(); // call the AttrChangeNotify on the UI-side.
481 Point
SwFEShell::FindAnchorPos( const Point
& rAbsPos
, bool bMoveIt
)
485 CurrShell
aCurr( this );
487 if ( !Imp()->HasDrawView() )
490 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
491 if (rMrkList
.GetMarkCount() != 1)
494 SdrObject
* pObj
= rMrkList
.GetMark(0)->GetMarkedSdrObj();
496 SwContact
* pContact
= ::GetUserCall( pObj
);
503 SwAnchoredObject
* pAnchoredObj
= pContact
->GetAnchoredObj( pObj
);
504 SwFrameFormat
* pFormat
= pAnchoredObj
->GetFrameFormat();
505 const RndStdIds nAnchorId
= pFormat
->GetAnchor().GetAnchorId();
507 if ( RndStdIds::FLY_AS_CHAR
== nAnchorId
)
510 bool bFlyFrame
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
) != nullptr;
512 bool bTextBox
= false;
513 if (pFormat
->Which() == RES_DRAWFRMFMT
)
515 bTextBox
= SwTextBoxHelper::isTextBox(pFormat
, RES_DRAWFRMFMT
, pObj
);
518 SwFlyFrame
* pFly
= nullptr;
519 const SwFrame
* pFooterOrHeader
= nullptr;
523 // Calculate reference point in document coordinates
524 SwContentFrame
*pContent
= GetCurrFrame( false );
527 pFly
= pContent
->FindFlyFrame();
530 const SwFrame
* pOldAnch
= pFly
->GetAnchorFrame();
533 if ( RndStdIds::FLY_AT_PAGE
!= nAnchorId
)
535 pFooterOrHeader
= pContent
->FindFooterOrHeader();
541 = dynamic_cast<const SwFlyFrameFormat
*>(SwTextBoxHelper::getOtherTextBoxFormat(
542 pFormat
, RES_DRAWFRMFMT
, pObj
));
545 pFly
= pFlyFormat
->GetFrame();
549 // set <pFooterOrHeader> also for drawing
550 // objects, but not for control objects.
551 // Necessary for moving 'anchor symbol' at the user interface inside header/footer.
552 else if ( !::CheckControlLayer( pObj
) )
554 SwContentFrame
*pContent
= GetCurrFrame( false );
557 pFooterOrHeader
= pContent
->FindFooterOrHeader();
560 // Search nearest SwFlyFrame starting from the upper-left corner
562 SwContentFrame
*pTextFrame
= nullptr;
564 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
565 SwPosition
aPos( GetDoc()->GetNodes().GetEndOfExtras() );
566 Point
aTmpPnt( rAbsPos
);
567 GetLayout()->GetModelPositionForViewPoint( &aPos
, aTmpPnt
, &aState
);
568 if (aPos
.GetNode() != GetDoc()->GetNodes().GetEndOfExtras()
569 && (nAnchorId
!= RndStdIds::FLY_AT_CHAR
|| !PosInsideInputField(aPos
)))
571 SwContentNode
* pCNode
= aPos
.GetNode().GetContentNode();
573 pTextFrame
= pCNode
->getLayoutFrame(GetLayout(), &aPos
, nullptr);
576 const SwFrame
*pNewAnch
= nullptr;
577 if( pTextFrame
!= nullptr )
579 if ( RndStdIds::FLY_AT_PAGE
== nAnchorId
)
581 pNewAnch
= pTextFrame
->FindPageFrame();
585 pNewAnch
= ::FindAnchor( pTextFrame
, rAbsPos
);
587 if( RndStdIds::FLY_AT_FLY
== nAnchorId
) // LAYER_IMPL
589 pNewAnch
= pNewAnch
->FindFlyFrame();
594 if( pNewAnch
&& !pNewAnch
->IsProtected() )
596 const SwFlyFrame
* pCheck
= (bFlyFrame
|| bTextBox
) ? pNewAnch
->FindFlyFrame() : nullptr;
597 // If we land inside the frame, make sure
598 // that the frame does not land inside its own content
603 const SwFrame
*pTmp
= pCheck
->GetAnchorFrame();
604 pCheck
= pTmp
? pTmp
->FindFlyFrame() : nullptr;
607 // Do not switch from header/footer to another area,
608 // do not switch to a header/footer
610 pFooterOrHeader
== pNewAnch
->FindFooterOrHeader() )
612 aRet
= pNewAnch
->GetFrameAnchorPos( ::HasWrap( pObj
) );
614 if ( bMoveIt
|| (nAnchorId
== RndStdIds::FLY_AT_CHAR
) )
616 SwFormatAnchor
aAnch( pFormat
->GetAnchor() );
619 case RndStdIds::FLY_AT_PARA
:
621 SwPosition
pos(pTextFrame
->IsTextFrame()
622 ? *static_cast<SwTextFrame
const*>(pTextFrame
)->GetTextNodeForParaProps()
623 : *static_cast<const SwNoTextFrame
*>(pTextFrame
)->GetNode());
624 aAnch
.SetAnchor( &pos
);
627 case RndStdIds::FLY_AT_PAGE
:
629 aAnch
.SetPageNum( static_cast<const SwPageFrame
*>(pNewAnch
)->
634 case RndStdIds::FLY_AT_FLY
:
636 SwPosition
aPos( *static_cast<const SwFlyFrame
*>(pNewAnch
)->GetFormat()->
637 GetContent().GetContentIdx() );
638 aAnch
.SetAnchor( &aPos
);
642 case RndStdIds::FLY_AT_CHAR
:
644 SwPosition pos
= *aAnch
.GetContentAnchor();
645 Point
aTmpPnt( rAbsPos
);
646 if( pTextFrame
->GetModelPositionForViewPoint( &pos
, aTmpPnt
) )
649 pTextFrame
->GetCharRect( aTmpRect
, pos
);
650 aRet
= aTmpRect
.Pos();
654 pos
= static_cast<SwTextFrame
const*>(pTextFrame
)->MapViewToModelPos(TextFrameIndex(0));
656 aAnch
.SetAnchor( &pos
);
667 // --> handle change of anchor node:
668 // if count of the anchor frame also change, the fly frames have to be
669 // re-created. Thus, delete all fly frames except the <this> before the
670 // anchor attribute is change and re-create them afterwards.
672 std::unique_ptr
<SwHandleAnchorNodeChg
> pHandleAnchorNodeChg
;
673 SwFlyFrameFormat
* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat
*>(pFormat
) );
674 if ( pFlyFrameFormat
)
676 pHandleAnchorNodeChg
.reset(
677 new SwHandleAnchorNodeChg( *pFlyFrameFormat
, aAnch
));
679 pFormat
->GetDoc()->SetAttr( aAnch
, *pFormat
);
680 if (SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_DRAWFRMFMT
,
683 if (SdrObjList
* pObjList
= pObj
->getChildrenOfSdrObject())
685 for (const rtl::Reference
<SdrObject
>& pChild
: *pObjList
)
686 SwTextBoxHelper::changeAnchor(pFormat
, pChild
.get());
689 SwTextBoxHelper::syncFlyFrameAttr(
690 *pFormat
, pFormat
->GetAttrSet(), pObj
);
693 // #i28701# - no call of method
694 // <CheckCharRectAndTopOfLine()> for to-character anchored
695 // Writer fly frame needed. This method call can cause a
696 // format of the anchor frame, which is no longer intended.
697 // Instead clear the anchor character rectangle and
698 // the top of line values for all to-character anchored objects.
699 pAnchoredObj
->ClearCharRectAndTopOfLine();
704 SwRect
aTmpRect( aRet
, rAbsPos
);
705 if( aTmpRect
.HasArea() )
706 MakeVisible( aTmpRect
);
707 #if OSL_DEBUG_LEVEL > 0
708 //TODO: That doesn't seem to be intended
709 if( COL_TRANSPARENT
!= GetOut()->GetLineColor() )
711 OSL_FAIL( "Hey, Joe: Where's my Null Pen?" );
712 GetOut()->SetLineColor( COL_TRANSPARENT
);
721 const SwFrameFormat
*SwFEShell::NewFlyFrame( const SfxItemSet
& rSet
, bool bAnchValid
,
722 SwFrameFormat
*pParent
)
724 CurrShell
aCurr( this );
727 SwPaM
* pCursor
= GetCursor();
728 const Point
aPt( GetCursorDocPos() );
731 bool bMoveContent
= true;
734 GetTableSel( *this, aBoxes
);
735 if( !aBoxes
.empty() )
737 // Cursor should be removed from the removal area.
738 // Always put it after/on the table; via the
739 // document position they will be set to the old
741 ParkCursor( *aBoxes
[0]->GetSttNd() );
743 // #i127787# pCurrentCursor will be deleted in ParkCursor,
744 // we better get the current pCurrentCursor instead of working with the
746 pCursor
= GetCursor();
749 bMoveContent
= false;
751 else if( !pCursor
->HasMark() && !pCursor
->IsMultiSelection() )
752 bMoveContent
= false;
754 const SwPosition
& rPos
= *pCursor
->Start();
756 SwFormatAnchor
& rAnch
= const_cast<SwFormatAnchor
&>(rSet
.Get( RES_ANCHOR
));
757 RndStdIds eRndId
= rAnch
.GetAnchorId();
760 case RndStdIds::FLY_AT_PAGE
:
761 if( !rAnch
.GetPageNum() ) //HotFix: Bug in UpdateByExample
762 rAnch
.SetPageNum( 1 );
765 case RndStdIds::FLY_AT_FLY
:
766 case RndStdIds::FLY_AT_PARA
:
767 case RndStdIds::FLY_AT_CHAR
:
768 case RndStdIds::FLY_AS_CHAR
:
771 if( RndStdIds::FLY_AT_FLY
!= eRndId
)
773 rAnch
.SetAnchor( &rPos
);
775 else if( lcl_SetNewFlyPos( rPos
.GetNode(), rAnch
, aPt
) )
777 eRndId
= RndStdIds::FLY_AT_PAGE
;
783 OSL_ENSURE( false, "What is the purpose of this Fly?" );
787 SwFlyFrameFormat
*pRet
;
790 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSLAYFMT
, nullptr );
791 std::unique_ptr
<SwFormatAnchor
> pOldAnchor
;
792 bool bHOriChgd
= false, bVOriChgd
= false;
793 std::shared_ptr
<SwFormatVertOrient
> aOldV
;
794 std::shared_ptr
<SwFormatHoriOrient
> aOldH
;
796 if ( RndStdIds::FLY_AT_PAGE
!= eRndId
)
798 // First as with page link. Paragraph/character link on if
799 // everything was shifted. Then the position is valid!
800 // JP 13.05.98: if necessary also convert the horizontal/vertical
801 // orientation, to prevent correction during re-anchoring
802 pOldAnchor
.reset(new SwFormatAnchor( rAnch
));
803 const_cast<SfxItemSet
&>(rSet
).Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE
, 1 ) );
805 const SwFormatHoriOrient
* pHoriOrientItem
;
806 if( (pHoriOrientItem
= rSet
.GetItemIfSet( RES_HORI_ORIENT
, false ))
807 && text::HoriOrientation::NONE
== pHoriOrientItem
->GetHoriOrient() )
810 aOldH
.reset(pHoriOrientItem
->Clone());
811 const_cast<SfxItemSet
&>(rSet
).Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT
) );
813 const SwFormatVertOrient
* pVertOrientItem
;
814 if( (pVertOrientItem
= rSet
.GetItemIfSet( RES_VERT_ORIENT
, false ))
815 && text::VertOrientation::NONE
== pVertOrientItem
->GetVertOrient() )
818 aOldV
.reset(pVertOrientItem
->Clone());
819 const_cast<SfxItemSet
&>(rSet
).Put( SwFormatVertOrient( 0, text::VertOrientation::TOP
) );
823 pRet
= GetDoc()->MakeFlyAndMove( *pCursor
, rSet
, &aBoxes
, pParent
);
831 // calculate new position
832 // JP 24.03.97: also go via page links
833 // anchor should not lie in the shifted area
836 const SwFrame
* pAnch
= ::FindAnchor( GetLayout(), aPt
);
837 SwPosition
aPos( pAnch
->IsTextFrame()
838 ? *static_cast<SwTextFrame
const*>(pAnch
)->GetTextNodeForParaProps()
839 : *static_cast<const SwNoTextFrame
*>(pAnch
)->GetNode() );
841 if ( RndStdIds::FLY_AS_CHAR
== eRndId
)
843 assert(pAnch
->IsTextFrame());
844 aPos
= static_cast<SwTextFrame
const*>(pAnch
)->MapViewToModelPos(TextFrameIndex(0));
846 pOldAnchor
->SetAnchor( &aPos
);
848 // shifting of table selection is not Undo-capable. therefore
849 // changing the anchors should not be recorded
850 bool const bDoesUndo
=
851 GetDoc()->GetIDocumentUndoRedo().DoesUndo();
852 SwUndoId
nLastUndoId(SwUndoId::EMPTY
);
854 GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(nullptr,
857 if (SwUndoId::INSLAYFMT
== nLastUndoId
)
859 GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
863 const_cast<SfxItemSet
&>(rSet
).Put( std::move(pOldAnchor
) );
866 const_cast<SfxItemSet
&>(rSet
).Put( *aOldH
);
868 const_cast<SfxItemSet
&>(rSet
).Put( *aOldV
);
870 GetDoc()->SetFlyFrameAttr( *pRet
, const_cast<SfxItemSet
&>(rSet
) );
871 GetDoc()->GetIDocumentUndoRedo().DoUndo(bDoesUndo
);
874 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSLAYFMT
, nullptr );
877 /* If called from a shell try to propagate an
878 existing adjust item from rPos to the content node of the
880 pRet
= GetDoc()->MakeFlySection( eRndId
, &rPos
, &rSet
, pParent
, true );
884 SwFlyFrame
* pFrame
= pRet
->GetFrame( &aPt
);
886 SelectFlyFrame( *pFrame
);
889 GetLayout()->SetAssertFlyPages();
893 EndAllActionAndCall();
900 /// If pCursor points to an as-char anchored graphic node, then set the node's anchor position on
901 /// pAnchor and rPam.
902 bool SetAnchorOnGrfNodeForAsChar(SwShellCursor
*pCursor
, SwFormatAnchor
* pAnchor
, std::optional
<SwPaM
>& rPam
)
904 const SwPosition
* pPoint
= pCursor
->GetPoint();
905 if (pAnchor
->GetAnchorId() != RndStdIds::FLY_AS_CHAR
)
910 if (!pPoint
->GetNode().IsGrfNode())
915 SwFrameFormat
* pFrameFormat
= pPoint
->GetNode().GetFlyFormat();
921 const SwPosition
* pContentAnchor
= pFrameFormat
->GetAnchor().GetContentAnchor();
927 SwPosition
aPosition(*pContentAnchor
);
928 ++aPosition
.nContent
;
929 pAnchor
->SetAnchor(&aPosition
);
930 rPam
.emplace(aPosition
);
935 void SwFEShell::Insert( const OUString
& rGrfName
, const OUString
& rFltName
,
936 const Graphic
* pGraphic
,
937 const SfxItemSet
* pFlyAttrSet
)
939 SwFlyFrameFormat
* pFormat
= nullptr;
940 CurrShell
aCurr( this );
942 SwShellCursor
*pStartCursor
= dynamic_cast<SwShellCursor
*>(GetCursor());
943 SwShellCursor
*pCursor
= pStartCursor
;
949 // Has the anchor not been set or been set incompletely?
950 std::optional
<SwPaM
> oPam
;
953 if( const SwFormatAnchor
* pItem
= pFlyAttrSet
->GetItemIfSet( RES_ANCHOR
, false ) )
955 SwFormatAnchor
* pAnchor
= const_cast<SwFormatAnchor
*>(pItem
);
956 switch( pAnchor
->GetAnchorId())
958 case RndStdIds::FLY_AT_PARA
:
959 case RndStdIds::FLY_AT_CHAR
: // LAYER_IMPL
960 case RndStdIds::FLY_AS_CHAR
:
961 if( !pAnchor
->GetAnchorNode() )
963 if (SetAnchorOnGrfNodeForAsChar(pCursor
, pAnchor
, oPam
))
965 // Don't anchor the image on the previous image, rather insert them next
970 pAnchor
->SetAnchor( pCursor
->GetPoint() );
973 case RndStdIds::FLY_AT_FLY
:
974 if( !pAnchor
->GetAnchorNode() )
976 lcl_SetNewFlyPos( pCursor
->GetPointNode(),
977 *pAnchor
, GetCursorDocPos() );
980 case RndStdIds::FLY_AT_PAGE
:
981 if( !pAnchor
->GetPageNum() )
983 pAnchor
->SetPageNum( pCursor
->GetPageNum(
984 true, &pCursor
->GetPtPos() ) );
992 pFormat
= GetDoc()->getIDocumentContentOperations().InsertGraphic(
993 oPam
.has_value() ? *oPam
: *pCursor
, rGrfName
,
997 OSL_ENSURE(pFormat
, "IDocumentContentOperations::InsertGraphic failed.");
999 pCursor
= pCursor
->GetNext();
1000 } while( pCursor
!= pStartCursor
);
1007 const Point
aPt( GetCursorDocPos() );
1008 SwFlyFrame
* pFrame
= pFormat
->GetFrame( &aPt
);
1012 // add a redline to the anchor point at tracked insertion of picture
1013 if ( IsRedlineOn() )
1015 const SwPosition
& rPos(*pFormat
->GetAnchor().GetContentAnchor());
1016 SwPaM
aPaM(rPos
.GetNode(), rPos
.GetContentIndex(),
1017 rPos
.GetNode(), rPos
.GetContentIndex() + 1);
1018 GetDoc()->getIDocumentRedlineAccess().AppendRedline(
1019 new SwRangeRedline( RedlineType::Insert
, aPaM
), true);
1022 // fdo#36681: Invalidate the content and layout to refresh
1023 // the picture anchoring properly
1024 SwPageFrame
* pPageFrame
= pFrame
->FindPageFrameOfAnchor();
1025 pPageFrame
->InvalidateFlyLayout();
1026 pPageFrame
->InvalidateContent();
1028 SelectFlyFrame( *pFrame
);
1031 GetLayout()->SetAssertFlyPages();
1034 SwFlyFrameFormat
* SwFEShell::InsertObject( const svt::EmbeddedObjectRef
& xObj
,
1035 SfxItemSet
* pFlyAttrSet
)
1037 SwFlyFrameFormat
* pFormat
= nullptr;
1038 CurrShell
aCurr( this );
1041 for(const SwPaM
& rPaM
: GetCursor()->GetRingContainer())
1043 pFormat
= GetDoc()->getIDocumentContentOperations().InsertEmbObject(
1044 rPaM
, xObj
, pFlyAttrSet
);
1045 OSL_ENSURE(pFormat
, "IDocumentContentOperations::InsertEmbObject failed.");
1052 const Point
aPt( GetCursorDocPos() );
1053 SwFlyFrame
* pFrame
= pFormat
->GetFrame( &aPt
);
1056 SelectFlyFrame( *pFrame
);
1058 GetLayout()->SetAssertFlyPages();
1064 void SwFEShell::InsertDrawObj( SdrObject
& rDrawObj
,
1065 const Point
& rInsertPosition
)
1067 CurrShell
aCurr( this );
1069 SfxItemSet
rFlyAttrSet( GetDoc()->GetAttrPool(), aFrameFormatSetRange
);
1070 rFlyAttrSet
.Put( SwFormatAnchor( RndStdIds::FLY_AT_PARA
));
1072 rFlyAttrSet
.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH
) );
1073 rDrawObj
.SetLayer( getIDocumentDrawModelAccess().GetHeavenId() );
1075 // find anchor position
1076 SwPaM
aPam( mxDoc
->GetNodes() );
1078 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
1079 Point
aTmpPt( rInsertPosition
);
1080 GetLayout()->GetModelPositionForViewPoint( aPam
.GetPoint(), aTmpPt
, &aState
);
1081 const SwFrame
* pFrame
= aPam
.GetPointContentNode()->getLayoutFrame(GetLayout(), nullptr, nullptr);
1082 const Point
aRelPos( rInsertPosition
.X() - pFrame
->getFrameArea().Left(),
1083 rInsertPosition
.Y() - pFrame
->getFrameArea().Top() );
1084 rDrawObj
.SetRelativePos( aRelPos
);
1085 ::lcl_FindAnchorPos( *GetDoc(), rInsertPosition
, *pFrame
, rFlyAttrSet
);
1087 // insert drawing object into the document creating a new <SwDrawFrameFormat> instance
1088 SwDrawFrameFormat
* pFormat
= GetDoc()->getIDocumentContentOperations().InsertDrawObj( aPam
, rDrawObj
, rFlyAttrSet
);
1090 // move object to visible layer
1091 SwContact
* pContact
= static_cast<SwContact
*>(rDrawObj
.GetUserCall());
1094 pContact
->MoveObjToVisibleLayer( &rDrawObj
);
1099 pFormat
->SetFormatName(rDrawObj
.GetName());
1100 // select drawing object
1101 Imp()->GetDrawView()->MarkObj( &rDrawObj
, Imp()->GetPageView() );
1105 GetLayout()->SetAssertFlyPages();
1109 void SwFEShell::GetPageObjs( std::vector
<SwFrameFormat
*>& rFillArr
)
1113 for(sw::SpzFrameFormat
* pFormat
: *mxDoc
->GetSpzFrameFormats() )
1115 if (RndStdIds::FLY_AT_PAGE
== pFormat
->GetAnchor().GetAnchorId())
1117 rFillArr
.push_back( pFormat
);
1122 void SwFEShell::SetPageObjsNewPage( std::vector
<SwFrameFormat
*>& rFillArr
)
1124 if( rFillArr
.empty() )
1130 SwRootFrame
* pTmpRootFrame
= GetLayout();
1131 sal_uInt16 nMaxPage
= pTmpRootFrame
->GetPageNum();
1132 bool bTmpAssert
= false;
1133 for( auto pFormat
: rFillArr
)
1135 if (mxDoc
->GetSpzFrameFormats()->IsAlive(static_cast<sw::SpzFrameFormat
*>(pFormat
)))
1137 // FlyFormat is still valid, therefore process
1139 SwFormatAnchor
aNewAnchor( pFormat
->GetAnchor() );
1140 if (RndStdIds::FLY_AT_PAGE
!= aNewAnchor
.GetAnchorId())
1141 // Anchor has been changed, therefore: do not change!
1143 sal_uInt16 nNewPage
= aNewAnchor
.GetPageNum() + 1;
1144 if (nNewPage
> nMaxPage
)
1146 if ( RES_DRAWFRMFMT
== pFormat
->Which() )
1147 pFormat
->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PAGE_OUT_OF_BOUNDS
));
1149 pFormat
->DelFrames();
1152 aNewAnchor
.SetPageNum(nNewPage
);
1153 mxDoc
->SetAttr( aNewAnchor
, *pFormat
);
1158 pTmpRootFrame
->SetAssertFlyPages();
1164 // All attributes in the "baskets" will be filled with the attributes of the
1165 // current FlyFrames. Attributes which cannot be filled due to being at the
1166 // wrong place or which are ambiguous (multiple selections) will be removed.
1167 bool SwFEShell::GetFlyFrameAttr( SfxItemSet
&rSet
) const
1169 SwFlyFrame
*pFly
= GetSelectedOrCurrFlyFrame();
1172 OSL_ENSURE( false, "GetFlyFrameAttr, no Fly selected." );
1176 CurrShell
aCurr( const_cast<SwFEShell
*>(this) );
1178 if( !rSet
.Set( pFly
->GetFormat()->GetAttrSet() ) )
1181 // now examine all attributes. Remove forbidden attributes, then
1182 // get all remaining attributes and enter them
1184 if( const SwFormatAnchor
* pAnchor
= rSet
.GetItemIfSet( RES_ANCHOR
, false ) )
1186 RndStdIds eType
= pAnchor
->GetAnchorId();
1188 if ( RndStdIds::FLY_AT_PAGE
!= eType
)
1190 // OD 12.11.2003 #i22341# - content anchor of anchor item is needed.
1191 // Thus, don't overwrite anchor item by default constructed anchor item.
1192 if ( RndStdIds::FLY_AS_CHAR
== eType
)
1194 rSet
.ClearItem( RES_OPAQUE
);
1195 rSet
.ClearItem( RES_SURROUND
);
1199 rSet
.SetParent( pFly
->GetFormat()->GetAttrSet().GetParent() );
1200 // attributes must be removed
1201 rSet
.ClearItem( RES_FILL_ORDER
);
1202 rSet
.ClearItem( RES_CNTNT
);
1203 //MA: remove first (Template by example etc.)
1204 rSet
.ClearItem( RES_CHAIN
);
1208 // Attributes of the current fly will change.
1209 bool SwFEShell::SetFlyFrameAttr( SfxItemSet
& rSet
)
1211 CurrShell
aCurr( this );
1216 SwFlyFrame
*pFly
= GetSelectedOrCurrFlyFrame();
1217 OSL_ENSURE(pFly
, "SetFlyFrameAttr, no Fly selected.");
1221 const Point
aPt( pFly
->getFrameArea().Pos() );
1223 if( SfxItemState::SET
== rSet
.GetItemState( RES_ANCHOR
, false ))
1224 sw_ChkAndSetNewAnchor( *pFly
, rSet
);
1225 SwFlyFrameFormat
* pFlyFormat
= pFly
->GetFormat();
1227 if( GetDoc()->SetFlyFrameAttr( *pFlyFormat
, rSet
))
1230 SwFlyFrame
* pFrame
= pFlyFormat
->GetFrame( &aPt
);
1232 SelectFlyFrame( *pFrame
);
1234 GetLayout()->SetAssertFlyPages();
1237 EndAllActionAndCall();
1243 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_ANCHOR
> SwFEShell::makeItemSetFromFormatAnchor(SfxItemPool
& rPool
, const SwFormatAnchor
&rAnchor
)
1245 // The set also includes VERT/HORI_ORIENT, because the align
1246 // shall be changed in FEShell::SetFlyFrameAttr/SetFlyFrameAnchor,
1247 // possibly as a result of the anchor change.
1248 SfxItemSetFixed
<RES_VERT_ORIENT
, RES_ANCHOR
> aSet(rPool
);
1253 bool SwFEShell::SetDrawingAttr( SfxItemSet
& rSet
)
1256 CurrShell
aCurr( this );
1257 if ( !rSet
.Count() ||
1258 !Imp()->HasDrawView() )
1261 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1262 if ( rMrkList
.GetMarkCount() != 1 )
1266 SdrObject
*pObj
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
1267 SwFrameFormat
*pFormat
= FindFrameFormat( pObj
);
1269 if( SfxItemState::SET
== rSet
.GetItemState( RES_ANCHOR
, false ))
1271 RndStdIds nNew
= rSet
.Get( RES_ANCHOR
).GetAnchorId();
1272 if ( nNew
!= pFormat
->GetAnchor().GetAnchorId() )
1275 // #i26791# - clear anchor attribute in item set,
1276 // because method <ChgAnchor(..)> takes care of it.
1277 rSet
.ClearItem( RES_ANCHOR
);
1281 if( GetDoc()->SetFlyFrameAttr( *pFormat
, rSet
))
1284 SelectObj( Point(), 0, pObj
);
1286 EndAllActionAndCall();
1291 // Reset attributes contained in the set.
1292 void SwFEShell::ResetFlyFrameAttr( const SfxItemSet
* pSet
)
1294 CurrShell
aCurr( this );
1296 SwFlyFrame
*pFly
= GetSelectedOrCurrFlyFrame();
1297 OSL_ENSURE( pFly
, "SetFlyFrameAttr, no Fly selected." );
1303 SfxItemIter
aIter( *pSet
);
1304 for (const SfxPoolItem
* pItem
= aIter
.GetCurItem(); pItem
; pItem
= aIter
.NextItem())
1306 if( !IsInvalidItem( pItem
) )
1308 sal_uInt16 nWhich
= pItem
->Which();
1309 if( RES_ANCHOR
!= nWhich
&& RES_CHAIN
!= nWhich
&& RES_CNTNT
!= nWhich
)
1310 pFly
->GetFormat()->ResetFormatAttr( nWhich
);
1314 EndAllActionAndCall();
1315 GetDoc()->getIDocumentState().SetModified();
1318 // Returns frame-format if frame, otherwise 0
1319 SwFrameFormat
* SwFEShell::GetSelectedFrameFormat() const
1321 SwFrameFormat
* pRet
= nullptr;
1322 SwLayoutFrame
*pFly
= GetSelectedFlyFrame();
1323 if( pFly
&& ( pRet
= static_cast<SwFrameFormat
*>(pFly
->GetFormat()->DerivedFrom()) ) ==
1324 GetDoc()->GetDfltFrameFormat() )
1329 void SwFEShell::SetFrameFormat( SwFrameFormat
*pNewFormat
, bool bKeepOrient
, Point
const * pDocPos
)
1331 SwFlyFrame
*pFly
= nullptr;
1334 const SwFrameFormat
* pFormat
= GetFormatFromObj( *pDocPos
);
1336 if (const SwFlyFrameFormat
* pFlyFormat
= dynamic_cast<const SwFlyFrameFormat
*>(pFormat
))
1337 pFly
= pFlyFormat
->GetFrame();
1340 pFly
= GetSelectedFlyFrame();
1341 OSL_ENSURE( pFly
, "SetFrameFormat: no frame" );
1346 CurrShell
aCurr( this );
1348 SwFlyFrameFormat
* pFlyFormat
= pFly
->GetFormat();
1349 const Point
aPt( pFly
->getFrameArea().Pos() );
1351 std::optional
<SfxItemSet
> oSet
;
1352 const SfxPoolItem
* pItem
;
1353 if( SfxItemState::SET
== pNewFormat
->GetItemState( RES_ANCHOR
, false, &pItem
))
1355 oSet
.emplace( GetDoc()->GetAttrPool(), aFrameFormatSetRange
);
1356 oSet
->Put( *pItem
);
1357 if( !sw_ChkAndSetNewAnchor( *pFly
, *oSet
))
1363 if( GetDoc()->SetFrameFormatToFly( *pFlyFormat
, *pNewFormat
, oSet
? &*oSet
: nullptr, bKeepOrient
))
1365 SwFlyFrame
* pFrame
= pFlyFormat
->GetFrame( &aPt
);
1367 SelectFlyFrame( *pFrame
);
1369 GetLayout()->SetAssertFlyPages();
1373 EndAllActionAndCall();
1376 const SwFrameFormat
* SwFEShell::GetFlyFrameFormat() const
1378 const SwFlyFrame
* pFly
= GetSelectedOrCurrFlyFrame();
1380 return pFly
->GetFormat();
1384 SwFrameFormat
* SwFEShell::GetFlyFrameFormat()
1386 SwFlyFrame
* pFly
= GetSelectedOrCurrFlyFrame();
1388 return pFly
->GetFormat();
1392 SwRect
SwFEShell::GetFlyRect() const
1394 SwFlyFrame
*pFly
= GetCurrFlyFrame(false);
1401 return pFly
->getFrameArea();
1404 SwRect
SwFEShell::GetObjRect() const
1406 if( Imp()->HasDrawView() )
1407 return SwRect(Imp()->GetDrawView()->GetAllMarkedRect());
1415 void SwFEShell::SetObjRect( const SwRect
& rRect
)
1417 if ( Imp()->HasDrawView() )
1419 Imp()->GetDrawView()->SetAllMarkedRect( rRect
.SVRect() );
1420 CallChgLnk(); // call AttrChangeNotify on the UI-side.
1424 Size
SwFEShell::RequestObjectResize( const SwRect
&rRect
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
1428 SwFlyFrame
*pFly
= FindFlyFrame( xObj
);
1431 aResult
= rRect
.SSize();
1435 aResult
= pFly
->getFramePrintArea().SSize();
1437 bool bPosProt
= pFly
->GetFormat()->GetProtect().IsPosProtected();
1438 bool bSizeProt
= pFly
->GetFormat()->GetProtect().IsSizeProtected();
1442 // MA we do not allow to clip the Fly, as the OLE server can
1443 // request various wishes. Clipping is done via the formatting.
1444 // Correct display is done by scaling.
1445 // Scaling is done by SwNoTextFrame::Format by calling
1446 // SwWrtShell::CalcAndSetScale()
1447 if ( rRect
.SSize() != pFly
->getFramePrintArea().SSize() && !bSizeProt
)
1449 Size
aSz( rRect
.SSize() );
1451 //JP 28.02.2001: Task 74707 - ask for fly in fly with automatic size
1453 const SwFrame
* pAnchor
;
1454 const SwFormatFrameSize
& rFrameSz
= pFly
->GetFormat()->GetFrameSize();
1455 if (m_bCheckForOLEInCaption
&&
1456 0 != rFrameSz
.GetWidthPercent() &&
1457 nullptr != (pAnchor
= pFly
->GetAnchorFrame()) &&
1458 pAnchor
->IsTextFrame() &&
1459 !pAnchor
->GetNext() && !pAnchor
->GetPrev() &&
1460 pAnchor
->GetUpper()->IsFlyFrame())
1462 // search for a sequence field:
1463 sw::MergedAttrIter
iter(*static_cast<SwTextFrame
const*>(pAnchor
));
1464 for (SwTextAttr
const* pHint
= iter
.NextAttr(); pHint
; pHint
= iter
.NextAttr())
1466 const SfxPoolItem
* pItem
= &pHint
->GetAttr();
1467 if( RES_TXTATR_FIELD
== pItem
->Which()
1468 && SwFieldTypesEnum::Sequence
== static_cast<const SwFormatField
*>(pItem
)->GetField()->GetTypeId() )
1470 // sequence field found
1471 SwFlyFrame
* pChgFly
= const_cast<SwFlyFrame
*>(static_cast<const SwFlyFrame
*>(pAnchor
->GetUpper()));
1472 // calculate the changed size:
1473 // width must change, height can change
1474 Size
aNewSz( aSz
.Width() + pChgFly
->getFrameArea().Width() -
1475 pFly
->getFramePrintArea().Width(), aSz
.Height() );
1477 SwFrameFormat
*pFormat
= pChgFly
->GetFormat();
1478 SwFormatFrameSize
aFrameSz( pFormat
->GetFrameSize() );
1479 aFrameSz
.SetWidth( aNewSz
.Width() );
1480 if( SwFrameSize::Minimum
!= aFrameSz
.GetHeightSizeType() )
1482 aNewSz
.AdjustHeight(pChgFly
->getFrameArea().Height() -
1483 pFly
->getFramePrintArea().Height() );
1484 if( std::abs( aNewSz
.Height() - pChgFly
->getFrameArea().Height()) > 1 )
1485 aFrameSz
.SetHeight( aNewSz
.Height() );
1487 // via Doc for the Undo!
1488 pFormat
->GetDoc()->SetAttr( aFrameSz
, *pFormat
);
1494 // set the new Size at the fly themself
1495 if ( !pFly
->getFramePrintArea().IsEmpty() )
1497 aSz
.AdjustWidth(pFly
->getFrameArea().Width() - pFly
->getFramePrintArea().Width() );
1498 aSz
.AdjustHeight(pFly
->getFrameArea().Height()- pFly
->getFramePrintArea().Height() );
1500 aResult
= pFly
->ChgSize( aSz
);
1502 // if the object changes, the contour is outside the object
1503 SwFrame
* pLower
= pFly
->Lower();
1504 assert(pLower
&& pLower
->IsNoTextFrame());
1505 SwNoTextNode
*pNd
= static_cast<SwNoTextFrame
*>(pLower
)->GetNode()->GetNoTextNode();
1507 pNd
->SetContour( nullptr );
1511 // if only the size is to be adjusted, a position is transported with
1513 Point
aPt( pFly
->getFramePrintArea().Pos() );
1514 aPt
+= pFly
->getFrameArea().Pos();
1515 if ( rRect
.Top() != LONG_MIN
&& rRect
.Pos() != aPt
&& !bPosProt
)
1518 aPt
.setX(aPt
.getX() - pFly
->getFramePrintArea().Left());
1519 aPt
.setY(aPt
.getY() - pFly
->getFramePrintArea().Top());
1521 // in case of paragraph-bound Flys, starting from the new position,
1522 // a new anchor is to be set. The anchor and the new RelPos are
1523 // calculated by the Fly and set
1524 if( pFly
->IsFlyAtContentFrame() )
1525 static_cast<SwFlyAtContentFrame
*>(pFly
)->SetAbsPos( aPt
);
1528 const SwFrameFormat
*pFormat
= pFly
->GetFormat();
1529 const SwFormatVertOrient
&rVert
= pFormat
->GetVertOrient();
1530 const SwFormatHoriOrient
&rHori
= pFormat
->GetHoriOrient();
1531 const tools::Long lXDiff
= aPt
.getX() - pFly
->getFrameArea().Left();
1532 const tools::Long lYDiff
= aPt
.getY() - pFly
->getFrameArea().Top();
1533 const Point
aTmp( rHori
.GetPos() + lXDiff
,
1534 rVert
.GetPos() + lYDiff
);
1535 pFly
->ChgRelPos( aTmp
);
1539 SwFlyFrameFormat
*pFlyFrameFormat
= pFly
->GetFormat();
1540 OSL_ENSURE( pFlyFrameFormat
, "fly frame format missing!" );
1541 if ( pFlyFrameFormat
)
1542 pFlyFrameFormat
->SetLastFlyFramePrtRectPos( pFly
->getFramePrintArea().Pos() ); //stores the value of last Prt rect
1549 SwFrameFormat
* SwFEShell::WizardGetFly()
1551 // do not search the Fly via the layout. Now we can delete a frame
1552 // without a valid layout. ( e.g. for the wizards )
1553 sw::SpzFrameFormats
& rSpzArr
= *mxDoc
->GetSpzFrameFormats();
1554 if( !rSpzArr
.empty() )
1556 SwNode
& rCursorNd
= GetCursor()->GetPoint()->GetNode();
1557 if( rCursorNd
> mxDoc
->GetNodes().GetEndOfExtras() )
1558 // Cursor is in the body area!
1561 for( auto pFormat
: rSpzArr
)
1563 const SwNodeIndex
* pIdx
= pFormat
->GetContent( false ).GetContentIdx();
1564 SwStartNode
* pSttNd
;
1566 nullptr != ( pSttNd
= pIdx
->GetNode().GetStartNode() ) &&
1567 *pSttNd
< rCursorNd
&&
1568 rCursorNd
< *pSttNd
->EndOfSectionNode() )
1570 // found: return immediately
1578 void SwFEShell::SetFlyName( const OUString
& rName
)
1580 SwLayoutFrame
*pFly
= GetSelectedFlyFrame();
1582 GetDoc()->SetFlyName( *static_cast<SwFlyFrameFormat
*>(pFly
->GetFormat()), rName
);
1584 OSL_ENSURE( false, "no FlyFrame selected" );
1588 OUString
SwFEShell::GetFlyName() const
1590 SwLayoutFrame
*pFly
= GetSelectedFlyFrame();
1592 return pFly
->GetFormat()->GetName();
1594 OSL_ENSURE( false, "no FlyFrame selected" );
1598 uno::Reference
< embed::XEmbeddedObject
> SwFEShell::GetOleRef() const
1600 uno::Reference
< embed::XEmbeddedObject
> xObj
;
1601 SwFlyFrame
* pFly
= GetSelectedFlyFrame();
1602 SwFrame
* pLower
= pFly
? pFly
->Lower() : nullptr;
1603 if (pLower
&& pLower
->IsNoTextFrame())
1605 SwOLENode
*pNd
= static_cast<SwNoTextFrame
*>(pLower
)->GetNode()->GetOLENode();
1607 xObj
= pNd
->GetOLEObj().GetOleRef();
1612 OUString
SwFEShell::GetUniqueGrfName() const
1614 return GetDoc()->GetUniqueGrfName();
1617 const SwFrameFormat
* SwFEShell::IsURLGrfAtPos( const Point
& rPt
, OUString
* pURL
,
1618 OUString
*pTargetFrameName
,
1619 OUString
*pDescription
) const
1621 if( !Imp()->HasDrawView() )
1625 const SwFrameFormat
* pRet
= nullptr;
1626 SwDrawView
*pDView
= const_cast<SwDrawView
*>(Imp()->GetDrawView());
1628 const auto nOld
= pDView
->GetHitTolerancePixel();
1629 pDView
->SetHitTolerancePixel( 2 );
1631 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMACRO
);
1632 SwVirtFlyDrawObj
* pFlyObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
);
1635 SwFlyFrame
*pFly
= pFlyObj
->GetFlyFrame();
1636 const SwFormatURL
&rURL
= pFly
->GetFormat()->GetURL();
1637 if( !rURL
.GetURL().isEmpty() || rURL
.GetMap() )
1639 bool bSetTargetFrameName
= pTargetFrameName
!= nullptr;
1640 bool bSetDescription
= pDescription
!= nullptr;
1641 if ( rURL
.GetMap() )
1643 IMapObject
*pObject
= pFly
->GetFormat()->GetIMapObject( rPt
, pFly
);
1644 if ( pObject
&& !pObject
->GetURL().isEmpty() )
1647 *pURL
= pObject
->GetURL();
1648 if ( bSetTargetFrameName
&& !pObject
->GetTarget().isEmpty() )
1650 bSetTargetFrameName
= false;
1651 *pTargetFrameName
= pObject
->GetTarget();
1653 if ( bSetDescription
)
1655 bSetDescription
= false;
1656 *pDescription
= pObject
->GetAltText();
1658 pRet
= pFly
->GetFormat();
1665 *pURL
= rURL
.GetURL();
1666 if( rURL
.IsServerMap() )
1668 // append the relative pixel position !!
1670 aPt
-= pFly
->getFrameArea().Pos();
1671 // without MapMode-Offset, without Offset, o ... !!!!!
1672 aPt
= GetOut()->LogicToPixel(
1673 aPt
, MapMode( MapUnit::MapTwip
) );
1674 *pURL
= *pURL
+ "?" + OUString::number( aPt
.getX() )
1675 + "," + OUString::number(aPt
.getY() );
1678 pRet
= pFly
->GetFormat();
1680 if ( bSetTargetFrameName
)
1681 *pTargetFrameName
= rURL
.GetTargetFrameName();
1682 if ( bSetDescription
)
1683 *pDescription
= pFly
->GetFormat()->GetName();
1686 pDView
->SetHitTolerancePixel( nOld
);
1690 const Graphic
*SwFEShell::GetGrfAtPos( const Point
&rPt
,
1691 OUString
&rName
, bool &rbLink
) const
1693 if( !Imp()->HasDrawView() )
1697 SwDrawView
*pDView
= const_cast<SwDrawView
*>(Imp()->GetDrawView());
1699 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPV
);
1700 SwVirtFlyDrawObj
* pFlyObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
);
1703 SwFlyFrame
*pFly
= pFlyObj
->GetFlyFrame();
1704 SwFrame
* pLower
= pFly
->Lower();
1705 if ( pLower
&& pLower
->IsNoTextFrame() )
1707 SwGrfNode
*const pNd
= static_cast<SwNoTextFrame
*>(pLower
)->GetNode()->GetGrfNode();
1710 if ( pNd
->IsGrfLink() )
1712 // halfway ready graphic?
1713 ::sfx2::SvLinkSource
* pLnkObj
= pNd
->GetLink()->GetObj();
1714 if( pLnkObj
&& pLnkObj
->IsPending() )
1719 pNd
->GetFileFilterNms( &rName
, nullptr );
1720 if ( rName
.isEmpty() )
1721 rName
= pFly
->GetFormat()->GetName();
1722 return &pNd
->GetGrf(true);
1729 const SwFrameFormat
* SwFEShell::GetFormatFromObj( const Point
& rPt
, SwRect
** pRectToFill
) const
1731 SwFrameFormat
* pRet
= nullptr;
1733 if( Imp()->HasDrawView() )
1735 SdrPageView
* pPView
;
1737 SwDrawView
*pDView
= const_cast<SwDrawView
*>(Imp()->GetDrawView());
1739 const auto nOld
= pDView
->GetHitTolerancePixel();
1740 // tolerance for Drawing-SS
1741 pDView
->SetHitTolerancePixel( pDView
->GetMarkHdlSizePixel()/2 );
1743 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPView
, SdrSearchOptions::PICKMARKABLE
);
1747 if (SwVirtFlyDrawObj
* pFlyObj
= dynamic_cast<SwVirtFlyDrawObj
*>(pObj
))
1748 pRet
= pFlyObj
->GetFormat();
1749 else if ( pObj
->GetUserCall() ) //not for group objects
1750 pRet
= static_cast<SwDrawContact
*>(pObj
->GetUserCall())->GetFormat();
1751 if(pRet
&& pRectToFill
)
1752 **pRectToFill
= SwRect(pObj
->GetCurrentBoundRect());
1754 pDView
->SetHitTolerancePixel( nOld
);
1759 // returns a format too, if the point is over the text of any fly
1760 const SwFrameFormat
* SwFEShell::GetFormatFromAnyObj( const Point
& rPt
) const
1762 const SwFrameFormat
* pRet
= GetFormatFromObj( rPt
);
1763 if( !pRet
|| RES_FLYFRMFMT
== pRet
->Which() )
1765 SwPosition
aPos( *GetCursor()->GetPoint() );
1767 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
);
1768 SwContentNode
*pNd
= aPos
.GetNode().GetContentNode();
1769 std::pair
<Point
, bool> const tmp(rPt
, false);
1770 SwFrame
* pFrame
= pNd
->getLayoutFrame(GetLayout(), nullptr, &tmp
)->FindFlyFrame();
1771 pRet
= pFrame
? static_cast<SwLayoutFrame
*>(pFrame
)->GetFormat() : nullptr;
1776 ObjCntType
SwFEShell::GetObjCntType( const SdrObject
& rObj
)
1778 ObjCntType eType
= OBJCNT_NONE
;
1780 // investigate 'master' drawing object, if method
1781 // is called for a 'virtual' drawing object.
1782 const SdrObject
* pInvestigatedObj
;
1783 if (const SwDrawVirtObj
* pDrawVirtObj
= dynamic_cast<const SwDrawVirtObj
*>( &rObj
))
1785 pInvestigatedObj
= &(pDrawVirtObj
->GetReferencedObj());
1789 pInvestigatedObj
= &rObj
;
1792 if( SdrInventor::FmForm
== pInvestigatedObj
->GetObjInventor() )
1794 eType
= OBJCNT_CONTROL
;
1795 uno::Reference
< awt::XControlModel
> xModel
=
1796 static_cast<const SdrUnoObj
&>(*pInvestigatedObj
).GetUnoControlModel();
1800 OUString
sName(u
"ButtonType"_ustr
);
1801 uno::Reference
< beans::XPropertySet
> xSet(xModel
, uno::UNO_QUERY
);
1803 uno::Reference
< beans::XPropertySetInfo
> xInfo
= xSet
->getPropertySetInfo();
1804 if(xInfo
->hasPropertyByName( sName
))
1806 aVal
= xSet
->getPropertyValue( sName
);
1807 if( aVal
.hasValue() && form::FormButtonType_URL
== *o3tl::doAccess
<form::FormButtonType
>(aVal
) )
1808 eType
= OBJCNT_URLBUTTON
;
1812 else if (const SwVirtFlyDrawObj
*pFlyObj
= dynamic_cast<const SwVirtFlyDrawObj
*>(pInvestigatedObj
))
1814 const SwFlyFrame
*pFly
= pFlyObj
->GetFlyFrame();
1815 const SwFrame
* pLower
= pFly
->Lower();
1816 if ( pLower
&& pLower
->IsNoTextFrame() )
1818 if (static_cast<const SwNoTextFrame
*>(pLower
)->GetNode()->GetGrfNode())
1826 else if ( dynamic_cast<const SdrObjGroup
*>( pInvestigatedObj
) != nullptr )
1828 SwDrawContact
* pDrawContact( dynamic_cast<SwDrawContact
*>(GetUserCall( pInvestigatedObj
) ) );
1829 if ( !pDrawContact
)
1831 OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing draw contact object" );
1832 eType
= OBJCNT_NONE
;
1836 SwFrameFormat
* pFrameFormat( pDrawContact
->GetFormat() );
1837 if ( !pFrameFormat
)
1839 OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing frame format" );
1840 eType
= OBJCNT_NONE
;
1842 else if ( RndStdIds::FLY_AS_CHAR
!= pFrameFormat
->GetAnchor().GetAnchorId() )
1844 eType
= OBJCNT_GROUPOBJ
;
1849 eType
= OBJCNT_SIMPLE
;
1853 ObjCntType
SwFEShell::GetObjCntType( const Point
&rPt
, SdrObject
*&rpObj
) const
1855 ObjCntType eType
= OBJCNT_NONE
;
1857 if( Imp()->HasDrawView() )
1859 SdrPageView
* pPView
;
1861 SwDrawView
*pDView
= const_cast<SwDrawView
*>(Imp()->GetDrawView());
1863 const auto nOld
= pDView
->GetHitTolerancePixel();
1864 // tolerance for Drawing-SS
1865 pDView
->SetHitTolerancePixel( pDView
->GetMarkHdlSizePixel()/2 );
1867 SdrObject
* pObj
= pDView
->PickObj(rPt
, pDView
->getHitTolLog(), pPView
, SdrSearchOptions::PICKMARKABLE
);
1871 eType
= GetObjCntType( *rpObj
);
1874 pDView
->SetHitTolerancePixel( nOld
);
1879 ObjCntType
SwFEShell::GetObjCntTypeOfSelection() const
1881 ObjCntType eType
= OBJCNT_NONE
;
1883 if( Imp()->HasDrawView() )
1885 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1886 for( size_t i
= 0, nE
= rMrkList
.GetMarkCount(); i
< nE
; ++i
)
1888 SdrObject
* pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
1891 ObjCntType eTmp
= GetObjCntType( *pObj
);
1896 else if( eTmp
!= eType
)
1898 eType
= OBJCNT_DONTCARE
;
1899 // once DontCare, always DontCare!
1907 void SwFEShell::ReplaceSdrObj( const OUString
& rGrfName
, const Graphic
* pGrf
)
1909 CurrShell
aCurr( this );
1911 const SdrMarkList
*pMrkList
;
1912 if( !(Imp()->HasDrawView() && 1 ==
1913 ( pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList())->GetMarkCount()) )
1916 SdrObject
* pObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
1918 SwFrameFormat
*pFormat
= FindFrameFormat( pObj
);
1920 // store attributes, then set the graphic
1921 SfxItemSet
aFrameSet( mxDoc
->GetAttrPool(),
1922 pFormat
->GetAttrSet().GetRanges() );
1923 aFrameSet
.Set( pFormat
->GetAttrSet() );
1925 // set size and position?
1926 if( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
1928 // then let's do it:
1929 const tools::Rectangle
&rBound
= pObj
->GetSnapRect();
1930 Point
aRelPos( pObj
->GetRelativePos() );
1932 const tools::Long nWidth
= rBound
.Right() - rBound
.Left();
1933 const tools::Long nHeight
= rBound
.Bottom() - rBound
.Top();
1934 aFrameSet
.Put( SwFormatFrameSize( SwFrameSize::Minimum
,
1935 std::max( nWidth
, tools::Long(MINFLY
) ),
1936 std::max( nHeight
, tools::Long(MINFLY
) )));
1938 if( SfxItemState::SET
!= aFrameSet
.GetItemState( RES_HORI_ORIENT
))
1939 aFrameSet
.Put( SwFormatHoriOrient( aRelPos
.getX(), text::HoriOrientation::NONE
, text::RelOrientation::FRAME
));
1941 if( SfxItemState::SET
!= aFrameSet
.GetItemState( RES_VERT_ORIENT
))
1942 aFrameSet
.Put( SwFormatVertOrient( aRelPos
.getY(), text::VertOrientation::NONE
, text::RelOrientation::FRAME
));
1951 // delete "Sdr-Object", insert the graphic instead
1954 GetDoc()->getIDocumentContentOperations().InsertGraphic(
1955 *GetCursor(), rGrfName
, u
""_ustr
, pGrf
, &aFrameSet
, nullptr, nullptr);
1961 static sal_uInt16
SwFormatGetPageNum(const SwFlyFrameFormat
* pFormat
)
1963 assert(pFormat
!= nullptr && "invalid argument");
1965 SwFlyFrame
* pFrame
= pFormat
->GetFrame();
1969 if (pFrame
!= nullptr)
1970 aResult
= pFrame
->GetPhyPageNum();
1972 aResult
= pFormat
->GetAnchor().GetPageNum();
1977 void SwFEShell::GetConnectableFrameFormats(SwFrameFormat
& rFormat
,
1978 std::u16string_view rReference
,
1980 std::vector
< OUString
> & aPrevPageVec
,
1981 std::vector
< OUString
> & aThisPageVec
,
1982 std::vector
< OUString
> & aNextPageVec
,
1983 std::vector
< OUString
> & aRestVec
)
1987 SwFormatChain rChain
= rFormat
.GetChain();
1988 SwFrameFormat
* pOldChainNext
= rChain
.GetNext();
1989 SwFrameFormat
* pOldChainPrev
= rChain
.GetPrev();
1992 mxDoc
->Unchain(rFormat
);
1995 mxDoc
->Unchain(*pOldChainPrev
);
1997 /* potential successors resp. predecessors */
1998 std::vector
<const SwFrameFormat
*> aTmpSpzArray
= mxDoc
->GetFlyFrameFormats(FLYCNTTYPE_FRM
, false);
2000 for (auto it
= aTmpSpzArray
.begin(); it
!= aTmpSpzArray
.end(); ++it
)
2003 pFormat is a potential successor of rFormat if it is chainable after
2006 pFormat is a potential predecessor of rFormat if rFormat is chainable
2010 SwChainRet nChainState
;
2013 nChainState
= mxDoc
->Chainable(rFormat
, **it
);
2015 nChainState
= mxDoc
->Chainable(**it
, rFormat
);
2017 if (nChainState
!= SwChainRet::OK
)
2020 std::erase(aTmpSpzArray
, nullptr);
2022 if (!aTmpSpzArray
.empty())
2024 aPrevPageVec
.clear();
2025 aThisPageVec
.clear();
2026 aNextPageVec
.clear();
2029 /* number of page rFormat resides on */
2030 sal_uInt16 nPageNum
= SwFormatGetPageNum(static_cast<SwFlyFrameFormat
*>(&rFormat
));
2032 for (const auto& rpFormat
: aTmpSpzArray
)
2034 const OUString aString
= rpFormat
->GetName();
2036 /* rFormat is not a valid successor or predecessor of
2038 if (aString
!= rReference
&& aString
!= rFormat
.GetName())
2041 SwFormatGetPageNum(static_cast<const SwFlyFrameFormat
*>(rpFormat
));
2043 if (nNum1
== nPageNum
-1)
2044 aPrevPageVec
.push_back(aString
);
2045 else if (nNum1
== nPageNum
)
2046 aThisPageVec
.push_back(aString
);
2047 else if (nNum1
== nPageNum
+ 1)
2048 aNextPageVec
.push_back(aString
);
2050 aRestVec
.push_back(aString
);
2057 mxDoc
->Chain(rFormat
, *pOldChainNext
);
2060 mxDoc
->Chain(*pOldChainPrev
, rFormat
);
2066 OUString
SwFEShell::GetObjTitle() const
2068 if ( Imp()->HasDrawView() )
2070 const SdrMarkList
*pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
2071 if ( pMrkList
->GetMarkCount() == 1 )
2073 const SdrObject
* pObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
2074 const SwFrameFormat
* pFormat
= FindFrameFormat( pObj
);
2075 if ( pFormat
->Which() == RES_FLYFRMFMT
)
2077 return static_cast<const SwFlyFrameFormat
*>(pFormat
)->GetObjTitle();
2079 return pObj
->GetTitle();
2086 void SwFEShell::SetObjTitle( const OUString
& rTitle
)
2088 if ( !Imp()->HasDrawView() )
2091 const SdrMarkList
*pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
2092 if ( pMrkList
->GetMarkCount() != 1 )
2095 SdrObject
* pObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
2096 SwFrameFormat
* pFormat
= FindFrameFormat( pObj
);
2097 if ( pFormat
->Which() == RES_FLYFRMFMT
)
2099 GetDoc()->SetFlyFrameTitle( dynamic_cast<SwFlyFrameFormat
&>(*pFormat
),
2104 pObj
->SetTitle( rTitle
);
2108 OUString
SwFEShell::GetObjDescription() const
2110 if ( Imp()->HasDrawView() )
2112 const SdrMarkList
*pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
2113 if ( pMrkList
->GetMarkCount() == 1 )
2115 const SdrObject
* pObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
2116 const SwFrameFormat
* pFormat
= FindFrameFormat( pObj
);
2117 if ( pFormat
->Which() == RES_FLYFRMFMT
)
2119 return dynamic_cast<const SwFlyFrameFormat
&>(*pFormat
).GetObjDescription();
2121 return pObj
->GetDescription();
2128 void SwFEShell::SetObjDescription( const OUString
& rDescription
)
2130 if ( !Imp()->HasDrawView() )
2133 const SdrMarkList
*pMrkList
= &Imp()->GetDrawView()->GetMarkedObjectList();
2134 if ( pMrkList
->GetMarkCount() != 1 )
2137 SdrObject
* pObj
= pMrkList
->GetMark( 0 )->GetMarkedSdrObj();
2138 SwFrameFormat
* pFormat
= FindFrameFormat( pObj
);
2139 if ( pFormat
->Which() == RES_FLYFRMFMT
)
2141 GetDoc()->SetFlyFrameDescription(dynamic_cast<SwFlyFrameFormat
&>(*pFormat
),
2146 pObj
->SetDescription( rDescription
);
2150 bool SwFEShell::IsObjDecorative() const
2152 if (!Imp()->HasDrawView())
2157 SdrMarkList
const& rMarkList(Imp()->GetDrawView()->GetMarkedObjectList());
2158 if (rMarkList
.GetMarkCount() != 1)
2163 SdrObject
const*const pObj(rMarkList
.GetMark(0)->GetMarkedSdrObj());
2164 SwFrameFormat
const*const pFormat(FindFrameFormat(pObj
));
2165 if (pFormat
->Which() == RES_FLYFRMFMT
)
2167 return dynamic_cast<const SwFlyFrameFormat
&>(*pFormat
).GetAttrSet().Get(RES_DECORATIVE
).GetValue();
2169 return pObj
->IsDecorative();
2172 void SwFEShell::SetObjDecorative(bool const isDecorative
)
2174 if (!Imp()->HasDrawView())
2179 SdrMarkList
const& rMarkList(Imp()->GetDrawView()->GetMarkedObjectList());
2180 if (rMarkList
.GetMarkCount() != 1)
2185 SdrObject
*const pObj(rMarkList
.GetMark(0)->GetMarkedSdrObj());
2186 SwFrameFormat
*const pFormat(FindFrameFormat(pObj
));
2187 if (pFormat
->Which() == RES_FLYFRMFMT
)
2189 GetDoc()->SetFlyFrameDecorative(dynamic_cast<SwFlyFrameFormat
&>(*pFormat
),
2194 pObj
->SetDecorative(isDecorative
);
2199 void SwFEShell::AlignFormulaToBaseline( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
2201 #if OSL_DEBUG_LEVEL > 0
2202 SvGlobalName
aCLSID( xObj
->getClassID() );
2203 const bool bStarMath
= ( SotExchange::IsMath( aCLSID
) != 0 );
2204 OSL_ENSURE( bStarMath
, "AlignFormulaToBaseline should only be called for Math objects" );
2210 SwFlyFrame
* pFly
= FindFlyFrame( xObj
);
2211 OSL_ENSURE( pFly
, "No fly frame!" );
2212 SwFrameFormat
* pFrameFormat
= pFly
? pFly
->GetFormat() : nullptr;
2214 // baseline to baseline alignment should only be applied to formulas anchored as char
2215 if ( !pFly
|| !pFrameFormat
|| RndStdIds::FLY_AS_CHAR
!= pFrameFormat
->GetAnchor().GetAnchorId() )
2218 // get baseline from Math object
2220 if( svt::EmbeddedObjectRef::TryRunningState( xObj
) )
2222 uno::Reference
< beans::XPropertySet
> xSet( xObj
->getComponent(), uno::UNO_QUERY
);
2227 aBaseline
= xSet
->getPropertyValue(u
"BaseLine"_ustr
);
2229 catch ( uno::Exception
& )
2231 OSL_FAIL( "Baseline could not be retrieved from Starmath!" );
2236 sal_Int32 nBaseline
= ::comphelper::getINT32(aBaseline
);
2237 nBaseline
= o3tl::toTwips( nBaseline
, o3tl::Length::mm100
);
2239 OSL_ENSURE( nBaseline
> 0, "Wrong value of Baseline while retrieving from Starmath!" );
2240 //nBaseline must be moved by aPrt position
2241 const SwFlyFrameFormat
*pFlyFrameFormat
= pFly
->GetFormat();
2242 OSL_ENSURE( pFlyFrameFormat
, "fly frame format missing!" );
2243 if ( pFlyFrameFormat
)
2244 nBaseline
+= pFlyFrameFormat
->GetLastFlyFramePrtRectPos().Y();
2246 const SwFormatVertOrient
&rVert
= pFrameFormat
->GetVertOrient();
2247 SwFormatVertOrient
aVert( rVert
);
2248 aVert
.SetPos( -nBaseline
);
2249 aVert
.SetVertOrient( css::text::VertOrientation::NONE
);
2251 pFrameFormat
->LockModify();
2252 pFrameFormat
->SetFormatAttr( aVert
);
2253 pFrameFormat
->UnlockModify();
2254 pFly
->InvalidatePos();
2258 void SwFEShell::AlignAllFormulasToBaseline()
2263 SwNodeIndex
aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
2264 while ( nullptr != (pStNd
= aIdx
.GetNode().GetStartNode()) )
2267 SwOLENode
*pOleNode
= aIdx
.GetNode().GetOLENode();
2270 const uno::Reference
< embed::XEmbeddedObject
> & xObj( pOleNode
->GetOLEObj().GetOleRef() );
2273 SvGlobalName
aCLSID( xObj
->getClassID() );
2274 if ( SotExchange::IsMath( aCLSID
) )
2275 AlignFormulaToBaseline( xObj
);
2279 aIdx
.Assign( *pStNd
->EndOfSectionNode(), + 1 );
2285 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */