android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / frmedt / fefly1.cxx
blob2fb646150d0efde74bef93a168772a07ae325c15
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <fmtanchr.hxx>
35 #include <fmtcntnt.hxx>
36 #include <fmtornt.hxx>
37 #include <fmturl.hxx>
38 #include <fmtfsize.hxx>
39 #include <fesh.hxx>
40 #include <rootfrm.hxx>
41 #include <pagefrm.hxx>
42 #include <cntfrm.hxx>
43 #include <txtfrm.hxx>
44 #include <viewimp.hxx>
45 #include <viscrs.hxx>
46 #include <doc.hxx>
47 #include <IDocumentDrawModelAccess.hxx>
48 #include <IDocumentUndoRedo.hxx>
49 #include <IDocumentState.hxx>
50 #include <IDocumentLayoutAccess.hxx>
51 #include <IDocumentRedlineAccess.hxx>
52 #include <redline.hxx>
53 #include <dview.hxx>
54 #include <dflyobj.hxx>
55 #include <dcontact.hxx>
56 #include <frmfmt.hxx>
57 #include <flyfrm.hxx>
58 #include <ndtxt.hxx>
59 #include <swtable.hxx>
60 #include <ndgrf.hxx>
61 #include <flyfrms.hxx>
62 #include <fldbas.hxx>
63 #include <fmtfld.hxx>
64 #include <swundo.hxx>
65 #include <txatbase.hxx>
66 #include <frame.hxx>
67 #include <notxtfrm.hxx>
68 #include <HandleAnchorNodeChg.hxx>
69 #include <frmatr.hxx>
70 #include <fmtsrnd.hxx>
71 #include <ndole.hxx>
72 #include <fefly.hxx>
73 #include <fmtcnct.hxx>
74 #include <frameformats.hxx>
75 #include <textboxhelper.hxx>
78 using namespace ::com::sun::star;
80 // Based on the request, changes to the specific layouts will be made, to
81 // fit to the format
82 static bool lcl_SetNewFlyPos( const SwNode& rNode, SwFormatAnchor& rAnchor,
83 const Point& rPt )
85 bool bRet = false;
86 const SwStartNode* pStNode = rNode.FindFlyStartNode();
87 if( pStNode )
89 SwPosition aPos( *pStNode );
90 rAnchor.SetAnchor( &aPos );
91 bRet = true;
93 else
95 const SwContentNode *pCntNd = rNode.GetContentNode();
96 std::pair<Point, bool> const tmp(rPt, false);
97 const SwContentFrame* pCFrame = pCntNd ? pCntNd->getLayoutFrame(
98 pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
99 nullptr, &tmp) : nullptr;
100 const SwPageFrame *pPg = pCFrame ? pCFrame->FindPageFrame() : nullptr;
102 rAnchor.SetPageNum( pPg ? pPg->GetPhyPageNum() : 1 );
103 rAnchor.SetType( RndStdIds::FLY_AT_PAGE );
105 return bRet;
108 static bool lcl_FindAnchorPos(
109 SwDoc& rDoc,
110 const Point& rPt,
111 const SwFrame& rFrame,
112 SfxItemSet& rSet )
114 bool bRet = true;
115 SwFormatAnchor aNewAnch( rSet.Get( RES_ANCHOR ) );
116 RndStdIds nNew = aNewAnch.GetAnchorId();
117 const SwFrame *pNewAnch;
119 //determine new anchor
120 Point aTmpPnt( rPt );
121 switch( nNew )
123 case RndStdIds::FLY_AS_CHAR: // also include this?
124 case RndStdIds::FLY_AT_PARA:
125 case RndStdIds::FLY_AT_CHAR: // LAYER_IMPL
127 // starting from the upper-left corner of the Fly,
128 // search nearest ContentFrame
129 const SwFrame* pFrame = rFrame.IsFlyFrame() ? static_cast<const SwFlyFrame&>(rFrame).GetAnchorFrame()
130 : &rFrame;
131 pNewAnch = ::FindAnchor( pFrame, aTmpPnt );
132 if( pNewAnch->IsProtected() )
134 bRet = false;
135 break;
137 SwPosition aPos( pNewAnch->IsTextFrame()
138 ? *static_cast<SwTextFrame const*>(pNewAnch)->GetTextNodeForParaProps()
139 : *static_cast<const SwNoTextFrame*>(pNewAnch)->GetNode() );
140 if ((RndStdIds::FLY_AT_CHAR == nNew) || (RndStdIds::FLY_AS_CHAR == nNew))
142 // textnode should be found, as only in those
143 // a content bound frame can be anchored
144 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
145 aTmpPnt.setX(aTmpPnt.getX() - 1); // do not land in the fly!
146 if( !pNewAnch->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState ) )
148 assert(pNewAnch->IsTextFrame()); // because AT_CHAR/AS_CHAR
149 SwTextFrame const*const pTextFrame(
150 static_cast<SwTextFrame const*>(pNewAnch));
151 if( pNewAnch->getFrameArea().Bottom() < aTmpPnt.Y() )
153 aPos = pTextFrame->MapViewToModelPos(TextFrameIndex(0));
155 else
157 aPos = pTextFrame->MapViewToModelPos(
158 TextFrameIndex(pTextFrame->GetText().getLength()));
161 else
163 if ( SwCursorShell::PosInsideInputField( aPos ) )
165 aPos.SetContent( SwCursorShell::StartOfInputFieldAtPos( aPos ) );
169 aNewAnch.SetAnchor( &aPos );
171 break;
173 case RndStdIds::FLY_AT_FLY: // LAYER_IMPL
175 // starting from the upper-left corner of the Fly
176 // search nearest SwFlyFrame
177 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
178 SwPosition aPos( rDoc.GetNodes() );
179 aTmpPnt.setX(aTmpPnt.getX() - 1); // do not land in the fly!
180 rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState );
181 pNewAnch = ::FindAnchor(
182 aPos.GetNode().GetContentNode()->getLayoutFrame(rFrame.getRootFrame(), nullptr, nullptr),
183 aTmpPnt )->FindFlyFrame();
185 if( pNewAnch && &rFrame != pNewAnch && !pNewAnch->IsProtected() )
187 aPos.Assign( *static_cast<const SwFlyFrame*>(pNewAnch)->GetFormat()->GetContent().
188 GetContentIdx() );
189 aNewAnch.SetAnchor( &aPos );
190 break;
194 nNew = RndStdIds::FLY_AT_PAGE;
195 aNewAnch.SetType( nNew );
196 [[fallthrough]];
198 case RndStdIds::FLY_AT_PAGE:
199 pNewAnch = rFrame.FindPageFrame();
200 aNewAnch.SetPageNum( pNewAnch->GetPhyPageNum() );
201 break;
203 default:
204 OSL_ENSURE( false, "Wrong Id for new anchor." );
207 rSet.Put( aNewAnch );
208 return bRet;
211 //! also used in unoframe.cxx
213 bool sw_ChkAndSetNewAnchor(
214 const SwFlyFrame& rFly,
215 SfxItemSet& rSet )
217 const SwFrameFormat& rFormat = *rFly.GetFormat();
218 const SwFormatAnchor &rOldAnch = rFormat.GetAnchor();
219 const RndStdIds nOld = rOldAnch.GetAnchorId();
221 RndStdIds nNew = rSet.Get( RES_ANCHOR ).GetAnchorId();
223 if( nOld == nNew )
224 return false;
226 SwDoc* pDoc = const_cast<SwDoc*>(rFormat.GetDoc());
228 #if OSL_DEBUG_LEVEL > 0
229 OSL_ENSURE( !(nNew == RndStdIds::FLY_AT_PAGE &&
230 (RndStdIds::FLY_AT_PARA==nOld || RndStdIds::FLY_AT_CHAR==nOld || RndStdIds::FLY_AS_CHAR==nOld ) &&
231 pDoc->IsInHeaderFooter( *rOldAnch.GetAnchorNode() )),
232 "forbidden anchor change in Head/Foot." );
233 #endif
235 return ::lcl_FindAnchorPos( *pDoc, rFly.getFrameArea().Pos(), rFly, rSet );
238 void SwFEShell::SelectFlyFrame( SwFlyFrame& rFrame )
240 CurrShell aCurr( this );
242 // The frame is new, thus select it.
243 // !! Always select the frame, if it's not selected.
244 // - it could be a new "old" one because the anchor was changed
245 // - "old" frames have had to be selected previously otherwise they could
246 // not have been changed
247 // The frames should not be selected by the document position, because
248 // it should have been selected!
249 SwViewShellImp *pImpl = Imp();
250 if( !GetWin() )
251 return;
253 OSL_ENSURE( rFrame.IsFlyFrame(), "SelectFlyFrame wants a Fly" );
255 // nothing to be done if the Fly already was selected
256 if (GetSelectedFlyFrame() == &rFrame)
257 return;
259 // assure the anchor is drawn
260 if( rFrame.IsFlyInContentFrame() && rFrame.GetAnchorFrame() )
261 rFrame.GetAnchorFrame()->SetCompletePaint();
263 if( pImpl->GetDrawView()->AreObjectsMarked() )
264 pImpl->GetDrawView()->UnmarkAll();
266 pImpl->GetDrawView()->MarkObj( rFrame.GetVirtDrawObj(),
267 pImpl->GetPageView() );
269 rFrame.SelectionHasChanged(this);
271 KillPams();
272 ClearMark();
273 SelFlyGrabCursor();
276 // Get selected fly
277 SwFlyFrame* SwFEShell::GetSelectedFlyFrame() const
279 if ( Imp()->HasDrawView() )
281 // A Fly is only accessible if it is selected
282 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
283 if( rMrkList.GetMarkCount() != 1 )
284 return nullptr;
286 SdrObject *pO = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
288 SwVirtFlyDrawObj *pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pO);
290 return pFlyObj ? pFlyObj->GetFlyFrame() : nullptr;
292 return nullptr;
295 // Get current fly in which the cursor is positioned
296 SwFlyFrame* SwFEShell::GetCurrFlyFrame(const bool bCalcFrame) const
298 SwContentFrame *pContent = GetCurrFrame(bCalcFrame);
299 return pContent ? pContent->FindFlyFrame() : nullptr;
302 // Get selected fly, but if none Get current fly in which the cursor is positioned
303 SwFlyFrame* SwFEShell::GetSelectedOrCurrFlyFrame() const
305 SwFlyFrame *pFly = GetSelectedFlyFrame();
306 if (pFly)
307 return pFly;
308 return GetCurrFlyFrame();
311 // Returns non-null pointer, if the current Fly could be anchored to another one (so it is inside)
312 const SwFrameFormat* SwFEShell::IsFlyInFly()
314 CurrShell aCurr( this );
316 if ( !Imp()->HasDrawView() )
317 return nullptr;
319 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
320 if ( !rMrkList.GetMarkCount() )
322 SwFlyFrame *pFly = GetCurrFlyFrame(false);
323 if (!pFly)
324 return nullptr;
325 return pFly->GetFormat();
327 else if ( rMrkList.GetMarkCount() != 1 ||
328 !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) )
329 return nullptr;
331 SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
333 SwFrameFormat *pFormat = FindFrameFormat( pObj );
334 if( pFormat && RndStdIds::FLY_AT_FLY == pFormat->GetAnchor().GetAnchorId() )
336 const SwFrame* pFly;
337 if (SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj *>(pObj))
339 pFly = pFlyObj->GetFlyFrame()->GetAnchorFrame();
341 else
343 pFly = static_cast<SwDrawContact*>(GetUserCall(pObj))->GetAnchorFrame(pObj);
346 OSL_ENSURE( pFly, "IsFlyInFly: Where's my anchor?" );
347 OSL_ENSURE( pFly->IsFlyFrame(), "IsFlyInFly: Funny anchor!" );
348 return static_cast<const SwFlyFrame*>(pFly)->GetFormat();
351 Point aTmpPos = pObj->GetCurrentBoundRect().TopLeft();
353 SwFrame *pTextFrame;
355 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
356 SwNodeIndex aSwNodeIndex( GetDoc()->GetNodes() );
357 SwPosition aPos( aSwNodeIndex );
358 Point aPoint( aTmpPos );
359 aPoint.setX(aPoint.getX() - 1); //do not land in the fly!!
360 GetLayout()->GetModelPositionForViewPoint( &aPos, aPoint, &aState );
361 // determine text frame by left-top-corner of object
362 SwContentNode *pNd = aPos.GetNode().GetContentNode();
363 std::pair<Point, bool> const tmp(aTmpPos, false);
364 pTextFrame = pNd ? pNd->getLayoutFrame(GetLayout(), nullptr, &tmp) : nullptr;
366 const SwFrame *pTmp = pTextFrame ? ::FindAnchor(pTextFrame, aTmpPos) : nullptr;
367 const SwFlyFrame *pFly = pTmp ? pTmp->FindFlyFrame() : nullptr;
368 if( pFly )
369 return pFly->GetFormat();
370 return nullptr;
373 void SwFEShell::SetFlyPos( const Point& rAbsPos )
375 CurrShell aCurr( this );
377 // Determine reference point in document coordinates
378 SwFlyFrame *pFly = GetCurrFlyFrame(false);
379 if (!pFly)
380 return;
382 //SwSaveHdl aSaveX( Imp() );
384 // Set an anchor starting from the absolute position for paragraph bound Flys
385 // Anchor and new RelPos will be calculated and set by the Fly
386 if ( pFly->IsFlyAtContentFrame() )
388 if(pFly->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame* >(pFly)->isTransformableSwFrame())
390 // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used),
391 // we need to correct the absolute position (rAbsPos) which was created in
392 // transformed coordinates to untransformed state
393 TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(pFly)->getTransformableSwFrame());
394 const SwRect aUntransformedFrameArea(pTransformableSwFrame->getUntransformedFrameArea());
395 const Point aNewAbsPos(
396 rAbsPos.X() + aUntransformedFrameArea.Left() - pFly->getFrameArea().Left(),
397 rAbsPos.Y() + aUntransformedFrameArea.Top() - pFly->getFrameArea().Top());
398 static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos(aNewAbsPos);
400 else
402 static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( rAbsPos );
405 else
407 const SwFrame *pAnch = pFly->GetAnchorFrame();
408 Point aOrient( pAnch->getFrameArea().Pos() );
410 if ( pFly->IsFlyInContentFrame() )
411 aOrient.setX(rAbsPos.getX());
413 // calculate RelPos.
414 aOrient.setX(rAbsPos.getX() - aOrient.getX());
415 aOrient.setY(rAbsPos.getY() - aOrient.getY());
416 pFly->ChgRelPos( aOrient );
418 CallChgLnk(); // call the AttrChangeNotify on the UI-side.
421 Point SwFEShell::FindAnchorPos( const Point& rAbsPos, bool bMoveIt )
423 Point aRet;
425 CurrShell aCurr( this );
427 if ( !Imp()->HasDrawView() )
428 return aRet;
430 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
431 if (rMrkList.GetMarkCount() != 1)
432 return aRet;
434 SdrObject* pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
436 if (!GetUserCall(pObj))
437 return aRet;
439 // #i28701#
440 SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
441 SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
442 const RndStdIds nAnchorId = rFormat.GetAnchor().GetAnchorId();
444 if ( RndStdIds::FLY_AS_CHAR == nAnchorId )
445 return aRet;
447 bool bFlyFrame = dynamic_cast<SwVirtFlyDrawObj *>(pObj) != nullptr;
449 bool bTextBox = false;
450 if (rFormat.Which() == RES_DRAWFRMFMT)
452 bTextBox = SwTextBoxHelper::isTextBox(&rFormat, RES_DRAWFRMFMT, pObj);
455 SwFlyFrame* pFly = nullptr;
456 const SwFrame* pFooterOrHeader = nullptr;
458 if( bFlyFrame )
460 // Calculate reference point in document coordinates
461 SwContentFrame *pContent = GetCurrFrame( false );
462 if( !pContent )
463 return aRet;
464 pFly = pContent->FindFlyFrame();
465 if ( !pFly )
466 return aRet;
467 const SwFrame* pOldAnch = pFly->GetAnchorFrame();
468 if( !pOldAnch )
469 return aRet;
470 if ( RndStdIds::FLY_AT_PAGE != nAnchorId )
472 pFooterOrHeader = pContent->FindFooterOrHeader();
475 else if (bTextBox)
477 auto pFlyFormat
478 = dynamic_cast<const SwFlyFrameFormat*>(SwTextBoxHelper::getOtherTextBoxFormat(
479 &rFormat, RES_DRAWFRMFMT, pObj));
480 if (pFlyFormat)
482 pFly = pFlyFormat->GetFrame();
486 // set <pFooterOrHeader> also for drawing
487 // objects, but not for control objects.
488 // Necessary for moving 'anchor symbol' at the user interface inside header/footer.
489 else if ( !::CheckControlLayer( pObj ) )
491 SwContentFrame *pContent = GetCurrFrame( false );
492 if( !pContent )
493 return aRet;
494 pFooterOrHeader = pContent->FindFooterOrHeader();
497 // Search nearest SwFlyFrame starting from the upper-left corner
498 // of the fly
499 SwContentFrame *pTextFrame = nullptr;
501 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
502 SwPosition aPos( GetDoc()->GetNodes().GetEndOfExtras() );
503 Point aTmpPnt( rAbsPos );
504 GetLayout()->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState );
505 if (aPos.GetNode() != GetDoc()->GetNodes().GetEndOfExtras()
506 && (nAnchorId != RndStdIds::FLY_AT_CHAR || !PosInsideInputField(aPos)))
508 SwContentNode* pCNode = aPos.GetNode().GetContentNode();
509 assert(pCNode);
510 pTextFrame = pCNode->getLayoutFrame(GetLayout(), &aPos, nullptr);
513 const SwFrame *pNewAnch = nullptr;
514 if( pTextFrame != nullptr )
516 if ( RndStdIds::FLY_AT_PAGE == nAnchorId )
518 pNewAnch = pTextFrame->FindPageFrame();
520 else
522 pNewAnch = ::FindAnchor( pTextFrame, rAbsPos );
524 if( RndStdIds::FLY_AT_FLY == nAnchorId ) // LAYER_IMPL
526 pNewAnch = pNewAnch->FindFlyFrame();
531 if( pNewAnch && !pNewAnch->IsProtected() )
533 const SwFlyFrame* pCheck = (bFlyFrame || bTextBox) ? pNewAnch->FindFlyFrame() : nullptr;
534 // If we land inside the frame, make sure
535 // that the frame does not land inside its own content
536 while( pCheck )
538 if( pCheck == pFly )
539 break;
540 const SwFrame *pTmp = pCheck->GetAnchorFrame();
541 pCheck = pTmp ? pTmp->FindFlyFrame() : nullptr;
544 // Do not switch from header/footer to another area,
545 // do not switch to a header/footer
546 if( !pCheck &&
547 pFooterOrHeader == pNewAnch->FindFooterOrHeader() )
549 aRet = pNewAnch->GetFrameAnchorPos( ::HasWrap( pObj ) );
551 if ( bMoveIt || (nAnchorId == RndStdIds::FLY_AT_CHAR) )
553 SwFormatAnchor aAnch( rFormat.GetAnchor() );
554 switch ( nAnchorId )
556 case RndStdIds::FLY_AT_PARA:
558 SwPosition pos(pTextFrame->IsTextFrame()
559 ? *static_cast<SwTextFrame const*>(pTextFrame)->GetTextNodeForParaProps()
560 : *static_cast<const SwNoTextFrame*>(pTextFrame)->GetNode());
561 aAnch.SetAnchor( &pos );
562 break;
564 case RndStdIds::FLY_AT_PAGE:
566 aAnch.SetPageNum( static_cast<const SwPageFrame*>(pNewAnch)->
567 GetPhyPageNum() );
568 break;
571 case RndStdIds::FLY_AT_FLY:
573 SwPosition aPos( *static_cast<const SwFlyFrame*>(pNewAnch)->GetFormat()->
574 GetContent().GetContentIdx() );
575 aAnch.SetAnchor( &aPos );
576 break;
579 case RndStdIds::FLY_AT_CHAR:
581 SwPosition pos = *aAnch.GetContentAnchor();
582 Point aTmpPnt( rAbsPos );
583 if( pTextFrame->GetModelPositionForViewPoint( &pos, aTmpPnt ) )
585 SwRect aTmpRect;
586 pTextFrame->GetCharRect( aTmpRect, pos );
587 aRet = aTmpRect.Pos();
589 else
591 pos = static_cast<SwTextFrame const*>(pTextFrame)->MapViewToModelPos(TextFrameIndex(0));
593 aAnch.SetAnchor( &pos );
594 break;
596 default:
597 break;
601 if( bMoveIt )
603 StartAllAction();
604 // --> handle change of anchor node:
605 // if count of the anchor frame also change, the fly frames have to be
606 // re-created. Thus, delete all fly frames except the <this> before the
607 // anchor attribute is change and re-create them afterwards.
609 std::unique_ptr<SwHandleAnchorNodeChg> pHandleAnchorNodeChg;
610 SwFlyFrameFormat* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat*>(&rFormat) );
611 if ( pFlyFrameFormat )
613 pHandleAnchorNodeChg.reset(
614 new SwHandleAnchorNodeChg( *pFlyFrameFormat, aAnch ));
616 rFormat.GetDoc()->SetAttr( aAnch, rFormat );
617 if (SwTextBoxHelper::getOtherTextBoxFormat(&rFormat, RES_DRAWFRMFMT,
618 pObj))
620 if (pObj->getChildrenOfSdrObject())
622 for (size_t i = 0;
623 i < pObj->getChildrenOfSdrObject()->GetObjCount(); ++i)
624 SwTextBoxHelper::changeAnchor(
625 &rFormat, pObj->getChildrenOfSdrObject()->GetObj(i));
627 else
628 SwTextBoxHelper::syncFlyFrameAttr(
629 rFormat, rFormat.GetAttrSet(), pObj);
632 // #i28701# - no call of method
633 // <CheckCharRectAndTopOfLine()> for to-character anchored
634 // Writer fly frame needed. This method call can cause a
635 // format of the anchor frame, which is no longer intended.
636 // Instead clear the anchor character rectangle and
637 // the top of line values for all to-character anchored objects.
638 pAnchoredObj->ClearCharRectAndTopOfLine();
639 EndAllAction();
643 SwRect aTmpRect( aRet, rAbsPos );
644 if( aTmpRect.HasArea() )
645 MakeVisible( aTmpRect );
646 #if OSL_DEBUG_LEVEL > 0
647 //TODO: That doesn't seem to be intended
648 if( COL_TRANSPARENT != GetOut()->GetLineColor() )
650 OSL_FAIL( "Hey, Joe: Where's my Null Pen?" );
651 GetOut()->SetLineColor( COL_TRANSPARENT );
653 #endif
657 return aRet;
660 const SwFrameFormat *SwFEShell::NewFlyFrame( const SfxItemSet& rSet, bool bAnchValid,
661 SwFrameFormat *pParent )
663 CurrShell aCurr( this );
664 StartAllAction();
666 SwPaM* pCursor = GetCursor();
667 const Point aPt( GetCursorDocPos() );
669 SwSelBoxes aBoxes;
670 bool bMoveContent = true;
671 if( IsTableMode() )
673 GetTableSel( *this, aBoxes );
674 if( !aBoxes.empty() )
676 // Cursor should be removed from the removal area.
677 // Always put it after/on the table; via the
678 // document position they will be set to the old
679 // position
680 ParkCursor( *aBoxes[0]->GetSttNd() );
682 // #i127787# pCurrentCursor will be deleted in ParkCursor,
683 // we better get the current pCurrentCursor instead of working with the
684 // deleted one:
685 pCursor = GetCursor();
687 else
688 bMoveContent = false;
690 else if( !pCursor->HasMark() && !pCursor->IsMultiSelection() )
691 bMoveContent = false;
693 const SwPosition& rPos = *pCursor->Start();
695 SwFormatAnchor& rAnch = const_cast<SwFormatAnchor&>(rSet.Get( RES_ANCHOR ));
696 RndStdIds eRndId = rAnch.GetAnchorId();
697 switch( eRndId )
699 case RndStdIds::FLY_AT_PAGE:
700 if( !rAnch.GetPageNum() ) //HotFix: Bug in UpdateByExample
701 rAnch.SetPageNum( 1 );
702 break;
704 case RndStdIds::FLY_AT_FLY:
705 case RndStdIds::FLY_AT_PARA:
706 case RndStdIds::FLY_AT_CHAR:
707 case RndStdIds::FLY_AS_CHAR:
708 if( !bAnchValid )
710 if( RndStdIds::FLY_AT_FLY != eRndId )
712 rAnch.SetAnchor( &rPos );
714 else if( lcl_SetNewFlyPos( rPos.GetNode(), rAnch, aPt ) )
716 eRndId = RndStdIds::FLY_AT_PAGE;
719 break;
721 default:
722 OSL_ENSURE( false, "What is the purpose of this Fly?" );
723 break;
726 SwFlyFrameFormat *pRet;
727 if( bMoveContent )
729 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSLAYFMT, nullptr );
730 std::unique_ptr<SwFormatAnchor> pOldAnchor;
731 bool bHOriChgd = false, bVOriChgd = false;
732 std::shared_ptr<SwFormatVertOrient> aOldV;
733 std::shared_ptr<SwFormatHoriOrient> aOldH;
735 if ( RndStdIds::FLY_AT_PAGE != eRndId )
737 // First as with page link. Paragraph/character link on if
738 // everything was shifted. Then the position is valid!
739 // JP 13.05.98: if necessary also convert the horizontal/vertical
740 // orientation, to prevent correction during re-anchoring
741 pOldAnchor.reset(new SwFormatAnchor( rAnch ));
742 const_cast<SfxItemSet&>(rSet).Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE, 1 ) );
744 const SwFormatHoriOrient* pHoriOrientItem;
745 if( (pHoriOrientItem = rSet.GetItemIfSet( RES_HORI_ORIENT, false ))
746 && text::HoriOrientation::NONE == pHoriOrientItem->GetHoriOrient() )
748 bHOriChgd = true;
749 aOldH.reset(pHoriOrientItem->Clone());
750 const_cast<SfxItemSet&>(rSet).Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT ) );
752 const SwFormatVertOrient* pVertOrientItem;
753 if( (pVertOrientItem = rSet.GetItemIfSet( RES_VERT_ORIENT, false ))
754 && text::VertOrientation::NONE == pVertOrientItem->GetVertOrient() )
756 bVOriChgd = true;
757 aOldV.reset(pVertOrientItem->Clone());
758 const_cast<SfxItemSet&>(rSet).Put( SwFormatVertOrient( 0, text::VertOrientation::TOP ) );
762 pRet = GetDoc()->MakeFlyAndMove( *pCursor, rSet, &aBoxes, pParent );
764 KillPams();
766 if( pOldAnchor )
768 if( pRet )
770 // calculate new position
771 // JP 24.03.97: also go via page links
772 // anchor should not lie in the shifted area
773 pRet->DelFrames();
775 const SwFrame* pAnch = ::FindAnchor( GetLayout(), aPt );
776 SwPosition aPos( pAnch->IsTextFrame()
777 ? *static_cast<SwTextFrame const*>(pAnch)->GetTextNodeForParaProps()
778 : *static_cast<const SwNoTextFrame*>(pAnch)->GetNode() );
780 if ( RndStdIds::FLY_AS_CHAR == eRndId )
782 assert(pAnch->IsTextFrame());
783 aPos = static_cast<SwTextFrame const*>(pAnch)->MapViewToModelPos(TextFrameIndex(0));
785 pOldAnchor->SetAnchor( &aPos );
787 // shifting of table selection is not Undo-capable. therefore
788 // changing the anchors should not be recorded
789 bool const bDoesUndo =
790 GetDoc()->GetIDocumentUndoRedo().DoesUndo();
791 SwUndoId nLastUndoId(SwUndoId::EMPTY);
792 if (bDoesUndo &&
793 GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(nullptr,
794 & nLastUndoId))
796 if (SwUndoId::INSLAYFMT == nLastUndoId)
798 GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
802 const_cast<SfxItemSet&>(rSet).Put( std::move(pOldAnchor) );
804 if( bHOriChgd )
805 const_cast<SfxItemSet&>(rSet).Put( *aOldH );
806 if( bVOriChgd )
807 const_cast<SfxItemSet&>(rSet).Put( *aOldV );
809 GetDoc()->SetFlyFrameAttr( *pRet, const_cast<SfxItemSet&>(rSet) );
810 GetDoc()->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
813 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSLAYFMT, nullptr );
815 else
816 /* If called from a shell try to propagate an
817 existing adjust item from rPos to the content node of the
818 new frame. */
819 pRet = GetDoc()->MakeFlySection( eRndId, &rPos, &rSet, pParent, true );
821 if( pRet )
823 SwFlyFrame* pFrame = pRet->GetFrame( &aPt );
824 if( pFrame )
825 SelectFlyFrame( *pFrame );
826 else
828 GetLayout()->SetAssertFlyPages();
829 pRet = nullptr;
832 EndAllActionAndCall();
834 return pRet;
837 void SwFEShell::Insert( const OUString& rGrfName, const OUString& rFltName,
838 const Graphic* pGraphic,
839 const SfxItemSet* pFlyAttrSet )
841 SwFlyFrameFormat* pFormat = nullptr;
842 CurrShell aCurr( this );
843 StartAllAction();
844 SwShellCursor *pStartCursor = dynamic_cast<SwShellCursor*>(GetCursor());
845 SwShellCursor *pCursor = pStartCursor;
848 if (!pCursor)
849 break;
851 // Has the anchor not been set or been set incompletely?
852 if( pFlyAttrSet )
854 if( const SwFormatAnchor* pItem = pFlyAttrSet->GetItemIfSet( RES_ANCHOR, false ) )
856 SwFormatAnchor* pAnchor = const_cast<SwFormatAnchor*>(pItem);
857 switch( pAnchor->GetAnchorId())
859 case RndStdIds::FLY_AT_PARA:
860 case RndStdIds::FLY_AT_CHAR: // LAYER_IMPL
861 case RndStdIds::FLY_AS_CHAR:
862 if( !pAnchor->GetAnchorNode() )
864 pAnchor->SetAnchor( pCursor->GetPoint() );
866 break;
867 case RndStdIds::FLY_AT_FLY:
868 if( !pAnchor->GetAnchorNode() )
870 lcl_SetNewFlyPos( pCursor->GetPointNode(),
871 *pAnchor, GetCursorDocPos() );
873 break;
874 case RndStdIds::FLY_AT_PAGE:
875 if( !pAnchor->GetPageNum() )
877 pAnchor->SetPageNum( pCursor->GetPageNum(
878 true, &pCursor->GetPtPos() ) );
880 break;
881 default :
882 break;
886 pFormat = GetDoc()->getIDocumentContentOperations().InsertGraphic(
887 *pCursor, rGrfName,
888 rFltName, pGraphic,
889 pFlyAttrSet,
890 nullptr, nullptr );
891 OSL_ENSURE(pFormat, "IDocumentContentOperations::InsertGraphic failed.");
893 pCursor = pCursor->GetNext();
894 } while( pCursor != pStartCursor );
896 EndAllAction();
898 if( !pFormat )
899 return;
901 const Point aPt( GetCursorDocPos() );
902 SwFlyFrame* pFrame = pFormat->GetFrame( &aPt );
904 if( pFrame )
906 // add a redline to the anchor point at tracked insertion of picture
907 if ( IsRedlineOn() )
909 const SwPosition & rPos(*pFormat->GetAnchor().GetContentAnchor());
910 SwPaM aPaM(rPos.GetNode(), rPos.GetContentIndex(),
911 rPos.GetNode(), rPos.GetContentIndex() + 1);
912 GetDoc()->getIDocumentRedlineAccess().AppendRedline(
913 new SwRangeRedline( RedlineType::Insert, aPaM ), true);
916 // fdo#36681: Invalidate the content and layout to refresh
917 // the picture anchoring properly
918 SwPageFrame* pPageFrame = pFrame->FindPageFrameOfAnchor();
919 pPageFrame->InvalidateFlyLayout();
920 pPageFrame->InvalidateContent();
922 SelectFlyFrame( *pFrame );
924 else
925 GetLayout()->SetAssertFlyPages();
928 SwFlyFrameFormat* SwFEShell::InsertObject( const svt::EmbeddedObjectRef& xObj,
929 SfxItemSet* pFlyAttrSet )
931 SwFlyFrameFormat* pFormat = nullptr;
932 CurrShell aCurr( this );
933 StartAllAction();
935 for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
937 pFormat = GetDoc()->getIDocumentContentOperations().InsertEmbObject(
938 rPaM, xObj, pFlyAttrSet );
939 OSL_ENSURE(pFormat, "IDocumentContentOperations::InsertEmbObject failed.");
942 EndAllAction();
944 if( pFormat )
946 const Point aPt( GetCursorDocPos() );
947 SwFlyFrame* pFrame = pFormat->GetFrame( &aPt );
949 if( pFrame )
950 SelectFlyFrame( *pFrame );
951 else
952 GetLayout()->SetAssertFlyPages();
955 return pFormat;
958 void SwFEShell::InsertDrawObj( SdrObject& rDrawObj,
959 const Point& rInsertPosition )
961 CurrShell aCurr( this );
963 SfxItemSet rFlyAttrSet( GetDoc()->GetAttrPool(), aFrameFormatSetRange );
964 rFlyAttrSet.Put( SwFormatAnchor( RndStdIds::FLY_AT_PARA ));
965 // #i89920#
966 rFlyAttrSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
967 rDrawObj.SetLayer( getIDocumentDrawModelAccess().GetHeavenId() );
969 // find anchor position
970 SwPaM aPam( mxDoc->GetNodes() );
972 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
973 Point aTmpPt( rInsertPosition );
974 GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmpPt, &aState );
975 const SwFrame* pFrame = aPam.GetPointContentNode()->getLayoutFrame(GetLayout(), nullptr, nullptr);
976 const Point aRelPos( rInsertPosition.X() - pFrame->getFrameArea().Left(),
977 rInsertPosition.Y() - pFrame->getFrameArea().Top() );
978 rDrawObj.SetRelativePos( aRelPos );
979 ::lcl_FindAnchorPos( *GetDoc(), rInsertPosition, *pFrame, rFlyAttrSet );
981 // insert drawing object into the document creating a new <SwDrawFrameFormat> instance
982 SwDrawFrameFormat* pFormat = GetDoc()->getIDocumentContentOperations().InsertDrawObj( aPam, rDrawObj, rFlyAttrSet );
984 // move object to visible layer
985 SwContact* pContact = static_cast<SwContact*>(rDrawObj.GetUserCall());
986 if ( pContact )
988 pContact->MoveObjToVisibleLayer( &rDrawObj );
991 if (pFormat)
993 pFormat->SetFormatName(rDrawObj.GetName());
994 // select drawing object
995 Imp()->GetDrawView()->MarkObj( &rDrawObj, Imp()->GetPageView() );
997 else
999 GetLayout()->SetAssertFlyPages();
1003 void SwFEShell::GetPageObjs( std::vector<SwFrameFormat*>& rFillArr )
1005 rFillArr.clear();
1007 for(sw::SpzFrameFormat* pFormat : *mxDoc->GetSpzFrameFormats() )
1009 if (RndStdIds::FLY_AT_PAGE == pFormat->GetAnchor().GetAnchorId())
1011 rFillArr.push_back( pFormat );
1016 void SwFEShell::SetPageObjsNewPage( std::vector<SwFrameFormat*>& rFillArr )
1018 if( rFillArr.empty() )
1019 return;
1021 StartAllAction();
1022 StartUndo();
1024 SwRootFrame* pTmpRootFrame = GetLayout();
1025 sal_uInt16 nMaxPage = pTmpRootFrame->GetPageNum();
1026 bool bTmpAssert = false;
1027 for( auto pFormat : rFillArr )
1029 if (mxDoc->GetSpzFrameFormats()->IsAlive(static_cast<sw::SpzFrameFormat*>(pFormat)))
1031 // FlyFormat is still valid, therefore process
1033 SwFormatAnchor aNewAnchor( pFormat->GetAnchor() );
1034 if (RndStdIds::FLY_AT_PAGE != aNewAnchor.GetAnchorId())
1035 // Anchor has been changed, therefore: do not change!
1036 continue;
1037 sal_uInt16 nNewPage = aNewAnchor.GetPageNum() + 1;
1038 if (nNewPage > nMaxPage)
1040 if ( RES_DRAWFRMFMT == pFormat->Which() )
1041 pFormat->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PAGE_OUT_OF_BOUNDS));
1042 else
1043 pFormat->DelFrames();
1044 bTmpAssert = true;
1046 aNewAnchor.SetPageNum(nNewPage);
1047 mxDoc->SetAttr( aNewAnchor, *pFormat );
1051 if( bTmpAssert )
1052 pTmpRootFrame->SetAssertFlyPages();
1054 EndUndo();
1055 EndAllAction();
1058 // All attributes in the "baskets" will be filled with the attributes of the
1059 // current FlyFrames. Attributes which cannot be filled due to being at the
1060 // wrong place or which are ambiguous (multiple selections) will be removed.
1061 bool SwFEShell::GetFlyFrameAttr( SfxItemSet &rSet ) const
1063 SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame();
1064 if (!pFly)
1066 OSL_ENSURE( false, "GetFlyFrameAttr, no Fly selected." );
1067 return false;
1070 CurrShell aCurr( const_cast<SwFEShell*>(this) );
1072 if( !rSet.Set( pFly->GetFormat()->GetAttrSet() ) )
1073 return false;
1075 // now examine all attributes. Remove forbidden attributes, then
1076 // get all remaining attributes and enter them
1078 if( const SwFormatAnchor* pAnchor = rSet.GetItemIfSet( RES_ANCHOR, false ) )
1080 RndStdIds eType = pAnchor->GetAnchorId();
1082 if ( RndStdIds::FLY_AT_PAGE != eType )
1084 // OD 12.11.2003 #i22341# - content anchor of anchor item is needed.
1085 // Thus, don't overwrite anchor item by default constructed anchor item.
1086 if ( RndStdIds::FLY_AS_CHAR == eType )
1088 rSet.ClearItem( RES_OPAQUE );
1089 rSet.ClearItem( RES_SURROUND );
1093 rSet.SetParent( pFly->GetFormat()->GetAttrSet().GetParent() );
1094 // attributes must be removed
1095 rSet.ClearItem( RES_FILL_ORDER );
1096 rSet.ClearItem( RES_CNTNT );
1097 //MA: remove first (Template by example etc.)
1098 rSet.ClearItem( RES_CHAIN );
1099 return true;
1102 // Attributes of the current fly will change.
1103 bool SwFEShell::SetFlyFrameAttr( SfxItemSet& rSet )
1105 CurrShell aCurr( this );
1106 bool bRet = false;
1108 if( rSet.Count() )
1110 SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame();
1111 OSL_ENSURE(pFly, "SetFlyFrameAttr, no Fly selected.");
1112 if (pFly)
1114 StartAllAction();
1115 const Point aPt( pFly->getFrameArea().Pos() );
1117 if( SfxItemState::SET == rSet.GetItemState( RES_ANCHOR, false ))
1118 sw_ChkAndSetNewAnchor( *pFly, rSet );
1119 SwFlyFrameFormat* pFlyFormat = pFly->GetFormat();
1121 if( GetDoc()->SetFlyFrameAttr( *pFlyFormat, rSet ))
1123 bRet = true;
1124 SwFlyFrame* pFrame = pFlyFormat->GetFrame( &aPt );
1125 if( pFrame )
1126 SelectFlyFrame( *pFrame );
1127 else
1128 GetLayout()->SetAssertFlyPages();
1131 EndAllActionAndCall();
1134 return bRet;
1137 SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> SwFEShell::makeItemSetFromFormatAnchor(SfxItemPool& rPool, const SwFormatAnchor &rAnchor)
1139 // The set also includes VERT/HORI_ORIENT, because the align
1140 // shall be changed in FEShell::SetFlyFrameAttr/SetFlyFrameAnchor,
1141 // possibly as a result of the anchor change.
1142 SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> aSet(rPool);
1143 aSet.Put(rAnchor);
1144 return aSet;
1147 bool SwFEShell::SetDrawingAttr( SfxItemSet& rSet )
1149 bool bRet = false;
1150 CurrShell aCurr( this );
1151 if ( !rSet.Count() ||
1152 !Imp()->HasDrawView() )
1153 return bRet;
1155 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1156 if ( rMrkList.GetMarkCount() != 1 )
1157 return bRet;
1159 StartUndo();
1160 SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
1161 SwFrameFormat *pFormat = FindFrameFormat( pObj );
1162 StartAllAction();
1163 if( SfxItemState::SET == rSet.GetItemState( RES_ANCHOR, false ))
1165 RndStdIds nNew = rSet.Get( RES_ANCHOR ).GetAnchorId();
1166 if ( nNew != pFormat->GetAnchor().GetAnchorId() )
1168 ChgAnchor( nNew );
1169 // #i26791# - clear anchor attribute in item set,
1170 // because method <ChgAnchor(..)> takes care of it.
1171 rSet.ClearItem( RES_ANCHOR );
1175 if( GetDoc()->SetFlyFrameAttr( *pFormat, rSet ))
1177 bRet = true;
1178 SelectObj( Point(), 0, pObj );
1180 EndAllActionAndCall();
1181 EndUndo();
1182 return bRet;
1185 // Reset attributes contained in the set.
1186 void SwFEShell::ResetFlyFrameAttr( const SfxItemSet* pSet )
1188 CurrShell aCurr( this );
1190 SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame();
1191 OSL_ENSURE( pFly, "SetFlyFrameAttr, no Fly selected." );
1192 if( !pFly )
1193 return;
1195 StartAllAction();
1197 SfxItemIter aIter( *pSet );
1198 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
1200 if( !IsInvalidItem( pItem ) )
1202 sal_uInt16 nWhich = pItem->Which();
1203 if( RES_ANCHOR != nWhich && RES_CHAIN != nWhich && RES_CNTNT != nWhich )
1204 pFly->GetFormat()->ResetFormatAttr( nWhich );
1208 EndAllActionAndCall();
1209 GetDoc()->getIDocumentState().SetModified();
1212 // Returns frame-format if frame, otherwise 0
1213 SwFrameFormat* SwFEShell::GetSelectedFrameFormat() const
1215 SwFrameFormat* pRet = nullptr;
1216 SwLayoutFrame *pFly = GetSelectedFlyFrame();
1217 if( pFly && ( pRet = static_cast<SwFrameFormat*>(pFly->GetFormat()->DerivedFrom()) ) ==
1218 GetDoc()->GetDfltFrameFormat() )
1219 pRet = nullptr;
1220 return pRet;
1223 void SwFEShell::SetFrameFormat( SwFrameFormat *pNewFormat, bool bKeepOrient, Point const * pDocPos )
1225 SwFlyFrame *pFly = nullptr;
1226 if(pDocPos)
1228 const SwFrameFormat* pFormat = GetFormatFromObj( *pDocPos );
1230 if (const SwFlyFrameFormat* pFlyFormat = dynamic_cast<const SwFlyFrameFormat*>(pFormat))
1231 pFly = pFlyFormat->GetFrame();
1233 else
1234 pFly = GetSelectedFlyFrame();
1235 OSL_ENSURE( pFly, "SetFrameFormat: no frame" );
1236 if( !pFly )
1237 return;
1239 StartAllAction();
1240 CurrShell aCurr( this );
1242 SwFlyFrameFormat* pFlyFormat = pFly->GetFormat();
1243 const Point aPt( pFly->getFrameArea().Pos() );
1245 std::optional<SfxItemSet> oSet;
1246 const SfxPoolItem* pItem;
1247 if( SfxItemState::SET == pNewFormat->GetItemState( RES_ANCHOR, false, &pItem ))
1249 oSet.emplace( GetDoc()->GetAttrPool(), aFrameFormatSetRange );
1250 oSet->Put( *pItem );
1251 if( !sw_ChkAndSetNewAnchor( *pFly, *oSet ))
1253 oSet.reset();
1257 if( GetDoc()->SetFrameFormatToFly( *pFlyFormat, *pNewFormat, oSet ? &*oSet : nullptr, bKeepOrient ))
1259 SwFlyFrame* pFrame = pFlyFormat->GetFrame( &aPt );
1260 if( pFrame )
1261 SelectFlyFrame( *pFrame );
1262 else
1263 GetLayout()->SetAssertFlyPages();
1265 oSet.reset();
1267 EndAllActionAndCall();
1270 const SwFrameFormat* SwFEShell::GetFlyFrameFormat() const
1272 const SwFlyFrame* pFly = GetSelectedOrCurrFlyFrame();
1273 if (pFly)
1274 return pFly->GetFormat();
1275 return nullptr;
1278 SwFrameFormat* SwFEShell::GetFlyFrameFormat()
1280 SwFlyFrame* pFly = GetSelectedOrCurrFlyFrame();
1281 if (pFly)
1282 return pFly->GetFormat();
1283 return nullptr;
1286 SwRect SwFEShell::GetFlyRect() const
1288 SwFlyFrame *pFly = GetCurrFlyFrame(false);
1289 if (!pFly)
1291 SwRect aRect;
1292 return aRect;
1294 else
1295 return pFly->getFrameArea();
1298 SwRect SwFEShell::GetObjRect() const
1300 if( Imp()->HasDrawView() )
1301 return SwRect(Imp()->GetDrawView()->GetAllMarkedRect());
1302 else
1304 SwRect aRect;
1305 return aRect;
1309 void SwFEShell::SetObjRect( const SwRect& rRect )
1311 if ( Imp()->HasDrawView() )
1313 Imp()->GetDrawView()->SetAllMarkedRect( rRect.SVRect() );
1314 CallChgLnk(); // call AttrChangeNotify on the UI-side.
1318 Size SwFEShell::RequestObjectResize( const SwRect &rRect, const uno::Reference < embed::XEmbeddedObject >& xObj )
1320 Size aResult;
1322 SwFlyFrame *pFly = FindFlyFrame( xObj );
1323 if ( !pFly )
1325 aResult = rRect.SSize();
1326 return aResult;
1329 aResult = pFly->getFramePrintArea().SSize();
1331 bool bPosProt = pFly->GetFormat()->GetProtect().IsPosProtected();
1332 bool bSizeProt = pFly->GetFormat()->GetProtect().IsSizeProtected();
1334 StartAllAction();
1336 // MA we do not allow to clip the Fly, as the OLE server can
1337 // request various wishes. Clipping is done via the formatting.
1338 // Correct display is done by scaling.
1339 // Scaling is done by SwNoTextFrame::Format by calling
1340 // SwWrtShell::CalcAndSetScale()
1341 if ( rRect.SSize() != pFly->getFramePrintArea().SSize() && !bSizeProt )
1343 Size aSz( rRect.SSize() );
1345 //JP 28.02.2001: Task 74707 - ask for fly in fly with automatic size
1347 const SwFrame* pAnchor;
1348 const SwFormatFrameSize& rFrameSz = pFly->GetFormat()->GetFrameSize();
1349 if (m_bCheckForOLEInCaption &&
1350 0 != rFrameSz.GetWidthPercent() &&
1351 nullptr != (pAnchor = pFly->GetAnchorFrame()) &&
1352 pAnchor->IsTextFrame() &&
1353 !pAnchor->GetNext() && !pAnchor->GetPrev() &&
1354 pAnchor->GetUpper()->IsFlyFrame())
1356 // search for a sequence field:
1357 sw::MergedAttrIter iter(*static_cast<SwTextFrame const*>(pAnchor));
1358 for (SwTextAttr const* pHint = iter.NextAttr(); pHint; pHint = iter.NextAttr())
1360 const SfxPoolItem* pItem = &pHint->GetAttr();
1361 if( RES_TXTATR_FIELD == pItem->Which()
1362 && SwFieldTypesEnum::Sequence == static_cast<const SwFormatField*>(pItem)->GetField()->GetTypeId() )
1364 // sequence field found
1365 SwFlyFrame* pChgFly = const_cast<SwFlyFrame*>(static_cast<const SwFlyFrame*>(pAnchor->GetUpper()));
1366 // calculate the changed size:
1367 // width must change, height can change
1368 Size aNewSz( aSz.Width() + pChgFly->getFrameArea().Width() -
1369 pFly->getFramePrintArea().Width(), aSz.Height() );
1371 SwFrameFormat *pFormat = pChgFly->GetFormat();
1372 SwFormatFrameSize aFrameSz( pFormat->GetFrameSize() );
1373 aFrameSz.SetWidth( aNewSz.Width() );
1374 if( SwFrameSize::Minimum != aFrameSz.GetHeightSizeType() )
1376 aNewSz.AdjustHeight(pChgFly->getFrameArea().Height() -
1377 pFly->getFramePrintArea().Height() );
1378 if( std::abs( aNewSz.Height() - pChgFly->getFrameArea().Height()) > 1 )
1379 aFrameSz.SetHeight( aNewSz.Height() );
1381 // via Doc for the Undo!
1382 pFormat->GetDoc()->SetAttr( aFrameSz, *pFormat );
1383 break;
1388 // set the new Size at the fly themself
1389 if ( !pFly->getFramePrintArea().IsEmpty() )
1391 aSz.AdjustWidth(pFly->getFrameArea().Width() - pFly->getFramePrintArea().Width() );
1392 aSz.AdjustHeight(pFly->getFrameArea().Height()- pFly->getFramePrintArea().Height() );
1394 aResult = pFly->ChgSize( aSz );
1396 // if the object changes, the contour is outside the object
1397 assert(pFly->Lower()->IsNoTextFrame());
1398 SwNoTextNode *pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetNoTextNode();
1399 assert(pNd);
1400 pNd->SetContour( nullptr );
1401 ClrContourCache();
1404 // if only the size is to be adjusted, a position is transported with
1405 // allocated values
1406 Point aPt( pFly->getFramePrintArea().Pos() );
1407 aPt += pFly->getFrameArea().Pos();
1408 if ( rRect.Top() != LONG_MIN && rRect.Pos() != aPt && !bPosProt )
1410 aPt = rRect.Pos();
1411 aPt.setX(aPt.getX() - pFly->getFramePrintArea().Left());
1412 aPt.setY(aPt.getY() - pFly->getFramePrintArea().Top());
1414 // in case of paragraph-bound Flys, starting from the new position,
1415 // a new anchor is to be set. The anchor and the new RelPos are
1416 // calculated by the Fly and set
1417 if( pFly->IsFlyAtContentFrame() )
1418 static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( aPt );
1419 else
1421 const SwFrameFormat *pFormat = pFly->GetFormat();
1422 const SwFormatVertOrient &rVert = pFormat->GetVertOrient();
1423 const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient();
1424 const tools::Long lXDiff = aPt.getX() - pFly->getFrameArea().Left();
1425 const tools::Long lYDiff = aPt.getY() - pFly->getFrameArea().Top();
1426 const Point aTmp( rHori.GetPos() + lXDiff,
1427 rVert.GetPos() + lYDiff );
1428 pFly->ChgRelPos( aTmp );
1432 SwFlyFrameFormat *pFlyFrameFormat = pFly->GetFormat();
1433 OSL_ENSURE( pFlyFrameFormat, "fly frame format missing!" );
1434 if ( pFlyFrameFormat )
1435 pFlyFrameFormat->SetLastFlyFramePrtRectPos( pFly->getFramePrintArea().Pos() ); //stores the value of last Prt rect
1437 EndAllAction();
1439 return aResult;
1442 SwFrameFormat* SwFEShell::WizardGetFly()
1444 // do not search the Fly via the layout. Now we can delete a frame
1445 // without a valid layout. ( e.g. for the wizards )
1446 sw::SpzFrameFormats& rSpzArr = *mxDoc->GetSpzFrameFormats();
1447 if( !rSpzArr.empty() )
1449 SwNode& rCursorNd = GetCursor()->GetPoint()->GetNode();
1450 if( rCursorNd > mxDoc->GetNodes().GetEndOfExtras() )
1451 // Cursor is in the body area!
1452 return nullptr;
1454 for( auto pFormat : rSpzArr )
1456 const SwNodeIndex* pIdx = pFormat->GetContent( false ).GetContentIdx();
1457 SwStartNode* pSttNd;
1458 if( pIdx &&
1459 nullptr != ( pSttNd = pIdx->GetNode().GetStartNode() ) &&
1460 *pSttNd < rCursorNd &&
1461 rCursorNd < *pSttNd->EndOfSectionNode() )
1463 // found: return immediately
1464 return pFormat;
1468 return nullptr;
1471 void SwFEShell::SetFlyName( const OUString& rName )
1473 SwLayoutFrame *pFly = GetSelectedFlyFrame();
1474 if( pFly )
1475 GetDoc()->SetFlyName( *static_cast<SwFlyFrameFormat*>(pFly->GetFormat()), rName );
1476 else {
1477 OSL_ENSURE( false, "no FlyFrame selected" );
1481 OUString SwFEShell::GetFlyName() const
1483 SwLayoutFrame *pFly = GetSelectedFlyFrame();
1484 if( pFly )
1485 return pFly->GetFormat()->GetName();
1487 OSL_ENSURE( false, "no FlyFrame selected" );
1488 return OUString();
1491 uno::Reference < embed::XEmbeddedObject > SwFEShell::GetOleRef() const
1493 uno::Reference < embed::XEmbeddedObject > xObj;
1494 SwFlyFrame * pFly = GetSelectedFlyFrame();
1495 if (pFly && pFly->Lower() && pFly->Lower()->IsNoTextFrame())
1497 SwOLENode *pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetOLENode();
1498 if (pNd)
1499 xObj = pNd->GetOLEObj().GetOleRef();
1501 return xObj;
1504 OUString SwFEShell::GetUniqueGrfName() const
1506 return GetDoc()->GetUniqueGrfName();
1509 const SwFrameFormat* SwFEShell::IsURLGrfAtPos( const Point& rPt, OUString* pURL,
1510 OUString *pTargetFrameName,
1511 OUString *pDescription ) const
1513 if( !Imp()->HasDrawView() )
1514 return nullptr;
1516 SdrPageView* pPV;
1517 const SwFrameFormat* pRet = nullptr;
1518 SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());
1520 const auto nOld = pDView->GetHitTolerancePixel();
1521 pDView->SetHitTolerancePixel( 2 );
1523 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO);
1524 SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
1525 if (pFlyObj)
1527 SwFlyFrame *pFly = pFlyObj->GetFlyFrame();
1528 const SwFormatURL &rURL = pFly->GetFormat()->GetURL();
1529 if( !rURL.GetURL().isEmpty() || rURL.GetMap() )
1531 bool bSetTargetFrameName = pTargetFrameName != nullptr;
1532 bool bSetDescription = pDescription != nullptr;
1533 if ( rURL.GetMap() )
1535 IMapObject *pObject = pFly->GetFormat()->GetIMapObject( rPt, pFly );
1536 if ( pObject && !pObject->GetURL().isEmpty() )
1538 if( pURL )
1539 *pURL = pObject->GetURL();
1540 if ( bSetTargetFrameName && !pObject->GetTarget().isEmpty() )
1542 bSetTargetFrameName = false;
1543 *pTargetFrameName = pObject->GetTarget();
1545 if ( bSetDescription )
1547 bSetDescription = false;
1548 *pDescription = pObject->GetAltText();
1550 pRet = pFly->GetFormat();
1553 else
1555 if( pURL )
1557 *pURL = rURL.GetURL();
1558 if( rURL.IsServerMap() )
1560 // append the relative pixel position !!
1561 Point aPt( rPt );
1562 aPt -= pFly->getFrameArea().Pos();
1563 // without MapMode-Offset, without Offset, o ... !!!!!
1564 aPt = GetOut()->LogicToPixel(
1565 aPt, MapMode( MapUnit::MapTwip ) );
1566 *pURL = *pURL + "?" + OUString::number( aPt.getX() )
1567 + "," + OUString::number(aPt.getY() );
1570 pRet = pFly->GetFormat();
1572 if ( bSetTargetFrameName )
1573 *pTargetFrameName = rURL.GetTargetFrameName();
1574 if ( bSetDescription )
1575 *pDescription = pFly->GetFormat()->GetName();
1578 pDView->SetHitTolerancePixel( nOld );
1579 return pRet;
1582 const Graphic *SwFEShell::GetGrfAtPos( const Point &rPt,
1583 OUString &rName, bool &rbLink ) const
1585 if( !Imp()->HasDrawView() )
1586 return nullptr;
1588 SdrPageView* pPV;
1589 SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());
1591 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV);
1592 SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
1593 if (pFlyObj)
1595 SwFlyFrame *pFly = pFlyObj->GetFlyFrame();
1596 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
1598 SwGrfNode *const pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetGrfNode();
1599 if ( pNd )
1601 if ( pNd->IsGrfLink() )
1603 // halfway ready graphic?
1604 ::sfx2::SvLinkSource* pLnkObj = pNd->GetLink()->GetObj();
1605 if( pLnkObj && pLnkObj->IsPending() )
1606 return nullptr;
1607 rbLink = true;
1610 pNd->GetFileFilterNms( &rName, nullptr );
1611 if ( rName.isEmpty() )
1612 rName = pFly->GetFormat()->GetName();
1613 return &pNd->GetGrf(true);
1617 return nullptr;
1620 const SwFrameFormat* SwFEShell::GetFormatFromObj( const Point& rPt, SwRect** pRectToFill ) const
1622 SwFrameFormat* pRet = nullptr;
1624 if( Imp()->HasDrawView() )
1626 SdrPageView* pPView;
1628 SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());
1630 const auto nOld = pDView->GetHitTolerancePixel();
1631 // tolerance for Drawing-SS
1632 pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
1634 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
1635 if (pObj)
1637 // first check it:
1638 if (SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
1639 pRet = pFlyObj->GetFormat();
1640 else if ( pObj->GetUserCall() ) //not for group objects
1641 pRet = static_cast<SwDrawContact*>(pObj->GetUserCall())->GetFormat();
1642 if(pRet && pRectToFill)
1643 **pRectToFill = SwRect(pObj->GetCurrentBoundRect());
1645 pDView->SetHitTolerancePixel( nOld );
1647 return pRet;
1650 // returns a format too, if the point is over the text of any fly
1651 const SwFrameFormat* SwFEShell::GetFormatFromAnyObj( const Point& rPt ) const
1653 const SwFrameFormat* pRet = GetFormatFromObj( rPt );
1654 if( !pRet || RES_FLYFRMFMT == pRet->Which() )
1656 SwPosition aPos( *GetCursor()->GetPoint() );
1657 Point aPt( rPt );
1658 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt );
1659 SwContentNode *pNd = aPos.GetNode().GetContentNode();
1660 std::pair<Point, bool> const tmp(rPt, false);
1661 SwFrame* pFrame = pNd->getLayoutFrame(GetLayout(), nullptr, &tmp)->FindFlyFrame();
1662 pRet = pFrame ? static_cast<SwLayoutFrame*>(pFrame)->GetFormat() : nullptr;
1664 return pRet;
1667 ObjCntType SwFEShell::GetObjCntType( const SdrObject& rObj )
1669 ObjCntType eType = OBJCNT_NONE;
1671 // investigate 'master' drawing object, if method
1672 // is called for a 'virtual' drawing object.
1673 const SdrObject* pInvestigatedObj;
1674 if (const SwDrawVirtObj* pDrawVirtObj = dynamic_cast<const SwDrawVirtObj*>( &rObj))
1676 pInvestigatedObj = &(pDrawVirtObj->GetReferencedObj());
1678 else
1680 pInvestigatedObj = &rObj;
1683 if( SdrInventor::FmForm == pInvestigatedObj->GetObjInventor() )
1685 eType = OBJCNT_CONTROL;
1686 uno::Reference< awt::XControlModel > xModel =
1687 static_cast<const SdrUnoObj&>(*pInvestigatedObj).GetUnoControlModel();
1688 if( xModel.is() )
1690 uno::Any aVal;
1691 OUString sName("ButtonType");
1692 uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY);
1694 uno::Reference< beans::XPropertySetInfo > xInfo = xSet->getPropertySetInfo();
1695 if(xInfo->hasPropertyByName( sName ))
1697 aVal = xSet->getPropertyValue( sName );
1698 if( aVal.hasValue() && form::FormButtonType_URL == *o3tl::doAccess<form::FormButtonType>(aVal) )
1699 eType = OBJCNT_URLBUTTON;
1703 else if (const SwVirtFlyDrawObj *pFlyObj = dynamic_cast<const SwVirtFlyDrawObj*>(pInvestigatedObj))
1705 const SwFlyFrame *pFly = pFlyObj->GetFlyFrame();
1706 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
1708 if (static_cast<const SwNoTextFrame*>(pFly->Lower())->GetNode()->GetGrfNode())
1709 eType = OBJCNT_GRF;
1710 else
1711 eType = OBJCNT_OLE;
1713 else
1714 eType = OBJCNT_FLY;
1716 else if ( dynamic_cast<const SdrObjGroup*>( pInvestigatedObj) != nullptr )
1718 SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(GetUserCall( pInvestigatedObj ) ) );
1719 if ( !pDrawContact )
1721 OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing draw contact object" );
1722 eType = OBJCNT_NONE;
1724 else
1726 SwFrameFormat* pFrameFormat( pDrawContact->GetFormat() );
1727 if ( !pFrameFormat )
1729 OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing frame format" );
1730 eType = OBJCNT_NONE;
1732 else if ( RndStdIds::FLY_AS_CHAR != pFrameFormat->GetAnchor().GetAnchorId() )
1734 eType = OBJCNT_GROUPOBJ;
1738 else
1739 eType = OBJCNT_SIMPLE;
1740 return eType;
1743 ObjCntType SwFEShell::GetObjCntType( const Point &rPt, SdrObject *&rpObj ) const
1745 ObjCntType eType = OBJCNT_NONE;
1747 if( Imp()->HasDrawView() )
1749 SdrPageView* pPView;
1751 SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());
1753 const auto nOld = pDView->GetHitTolerancePixel();
1754 // tolerance for Drawing-SS
1755 pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
1757 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
1758 if (pObj)
1760 rpObj = pObj;
1761 eType = GetObjCntType( *rpObj );
1764 pDView->SetHitTolerancePixel( nOld );
1766 return eType;
1769 ObjCntType SwFEShell::GetObjCntTypeOfSelection() const
1771 ObjCntType eType = OBJCNT_NONE;
1773 if( Imp()->HasDrawView() )
1775 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1776 for( size_t i = 0, nE = rMrkList.GetMarkCount(); i < nE; ++i )
1778 SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
1779 if( !pObj )
1780 continue;
1781 ObjCntType eTmp = GetObjCntType( *pObj );
1782 if( !i )
1784 eType = eTmp;
1786 else if( eTmp != eType )
1788 eType = OBJCNT_DONTCARE;
1789 // once DontCare, always DontCare!
1790 break;
1794 return eType;
1797 void SwFEShell::ReplaceSdrObj( const OUString& rGrfName, const Graphic* pGrf )
1799 CurrShell aCurr( this );
1801 const SdrMarkList *pMrkList;
1802 if( !(Imp()->HasDrawView() && 1 ==
1803 ( pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList())->GetMarkCount()) )
1804 return;
1806 SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
1807 SwFrameFormat *pFormat = FindFrameFormat( pObj );
1809 // store attributes, then set the graphic
1810 SfxItemSet aFrameSet( mxDoc->GetAttrPool(),
1811 pFormat->GetAttrSet().GetRanges() );
1812 aFrameSet.Set( pFormat->GetAttrSet() );
1814 // set size and position?
1815 if( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr )
1817 // then let's do it:
1818 const tools::Rectangle &rBound = pObj->GetSnapRect();
1819 Point aRelPos( pObj->GetRelativePos() );
1821 const tools::Long nWidth = rBound.Right() - rBound.Left();
1822 const tools::Long nHeight= rBound.Bottom() - rBound.Top();
1823 aFrameSet.Put( SwFormatFrameSize( SwFrameSize::Minimum,
1824 std::max( nWidth, tools::Long(MINFLY) ),
1825 std::max( nHeight, tools::Long(MINFLY) )));
1827 if( SfxItemState::SET != aFrameSet.GetItemState( RES_HORI_ORIENT ))
1828 aFrameSet.Put( SwFormatHoriOrient( aRelPos.getX(), text::HoriOrientation::NONE, text::RelOrientation::FRAME ));
1830 if( SfxItemState::SET != aFrameSet.GetItemState( RES_VERT_ORIENT ))
1831 aFrameSet.Put( SwFormatVertOrient( aRelPos.getY(), text::VertOrientation::NONE, text::RelOrientation::FRAME ));
1835 pObj->GetOrdNum();
1837 StartAllAction();
1838 StartUndo();
1840 // delete "Sdr-Object", insert the graphic instead
1841 DelSelectedObj();
1843 GetDoc()->getIDocumentContentOperations().InsertGraphic(
1844 *GetCursor(), rGrfName, "", pGrf, &aFrameSet, nullptr, nullptr);
1846 EndUndo();
1847 EndAllAction();
1850 static sal_uInt16 SwFormatGetPageNum(const SwFlyFrameFormat * pFormat)
1852 OSL_ENSURE(pFormat != nullptr, "invalid argument");
1854 SwFlyFrame * pFrame = pFormat->GetFrame();
1856 sal_uInt16 aResult;
1858 if (pFrame != nullptr)
1859 aResult = pFrame->GetPhyPageNum();
1860 else
1861 aResult = pFormat->GetAnchor().GetPageNum();
1863 return aResult;
1866 void SwFEShell::GetConnectableFrameFormats(SwFrameFormat & rFormat,
1867 const OUString & rReference,
1868 bool bSuccessors,
1869 std::vector< OUString > & aPrevPageVec,
1870 std::vector< OUString > & aThisPageVec,
1871 std::vector< OUString > & aNextPageVec,
1872 std::vector< OUString > & aRestVec)
1874 StartAction();
1876 SwFormatChain rChain = rFormat.GetChain();
1877 SwFrameFormat * pOldChainNext = rChain.GetNext();
1878 SwFrameFormat * pOldChainPrev = rChain.GetPrev();
1880 if (pOldChainNext)
1881 mxDoc->Unchain(rFormat);
1883 if (pOldChainPrev)
1884 mxDoc->Unchain(*pOldChainPrev);
1886 const size_t nCnt = mxDoc->GetFlyCount(FLYCNTTYPE_FRM);
1888 /* potential successors resp. predecessors */
1889 std::vector< const SwFrameFormat * > aTmpSpzArray;
1891 mxDoc->FindFlyByName(rReference);
1893 for (size_t n = 0; n < nCnt; ++n)
1895 const SwFrameFormat & rFormat1 = *(mxDoc->GetFlyNum(n, FLYCNTTYPE_FRM));
1898 pFormat is a potential successor of rFormat if it is chainable after
1899 rFormat.
1901 pFormat is a potential predecessor of rFormat if rFormat is chainable
1902 after pFormat.
1905 SwChainRet nChainState;
1907 if (bSuccessors)
1908 nChainState = mxDoc->Chainable(rFormat, rFormat1);
1909 else
1910 nChainState = mxDoc->Chainable(rFormat1, rFormat);
1912 if (nChainState == SwChainRet::OK)
1914 aTmpSpzArray.push_back(&rFormat1);
1920 if (!aTmpSpzArray.empty())
1922 aPrevPageVec.clear();
1923 aThisPageVec.clear();
1924 aNextPageVec.clear();
1925 aRestVec.clear();
1927 /* number of page rFormat resides on */
1928 sal_uInt16 nPageNum = SwFormatGetPageNum(static_cast<SwFlyFrameFormat *>(&rFormat));
1930 for (const auto& rpFormat : aTmpSpzArray)
1932 const OUString aString = rpFormat->GetName();
1934 /* rFormat is not a valid successor or predecessor of
1935 itself */
1936 if (aString != rReference && aString != rFormat.GetName())
1938 sal_uInt16 nNum1 =
1939 SwFormatGetPageNum(static_cast<const SwFlyFrameFormat *>(rpFormat));
1941 if (nNum1 == nPageNum -1)
1942 aPrevPageVec.push_back(aString);
1943 else if (nNum1 == nPageNum)
1944 aThisPageVec.push_back(aString);
1945 else if (nNum1 == nPageNum + 1)
1946 aNextPageVec.push_back(aString);
1947 else
1948 aRestVec.push_back(aString);
1954 if (pOldChainNext)
1955 mxDoc->Chain(rFormat, *pOldChainNext);
1957 if (pOldChainPrev)
1958 mxDoc->Chain(*pOldChainPrev, rFormat);
1960 EndAction();
1963 // #i73249#
1964 OUString SwFEShell::GetObjTitle() const
1966 if ( Imp()->HasDrawView() )
1968 const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
1969 if ( pMrkList->GetMarkCount() == 1 )
1971 const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
1972 const SwFrameFormat* pFormat = FindFrameFormat( pObj );
1973 if ( pFormat->Which() == RES_FLYFRMFMT )
1975 return static_cast<const SwFlyFrameFormat*>(pFormat)->GetObjTitle();
1977 return pObj->GetTitle();
1981 return OUString();
1984 void SwFEShell::SetObjTitle( const OUString& rTitle )
1986 if ( !Imp()->HasDrawView() )
1987 return;
1989 const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
1990 if ( pMrkList->GetMarkCount() != 1 )
1991 return;
1993 SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
1994 SwFrameFormat* pFormat = FindFrameFormat( pObj );
1995 if ( pFormat->Which() == RES_FLYFRMFMT )
1997 GetDoc()->SetFlyFrameTitle( dynamic_cast<SwFlyFrameFormat&>(*pFormat),
1998 rTitle );
2000 else
2002 pObj->SetTitle( rTitle );
2006 OUString SwFEShell::GetObjDescription() const
2008 if ( Imp()->HasDrawView() )
2010 const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
2011 if ( pMrkList->GetMarkCount() == 1 )
2013 const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
2014 const SwFrameFormat* pFormat = FindFrameFormat( pObj );
2015 if ( pFormat->Which() == RES_FLYFRMFMT )
2017 return dynamic_cast<const SwFlyFrameFormat&>(*pFormat).GetObjDescription();
2019 return pObj->GetDescription();
2023 return OUString();
2026 void SwFEShell::SetObjDescription( const OUString& rDescription )
2028 if ( !Imp()->HasDrawView() )
2029 return;
2031 const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
2032 if ( pMrkList->GetMarkCount() != 1 )
2033 return;
2035 SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
2036 SwFrameFormat* pFormat = FindFrameFormat( pObj );
2037 if ( pFormat->Which() == RES_FLYFRMFMT )
2039 GetDoc()->SetFlyFrameDescription(dynamic_cast<SwFlyFrameFormat&>(*pFormat),
2040 rDescription);
2042 else
2044 pObj->SetDescription( rDescription );
2048 bool SwFEShell::IsObjDecorative() const
2050 if (!Imp()->HasDrawView())
2052 return false;
2055 SdrMarkList const& rMarkList(Imp()->GetDrawView()->GetMarkedObjectList());
2056 if (rMarkList.GetMarkCount() != 1)
2058 return false;
2061 SdrObject const*const pObj(rMarkList.GetMark(0)->GetMarkedSdrObj());
2062 SwFrameFormat const*const pFormat(FindFrameFormat(pObj));
2063 if (pFormat->Which() == RES_FLYFRMFMT)
2065 return dynamic_cast<const SwFlyFrameFormat&>(*pFormat).GetAttrSet().Get(RES_DECORATIVE).GetValue();
2067 return pObj->IsDecorative();
2070 void SwFEShell::SetObjDecorative(bool const isDecorative)
2072 if (!Imp()->HasDrawView())
2074 return;
2077 SdrMarkList const& rMarkList(Imp()->GetDrawView()->GetMarkedObjectList());
2078 if (rMarkList.GetMarkCount() != 1)
2080 return;
2083 SdrObject *const pObj(rMarkList.GetMark(0)->GetMarkedSdrObj());
2084 SwFrameFormat *const pFormat(FindFrameFormat(pObj));
2085 if (pFormat->Which() == RES_FLYFRMFMT)
2087 GetDoc()->SetFlyFrameDecorative(dynamic_cast<SwFlyFrameFormat&>(*pFormat),
2088 isDecorative);
2090 else
2092 pObj->SetDecorative(isDecorative);
2097 void SwFEShell::AlignFormulaToBaseline( const uno::Reference < embed::XEmbeddedObject >& xObj )
2099 #if OSL_DEBUG_LEVEL > 0
2100 SvGlobalName aCLSID( xObj->getClassID() );
2101 const bool bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
2102 OSL_ENSURE( bStarMath, "AlignFormulaToBaseline should only be called for Math objects" );
2104 if ( !bStarMath )
2105 return;
2106 #endif
2108 SwFlyFrame * pFly = FindFlyFrame( xObj );
2109 OSL_ENSURE( pFly , "No fly frame!" );
2110 SwFrameFormat * pFrameFormat = pFly ? pFly->GetFormat() : nullptr;
2112 // baseline to baseline alignment should only be applied to formulas anchored as char
2113 if ( !pFly || !pFrameFormat || RndStdIds::FLY_AS_CHAR != pFrameFormat->GetAnchor().GetAnchorId() )
2114 return;
2116 // get baseline from Math object
2117 uno::Any aBaseline;
2118 if( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
2120 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
2121 if ( xSet.is() )
2125 aBaseline = xSet->getPropertyValue("BaseLine");
2127 catch ( uno::Exception& )
2129 OSL_FAIL( "Baseline could not be retrieved from Starmath!" );
2134 sal_Int32 nBaseline = ::comphelper::getINT32(aBaseline);
2135 nBaseline = o3tl::toTwips( nBaseline, o3tl::Length::mm100 );
2137 OSL_ENSURE( nBaseline > 0, "Wrong value of Baseline while retrieving from Starmath!" );
2138 //nBaseline must be moved by aPrt position
2139 const SwFlyFrameFormat *pFlyFrameFormat = pFly->GetFormat();
2140 OSL_ENSURE( pFlyFrameFormat, "fly frame format missing!" );
2141 if ( pFlyFrameFormat )
2142 nBaseline += pFlyFrameFormat->GetLastFlyFramePrtRectPos().Y();
2144 const SwFormatVertOrient &rVert = pFrameFormat->GetVertOrient();
2145 SwFormatVertOrient aVert( rVert );
2146 aVert.SetPos( -nBaseline );
2147 aVert.SetVertOrient( css::text::VertOrientation::NONE );
2149 pFrameFormat->LockModify();
2150 pFrameFormat->SetFormatAttr( aVert );
2151 pFrameFormat->UnlockModify();
2152 pFly->InvalidatePos();
2156 void SwFEShell::AlignAllFormulasToBaseline()
2158 StartAllAction();
2160 SwStartNode *pStNd;
2161 SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
2162 while ( nullptr != (pStNd = aIdx.GetNode().GetStartNode()) )
2164 ++aIdx;
2165 SwOLENode *pOleNode = aIdx.GetNode().GetOLENode();
2166 if ( pOleNode )
2168 const uno::Reference < embed::XEmbeddedObject > & xObj( pOleNode->GetOLEObj().GetOleRef() );
2169 if (xObj.is())
2171 SvGlobalName aCLSID( xObj->getClassID() );
2172 if ( SotExchange::IsMath( aCLSID ) )
2173 AlignFormulaToBaseline( xObj );
2177 aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
2180 EndAllAction();
2183 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */