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 <svx/svdobj.hxx>
21 #include <osl/diagnose.h>
22 #include <comphelper/lok.hxx>
26 #include <pagefrm.hxx>
27 #include <rootfrm.hxx>
30 #include <frmtool.hxx>
31 #include <swtable.hxx>
32 #include <viewimp.hxx>
37 #include <sectfrm.hxx>
38 #include <fmtpdsc.hxx>
39 #include <fmtsrnd.hxx>
40 #include <fmtcntnt.hxx>
41 #include <fmtfsize.hxx>
43 #include <flyfrms.hxx>
46 #include <pagedesc.hxx>
47 #include <fmtanchr.hxx>
48 #include <environmentofanchoredobject.hxx>
50 #include <dflyobj.hxx>
51 #include <dcontact.hxx>
52 #include <UndoInsert.hxx>
53 #include <formatflysplit.hxx>
55 using namespace com::sun::star
;
60 * This mutex is only used for the paste listeners, where the solar mutex can't
63 osl::Mutex
& GetPasteMutex()
65 static osl::Mutex aMutex
;
70 void SwFEShell::EndAllActionAndCall()
72 for(SwViewShell
& rCurrentShell
: GetRingContainer())
74 if( dynamic_cast<const SwCursorShell
*>( &rCurrentShell
) != nullptr )
76 static_cast<SwFEShell
*>(&rCurrentShell
)->EndAction();
77 static_cast<SwFEShell
*>(&rCurrentShell
)->CallChgLnk();
80 rCurrentShell
.EndAction();
84 // Determine the Content's nearest to the point
85 Point
SwFEShell::GetContentPos( const Point
& rPoint
, bool bNext
) const
87 CurrShell
aCurr( const_cast<SwFEShell
*>(this) );
88 return GetLayout()->GetNextPrevContentPos( rPoint
, bNext
);
91 const SwRect
& SwFEShell::GetAnyCurRect( CurRectType eType
, const Point
* pPt
,
92 const uno::Reference
< embed::XEmbeddedObject
>& xObj
) const
94 const SwFrame
*pFrame
= Imp()->HasDrawView()
95 ? ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
96 const_cast<SwFEShell
*>(this))
103 SwPosition
aPos( *GetCursor()->GetPoint() );
105 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
);
106 SwContentNode
*pNd
= aPos
.GetNode().GetContentNode();
107 std::pair
<Point
, bool> const tmp(*pPt
, true);
108 pFrame
= pNd
->getLayoutFrame(GetLayout(), nullptr, &tmp
);
112 const bool bOldCallbackActionEnabled
= GetLayout()->IsCallbackActionEnabled();
113 if( bOldCallbackActionEnabled
)
114 GetLayout()->SetCallbackActionEnabled( false );
115 pFrame
= GetCurrFrame();
116 if( bOldCallbackActionEnabled
)
117 GetLayout()->SetCallbackActionEnabled( true );
122 return GetLayout()->getFrameArea();
127 case CurRectType::PagePrt
: bFrame
= false;
129 case CurRectType::Page
: pFrame
= pFrame
->FindPageFrame();
132 case CurRectType::PageCalc
:
134 DisableCallbackAction
a(const_cast<SwRootFrame
&>(*pFrame
->getRootFrame()));
135 pFrame
->Calc(Imp()->GetShell()->GetOut());
136 pFrame
= pFrame
->FindPageFrame();
137 pFrame
->Calc(Imp()->GetShell()->GetOut());
141 case CurRectType::FlyEmbeddedPrt
:
144 case CurRectType::FlyEmbedded
:
146 const SwFrame
*pFlyFrame
= xObj
.is() ? FindFlyFrame(xObj
) : nullptr;
147 pFrame
= pFlyFrame
? pFlyFrame
148 : pFrame
->IsFlyFrame()
150 : pFrame
->FindFlyFrame();
153 case CurRectType::SectionOutsideTable
:
154 if( pFrame
->IsInTab() )
155 pFrame
= pFrame
->FindTabFrame();
157 OSL_FAIL( "Missing Table" );
160 case CurRectType::SectionPrt
:
161 case CurRectType::Section
:
162 if( pFrame
->IsInSct() )
163 pFrame
= pFrame
->FindSctFrame();
165 OSL_FAIL( "Missing section" );
168 if( CurRectType::SectionPrt
== eType
)
172 case CurRectType::HeaderFooter
:
173 pFrame
= pFrame
->FindFooterOrHeader();
174 if( nullptr == pFrame
)
175 return GetLayout()->getFrameArea();
178 case CurRectType::PagesArea
:
179 return GetLayout()->GetPagesArea();
183 return bFrame
? pFrame
->getFrameArea() : pFrame
->getFramePrintArea();
186 sal_uInt16
SwFEShell::GetPageNumber( const Point
&rPoint
) const
188 const SwFrame
*pPage
= GetLayout()->Lower();
189 while ( pPage
&& !pPage
->getFrameArea().Contains( rPoint
) )
190 pPage
= pPage
->GetNext();
192 return static_cast<const SwPageFrame
*>(pPage
)->GetPhyPageNum();
197 bool SwFEShell::GetPageNumber( tools::Long nYPos
, bool bAtCursorPos
, sal_uInt16
& rPhyNum
, sal_uInt16
& rVirtNum
, OUString
&rDisplay
) const
199 const SwFrame
*pPage
;
201 if ( bAtCursorPos
) // get page of Cursor
203 pPage
= GetCurrFrame( false );
205 pPage
= pPage
->FindPageFrame();
207 else if ( nYPos
> -1 ) // determine page via the position
209 pPage
= GetLayout()->Lower();
210 while( pPage
&& (pPage
->getFrameArea().Bottom() < nYPos
||
211 nYPos
< pPage
->getFrameArea().Top() ) )
212 pPage
= pPage
->GetNext();
214 else // first visible page
216 pPage
= Imp()->GetFirstVisPage(GetOut());
217 if ( pPage
&& static_cast<const SwPageFrame
*>(pPage
)->IsEmptyPage() )
218 pPage
= pPage
->GetNext();
223 rPhyNum
= static_cast<const SwPageFrame
*>(pPage
)->GetPhyPageNum();
224 rVirtNum
= static_cast<const SwPageFrame
*>(pPage
)->GetVirtPageNum();
225 const SvxNumberType
& rNum
= static_cast<const SwPageFrame
*>(pPage
)->GetPageDesc()->GetNumType();
226 rDisplay
= rNum
.GetNumStr( rVirtNum
);
229 return nullptr != pPage
;
232 bool SwFEShell::IsDirectlyInSection() const
234 SwFrame
* pFrame
= GetCurrFrame( false );
235 return pFrame
&& pFrame
->GetUpper() && pFrame
->GetUpper()->IsSctFrame();
238 FrameTypeFlags
SwFEShell::GetFrameType( const Point
*pPt
, bool bStopAtFly
) const
240 FrameTypeFlags nReturn
= FrameTypeFlags::NONE
;
241 const SwFrame
*pFrame
;
244 SwPosition
aPos( *GetCursor()->GetPoint() );
246 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
);
247 SwContentNode
*pNd
= aPos
.GetNode().GetContentNode();
248 std::pair
<Point
, bool> const tmp(*pPt
, true);
249 pFrame
= pNd
->getLayoutFrame(GetLayout(), nullptr, &tmp
);
252 pFrame
= GetCurrFrame( false );
255 switch ( pFrame
->GetType() )
257 case SwFrameType::Column
:
258 if( pFrame
->GetUpper()->IsSctFrame() )
260 // Check, if isn't not only a single column
261 // from a section with footnotes at the end.
262 if( pFrame
->GetNext() || pFrame
->GetPrev() )
264 nReturn
|= ( nReturn
& FrameTypeFlags::TABLE
) ?
265 FrameTypeFlags::COLSECTOUTTAB
: FrameTypeFlags::COLSECT
;
267 else // only pages and frame columns
268 nReturn
|= FrameTypeFlags::COLUMN
;
270 case SwFrameType::Page
:
271 nReturn
|= FrameTypeFlags::PAGE
;
272 if( static_cast<const SwPageFrame
*>(pFrame
)->IsFootnotePage() )
273 nReturn
|= FrameTypeFlags::FTNPAGE
;
275 case SwFrameType::Header
: nReturn
|= FrameTypeFlags::HEADER
; break;
276 case SwFrameType::Footer
: nReturn
|= FrameTypeFlags::FOOTER
; break;
277 case SwFrameType::Body
:
278 if( pFrame
->GetUpper()->IsPageFrame() ) // not for ColumnFrames
279 nReturn
|= FrameTypeFlags::BODY
;
281 case SwFrameType::Ftn
: nReturn
|= FrameTypeFlags::FOOTNOTE
; break;
282 case SwFrameType::Fly
:
283 if( static_cast<const SwFlyFrame
*>(pFrame
)->IsFlyLayFrame() )
284 nReturn
|= FrameTypeFlags::FLY_FREE
;
285 else if ( static_cast<const SwFlyFrame
*>(pFrame
)->IsFlyAtContentFrame() )
286 nReturn
|= FrameTypeFlags::FLY_ATCNT
;
289 OSL_ENSURE( static_cast<const SwFlyFrame
*>(pFrame
)->IsFlyInContentFrame(),
291 nReturn
|= FrameTypeFlags::FLY_INCNT
;
293 nReturn
|= FrameTypeFlags::FLY_ANY
;
297 case SwFrameType::Tab
:
298 case SwFrameType::Row
:
299 case SwFrameType::Cell
: nReturn
|= FrameTypeFlags::TABLE
; break;
300 default: /* do nothing */ break;
302 if ( pFrame
->IsFlyFrame() )
303 pFrame
= static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame();
305 pFrame
= pFrame
->GetUpper();
310 void SwFEShell::ShellGetFocus()
313 SwCursorShell::ShellGetFocus();
317 if (!comphelper::LibreOfficeKit::isActive())
318 Imp()->GetDrawView()->showMarkHandles();
319 if ( Imp()->GetDrawView()->AreObjectsMarked() )
320 FrameNotify( this, FLY_DRAG_START
);
324 void SwFEShell::ShellLoseFocus()
326 SwCursorShell::ShellLoseFocus();
328 if ( HasDrawView() && Imp()->GetDrawView()->AreObjectsMarked() )
330 if (!comphelper::LibreOfficeKit::isActive())
331 Imp()->GetDrawView()->hideMarkHandles();
332 FrameNotify( this, FLY_DRAG_END
);
336 sal_uInt16
SwFEShell::GetPhyPageNum() const
338 SwFrame
*pFrame
= GetCurrFrame();
340 return pFrame
->GetPhyPageNum();
344 sal_uInt16
SwFEShell::GetVirtPageNum() const
346 SwFrame
*pFrame
= GetCurrFrame();
348 return pFrame
->GetVirtPageNum();
352 static void lcl_SetAPageOffset( sal_uInt16 nOffset
, SwPageFrame
* pPage
, SwFEShell
* pThis
)
354 pThis
->StartAllAction();
355 OSL_ENSURE( pPage
->FindFirstBodyContent(),
356 "SwFEShell _SetAPageOffset() without ContentFrame" );
358 SwFormatPageDesc
aDesc( pPage
->GetPageDesc() );
359 aDesc
.SetNumOffset( nOffset
);
361 SwFrame
*pFrame
= pThis
->GetCurrFrame( false );
362 if ( pFrame
->IsInTab() )
363 pThis
->GetDoc()->SetAttr( aDesc
, *pFrame
->FindTabFrame()->GetFormat() );
366 pThis
->GetDoc()->getIDocumentContentOperations().InsertPoolItem(
367 *pThis
->GetCursor(), aDesc
, SetAttrMode::DEFAULT
, pThis
->GetLayout());
370 pThis
->EndAllAction();
373 void SwFEShell::SetNewPageOffset( sal_uInt16 nOffset
)
375 GetLayout()->SetVirtPageNum( true );
376 const SwPageFrame
*pPage
= GetCurrFrame( false )->FindPageFrame();
377 lcl_SetAPageOffset( nOffset
, const_cast<SwPageFrame
*>(pPage
), this );
380 void SwFEShell::SetPageOffset( sal_uInt16 nOffset
)
382 const SwPageFrame
*pPage
= GetCurrFrame( false )->FindPageFrame();
383 const SwRootFrame
* pDocLayout
= GetLayout();
386 const SwFrame
*pFlow
= pPage
->FindFirstBodyContent();
389 if ( pFlow
->IsInTab() )
390 pFlow
= pFlow
->FindTabFrame();
391 const SwFormatPageDesc
& rPgDesc
= pFlow
->GetPageDescItem();
392 if ( rPgDesc
.GetNumOffset() )
394 pDocLayout
->SetVirtPageNum( true );
395 lcl_SetAPageOffset( nOffset
, const_cast<SwPageFrame
*>(pPage
), this );
399 pPage
= static_cast<const SwPageFrame
*>(pPage
->GetPrev());
403 sal_uInt16
SwFEShell::GetPageOffset() const
405 const SwPageFrame
*pPage
= GetCurrFrame()->FindPageFrame();
408 const SwFrame
*pFlow
= pPage
->FindFirstBodyContent();
411 if ( pFlow
->IsInTab() )
412 pFlow
= pFlow
->FindTabFrame();
413 ::std::optional
<sal_uInt16
> oNumOffset
= pFlow
->GetPageDescItem().GetNumOffset();
417 pPage
= static_cast<const SwPageFrame
*>(pPage
->GetPrev());
422 void SwFEShell::InsertLabel( const SwLabelType eType
, const OUString
&rText
, const OUString
& rSeparator
,
423 const OUString
& rNumberSeparator
,
424 const bool bBefore
, const sal_uInt16 nId
,
425 const OUString
& rCharacterStyle
,
428 // get node index of cursor position, SwDoc can do everything else itself
429 SwContentFrame
*pCnt
= SwLabelType::Draw
==eType
? nullptr : GetCurrFrame( false );
430 if( SwLabelType::Draw
!=eType
&& !pCnt
)
434 SwRewriter
aRewriter(SwUndoInsertLabel::CreateRewriter(rText
));
435 StartUndo(SwUndoId::INSERTLABEL
, &aRewriter
);
437 SwNodeOffset
nIdx(0);
438 bool bInnerCntIsFly
= false;
439 SwFlyFrameFormat
* pFlyFormat
= nullptr;
442 case SwLabelType::Object
:
443 case SwLabelType::Fly
:
444 bInnerCntIsFly
= pCnt
->IsInFly();
447 // pass down index to the startnode for flys
448 nIdx
= pCnt
->FindFlyFrame()->
449 GetFormat()->GetContent().GetContentIdx()->GetIndex();
452 case SwLabelType::Table
:
453 if( pCnt
->IsInTab() )
455 // pass down index to the TableNode for tables
456 SwTabFrame
* pTabFrame
= pCnt
->FindTabFrame();
457 const SwTable
& rTable
= *pTabFrame
->GetTable();
458 nIdx
= rTable
.GetTabSortBoxes()[ 0 ]
459 ->GetSttNd()->FindTableNode()->GetIndex();
461 SwFlyFrame
* pFly
= pTabFrame
->FindFlyFrame();
462 if (pFly
&& pFly
->IsFlySplitAllowed())
464 // This table is in a split fly, but we will insert a label, which means this is not
465 // a floating table anymore, disable the "can split" bit, it'll be hidden on the UI
467 SwFrameFormat
& rFlyFormat
= pFly
->GetFrameFormat();
468 SfxItemSetFixed
<RES_FLY_SPLIT
, RES_FLY_SPLIT
> aSet(GetDoc()->GetAttrPool());
469 SwFormatFlySplit
aSplit(false);
471 // SwUndoFormatAttr is created for us.
472 GetDoc()->SetFlyFrameAttr(rFlyFormat
, aSet
);
476 case SwLabelType::Draw
:
477 if( Imp()->GetDrawView() )
479 SwDrawView
*pDView
= Imp()->GetDrawView();
480 const SdrMarkList
& rMrkList
= pDView
->GetMarkedObjectList();
482 // copy marked drawing objects to
483 // local list to perform the corresponding action for each object
484 std::vector
<SdrObject
*> aDrawObjs
;
486 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
488 SdrObject
* pDrawObj
= rMrkList
.GetMark(i
)->GetMarkedSdrObj();
490 aDrawObjs
.push_back( pDrawObj
);
493 // loop on marked drawing objects
494 while ( !aDrawObjs
.empty() )
496 SdrObject
* pDrawObj
= aDrawObjs
.back();
497 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pDrawObj
) == nullptr &&
498 dynamic_cast<const SwFlyDrawObj
*>( pDrawObj
) == nullptr )
500 SwFlyFrameFormat
*pFormat
=
501 GetDoc()->InsertDrawLabel( rText
, rSeparator
, rNumberSeparator
, nId
, rCharacterStyle
, *pDrawObj
);
503 pFlyFormat
= pFormat
;
506 aDrawObjs
.pop_back();
512 OSL_ENSURE( false, "Cursor neither in table nor in fly." );
517 pFlyFormat
= GetDoc()->InsertLabel(eType
, rText
, rSeparator
,
518 rNumberSeparator
, bBefore
, nId
,
519 nIdx
, rCharacterStyle
, bCpyBrd
);
524 const Point
aPt(GetCursorDocPos());
525 if (SwFlyFrame
* pFrame
= pFlyFormat
->GetFrame(&aPt
))
526 SelectFlyFrame(*pFrame
);
529 EndAllActionAndCall();
533 bool SwFEShell::Sort(const SwSortOptions
& rOpt
)
535 if( !HasSelection() )
538 CurrShell
aCurr( this );
544 // check if Point/Mark of current Cursor are in one table
545 SwFrame
*pFrame
= GetCurrFrame( false );
546 OSL_ENSURE( pFrame
->FindTabFrame(), "Cursor not in table." );
548 // search boxes via the layout
550 GetTableSel(*this, aBoxes
);
552 // The Cursor should be removed from the deletion area.
553 // Always put them behind/on the table; via the
554 // document position they will always be set to the old position
555 while( !pFrame
->IsCellFrame() )
556 pFrame
= pFrame
->GetUpper();
558 /* ParkCursor->ParkCursorTab */
562 // call sorting on document
563 bRet
= mxDoc
->SortTable(aBoxes
, rOpt
);
567 // Sort text nothing else
568 for(SwPaM
& rPaM
: GetCursor()->GetRingContainer())
572 auto [pStart
, pEnd
] = pPam
->StartEnd(); // SwPosition*
574 SwNodeIndex
aPrevIdx( pStart
->GetNode(), -1 );
575 SwNodeOffset nOffset
= pEnd
->GetNodeIndex() - pStart
->GetNodeIndex();
576 const sal_Int32 nCntStt
= pStart
->GetContentIndex();
579 bRet
= mxDoc
->SortText(*pPam
, rOpt
);
581 // put selection again
583 pPam
->GetPoint()->Assign( aPrevIdx
.GetNode(), SwNodeOffset(+1) );
584 SwContentNode
* pCNd
= pPam
->GetPointContentNode();
585 sal_Int32 nLen
= pCNd
->Len();
588 pPam
->GetPoint()->SetContent(nLen
);
591 pPam
->GetPoint()->Adjust(nOffset
);
592 pCNd
= pPam
->GetPointContentNode();
593 pPam
->GetPoint()->SetContent( pCNd
->Len() );
601 bool SwFEShell::IsColRightToLeft() const
603 SwFrame
* pFrame
= GetCurrFrame();
606 pFrame
= pFrame
->GetUpper();
607 if (pFrame
&& pFrame
->IsColumnFrame())
609 return pFrame
->IsRightToLeft();
615 sal_uInt16
SwFEShell::GetCurColNum_( const SwFrame
*pFrame
,
616 SwGetCurColNumPara
* pPara
)
621 pFrame
= pFrame
->GetUpper();
622 if( pFrame
&& pFrame
->IsColumnFrame() )
624 const SwFrame
*pCurFrame
= pFrame
;
627 pFrame
= pFrame
->GetPrev();
632 // now search the format, determining the columness
633 pFrame
= pCurFrame
->GetUpper();
636 if( ( SwFrameType::Page
| SwFrameType::Fly
| SwFrameType::Section
) & pFrame
->GetType() )
638 pPara
->pFrameFormat
= static_cast<const SwLayoutFrame
*>(pFrame
)->GetFormat();
639 pPara
->pPrtRect
= &pFrame
->getFramePrintArea();
642 pFrame
= pFrame
->GetUpper();
646 pPara
->pFrameFormat
= nullptr;
647 pPara
->pPrtRect
= nullptr;
656 sal_uInt16
SwFEShell::GetCurColNum( SwGetCurColNumPara
* pPara
) const
658 OSL_ENSURE( GetCurrFrame(), "Cursor parked?" );
659 return GetCurColNum_( GetCurrFrame(), pPara
);
662 sal_uInt16
SwFEShell::GetCurOutColNum() const
665 SwFrame
* pFrame
= GetCurrFrame();
666 OSL_ENSURE( pFrame
, "Cursor parked?" );
669 pFrame
= pFrame
->IsInTab() ? static_cast<SwFrame
*>(pFrame
->FindTabFrame())
670 : static_cast<SwFrame
*>(pFrame
->FindSctFrame());
671 OSL_ENSURE( pFrame
, "No Tab, no Sect" );
673 nRet
= GetCurColNum_( pFrame
, nullptr );
678 SwFEShell::SwFEShell( SwDoc
& rDoc
, vcl::Window
*pWindow
, const SwViewOption
*pOptions
)
679 : SwEditShell( rDoc
, pWindow
, pOptions
)
680 , m_bCheckForOLEInCaption(false)
681 , m_aPasteListeners(GetPasteMutex())
682 , m_eTableInsertMode(SwTable::SEARCH_NONE
)
683 , m_bTableCopied(false)
687 SwFEShell::SwFEShell( SwEditShell
& rShell
, vcl::Window
*pWindow
)
688 : SwEditShell( rShell
, pWindow
)
689 , m_bCheckForOLEInCaption(false)
690 , m_aPasteListeners(GetPasteMutex())
691 , m_eTableInsertMode(SwTable::SEARCH_NONE
)
692 , m_bTableCopied(false)
696 SwFEShell::~SwFEShell()
700 // #i17567# - adjustments for allowing
701 // negative vertical positions for fly frames anchored to paragraph/to character.
702 // #i22305# - adjustments for option 'Follow text flow'
703 // for to frame anchored objects.
704 // #i22341# - adjustments for vertical alignment at top of line
705 // for to character anchored objects.
706 void SwFEShell::CalcBoundRect( SwRect
& _orRect
,
707 const RndStdIds _nAnchorId
,
708 const sal_Int16 _eHoriRelOrient
,
709 const sal_Int16 _eVertRelOrient
,
710 const SwFormatAnchor
* _pToCharContentPos
,
711 const bool _bFollowTextFlow
,
715 const SwFormatFrameSize
* pFormatFrameSize
) const
717 const SwFrame
* pFrame
;
718 const SwFlyFrame
* pFly
;
721 pFrame
= GetCurrFrame();
722 pFly
= pFrame
->FindFlyFrame();
723 if( nullptr != pFly
)
724 pFrame
= pFly
->GetAnchorFrame();
728 pFly
= GetSelectedFlyFrame();
729 pFrame
= pFly
? pFly
->GetAnchorFrame() : GetCurrFrame();
732 bool bWrapThrough
= false;
735 SwFlyFrameFormat
* pFormat
= const_cast<SwFlyFrameFormat
*>(pFly
->GetFormat());
736 const SwFormatSurround
& rSurround
= pFormat
->GetSurround();
737 bWrapThrough
= rSurround
.GetSurround() == css::text::WrapTextMode_THROUGH
;
740 const SwPageFrame
* pPage
= pFrame
->FindPageFrame();
741 _bMirror
= _bMirror
&& !pPage
->OnRightPage();
744 bool bVertic
= false;
746 bool bVerticalL2R
= false;
748 if ((RndStdIds::FLY_AT_PAGE
== _nAnchorId
) || (RndStdIds::FLY_AT_FLY
== _nAnchorId
)) // LAYER_IMPL
750 const SwFrame
* pTmp
= pFrame
;
752 if ((RndStdIds::FLY_AT_PAGE
== _nAnchorId
) ||
753 ((RndStdIds::FLY_AT_FLY
== _nAnchorId
) && !_bFollowTextFlow
))
759 pFrame
= pFrame
->FindFlyFrame();
763 _orRect
= pFrame
->getFrameArea();
764 SwRectFnSet
aRectFnSet(pFrame
);
765 bRTL
= pFrame
->IsRightToLeft();
767 aPos
= pFrame
->getFrameArea().TopRight();
769 aPos
= aRectFnSet
.GetPos(pFrame
->getFrameArea());
771 if( aRectFnSet
.IsVert() || aRectFnSet
.IsVertL2R() )
773 bVertic
= aRectFnSet
.IsVert();
774 bVerticalL2R
= aRectFnSet
.IsVertL2R();
775 _bMirror
= false; // no mirroring in vertical environment
776 switch ( _eHoriRelOrient
)
778 case text::RelOrientation::PAGE_RIGHT
:
779 case text::RelOrientation::FRAME_RIGHT
: aPos
.AdjustY(pFrame
->getFramePrintArea().Height() );
781 case text::RelOrientation::PRINT_AREA
:
782 case text::RelOrientation::PAGE_PRINT_AREA
: aPos
.AdjustY(pFrame
->getFramePrintArea().Top() ); break;
788 switch ( _eHoriRelOrient
)
790 case text::RelOrientation::PRINT_AREA
:
791 case text::RelOrientation::PAGE_PRINT_AREA
: aPos
.AdjustX(pFrame
->getFramePrintArea().Width() );
793 case text::RelOrientation::PAGE_RIGHT
:
794 case text::RelOrientation::FRAME_RIGHT
: aPos
.AdjustX(pFrame
->getFramePrintArea().Left() ); break;
795 default: aPos
.AdjustX(pFrame
->getFrameArea().Width() );
800 switch ( _eHoriRelOrient
)
802 case text::RelOrientation::PRINT_AREA
:
803 case text::RelOrientation::PAGE_PRINT_AREA
: aPos
.AdjustX(pFrame
->getFramePrintArea().Width() );
805 case text::RelOrientation::PAGE_LEFT
:
806 case text::RelOrientation::FRAME_LEFT
: aPos
.AdjustX(pFrame
->getFramePrintArea().Left() -
807 pFrame
->getFrameArea().Width() ); break;
813 switch ( _eHoriRelOrient
)
815 case text::RelOrientation::PAGE_RIGHT
:
816 case text::RelOrientation::FRAME_RIGHT
: aPos
.AdjustX(pFrame
->getFramePrintArea().Width() );
818 case text::RelOrientation::PRINT_AREA
:
819 case text::RelOrientation::PAGE_PRINT_AREA
: aPos
.AdjustX(pFrame
->getFramePrintArea().Left() ); break;
824 if ( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
826 switch ( _eVertRelOrient
)
828 case text::RelOrientation::PRINT_AREA
:
829 case text::RelOrientation::PAGE_PRINT_AREA
:
831 aPos
.AdjustX( -(pFrame
->GetRightMargin()) );
836 else if ( aRectFnSet
.IsVertL2R() )
838 switch ( _eVertRelOrient
)
840 case text::RelOrientation::PRINT_AREA
:
841 case text::RelOrientation::PAGE_PRINT_AREA
:
843 aPos
.AdjustX(pFrame
->GetLeftMargin() );
850 switch ( _eVertRelOrient
)
852 case text::RelOrientation::PRINT_AREA
:
853 case text::RelOrientation::PAGE_PRINT_AREA
:
855 if ( pFrame
->IsPageFrame() )
858 static_cast<const SwPageFrame
*>(pFrame
)->PrtWithoutHeaderAndFooter().Top() );
862 aPos
.AdjustY(pFrame
->getFramePrintArea().Top() );
869 *_opPercent
= pFrame
->getFramePrintArea().SSize();
873 const SwFrame
* pUpper
= ( pFrame
->IsPageFrame() || pFrame
->IsFlyFrame() ) ?
874 pFrame
: pFrame
->GetUpper();
875 SwRectFnSet
aRectFnSet(pUpper
);
878 // If the size is relative from page, then full size should be counted from the page frame.
879 if (pFormatFrameSize
&& pFormatFrameSize
->GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME
)
880 _opPercent
->setWidth(pPage
->getFrameArea().Width());
882 _opPercent
->setWidth(pUpper
->getFramePrintArea().Width());
884 if (pFormatFrameSize
&& pFormatFrameSize
->GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME
)
885 // If the size is relative from page, then full size should be counted from the page frame.
886 _opPercent
->setHeight(pPage
->getFrameArea().Height());
888 _opPercent
->setHeight(pUpper
->getFramePrintArea().Height());
891 bRTL
= pFrame
->IsRightToLeft();
893 aPos
= pFrame
->getFrameArea().TopRight();
895 aPos
= aRectFnSet
.GetPos(pFrame
->getFrameArea());
896 // #i17567# - allow negative positions
897 // for fly frames anchor to paragraph/to character.
898 if ((_nAnchorId
== RndStdIds::FLY_AT_PARA
) || (_nAnchorId
== RndStdIds::FLY_AT_CHAR
))
900 // The rectangle, the fly frame can be positioned in, is determined
901 // horizontally by the frame area of the horizontal environment
902 // and vertically by the printing area of the vertical environment,
903 // if the object follows the text flow, or by the frame area of the
904 // vertical environment, if the object doesn't follow the text flow.
905 // new class <SwEnvironmentOfAnchoredObject>
906 objectpositioning::SwEnvironmentOfAnchoredObject
aEnvOfObj(
908 const SwLayoutFrame
& rHoriEnvironLayFrame
=
909 aEnvOfObj
.GetHoriEnvironmentLayoutFrame( *pFrame
);
910 const SwLayoutFrame
& rVertEnvironLayFrame
=
911 aEnvOfObj
.GetVertEnvironmentLayoutFrame( *pFrame
);
912 const SwRect
& aHoriEnvironRect( rHoriEnvironLayFrame
.getFrameArea() );
913 SwRect aVertEnvironRect
;
914 if ( _bFollowTextFlow
)
916 aVertEnvironRect
= rVertEnvironLayFrame
.getFramePrintArea();
917 aVertEnvironRect
.Pos() += rVertEnvironLayFrame
.getFrameArea().Pos();
918 // #i18732# - adjust vertical 'virtual' anchor position
919 // (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned
921 if ( _eVertRelOrient
== text::RelOrientation::PAGE_FRAME
|| _eVertRelOrient
== text::RelOrientation::PAGE_PRINT_AREA
)
923 if ( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
925 aPos
.setX( aVertEnvironRect
.Right() );
927 else if ( aRectFnSet
.IsVertL2R() )
929 aPos
.setX( aVertEnvironRect
.Left() );
933 aPos
.setY( aVertEnvironRect
.Top() );
939 OSL_ENSURE( rVertEnvironLayFrame
.IsPageFrame(),
940 "<SwFEShell::CalcBoundRect(..)> - not following text flow, but vertical environment *not* page!" );
941 aVertEnvironRect
= rVertEnvironLayFrame
.getFrameArea();
942 // #i18732# - adjustment vertical 'virtual' anchor position
943 // (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned
945 if (_eVertRelOrient
== text::RelOrientation::PAGE_FRAME
946 || _eVertRelOrient
== text::RelOrientation::PAGE_PRINT_AREA
947 || _eVertRelOrient
== text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
)
949 if ( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
951 aPos
.setX( aVertEnvironRect
.Right() );
952 if ( _eVertRelOrient
== text::RelOrientation::PAGE_PRINT_AREA
)
954 aPos
.setX(aPos
.getX() - rVertEnvironLayFrame
.GetRightMargin());
957 else if ( aRectFnSet
.IsVertL2R() )
959 aPos
.setX( aVertEnvironRect
.Left() );
960 if ( _eVertRelOrient
== text::RelOrientation::PAGE_PRINT_AREA
)
962 aPos
.setX(aPos
.getX() + rVertEnvironLayFrame
.GetLeftMargin());
967 aPos
.setY( aVertEnvironRect
.Top() );
968 if ( _eVertRelOrient
== text::RelOrientation::PAGE_PRINT_AREA
)
970 aPos
.setY(aPos
.getY() + rVertEnvironLayFrame
.GetTopMargin());
971 // add height of page header
972 const SwFrame
* pTmpFrame
= rVertEnvironLayFrame
.Lower();
973 if ( pTmpFrame
->IsHeaderFrame() )
975 aPos
.setY(aPos
.getY() + pTmpFrame
->getFrameArea().Height());
978 else if (_eVertRelOrient
== text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
)
980 if (rVertEnvironLayFrame
.IsPageFrame())
982 auto& rPageFrame
= static_cast<const SwPageFrame
&>(rVertEnvironLayFrame
);
983 aPos
.setY(rPageFrame
.PrtWithoutHeaderAndFooter().Bottom());
987 aPos
.AdjustY(rVertEnvironLayFrame
.getFramePrintArea().Bottom());
994 // #i22341# - adjust vertical 'virtual' anchor position
995 // (<aPos.Y()> respectively <aPos.X()>), if object is anchored to
996 // character and vertical aligned at character or top of line
997 // <pFrame>, which is the anchor frame or the proposed anchor frame,
998 // doesn't have to be a text frame (e.g. edit a to-page anchored
999 // fly frame). Thus, assure this.
1000 const SwTextFrame
* pTextFrame
= pFrame
->DynCastTextFrame();
1002 (_nAnchorId
== RndStdIds::FLY_AT_CHAR
) &&
1003 ( _eVertRelOrient
== text::RelOrientation::CHAR
||
1004 _eVertRelOrient
== text::RelOrientation::TEXT_LINE
) )
1007 if ( _eVertRelOrient
== text::RelOrientation::CHAR
)
1010 if ( _pToCharContentPos
)
1012 pTextFrame
->GetAutoPos( aChRect
, *_pToCharContentPos
->GetContentAnchor() );
1016 // No content position provided. Thus, use a default one.
1017 SwPosition
aDefaultContentPos(*(pTextFrame
->GetTextNodeFirst()));
1018 pTextFrame
->GetAutoPos( aChRect
, aDefaultContentPos
);
1020 nTop
= aRectFnSet
.GetBottom(aChRect
);
1024 if ( _pToCharContentPos
)
1026 pTextFrame
->GetTopOfLine( nTop
, *_pToCharContentPos
->GetContentAnchor() );
1030 // No content position provided. Thus, use a default one.
1031 SwPosition
aDefaultContentPos(*(pTextFrame
->GetTextNodeFirst()));
1032 pTextFrame
->GetTopOfLine( nTop
, aDefaultContentPos
);
1035 if ( aRectFnSet
.IsVert() || aRectFnSet
.IsVertL2R() )
1045 // #i26945# - adjust horizontal 'virtual' anchor
1046 // position (<aPos.X()> respectively <aPos.Y()>), if object is
1047 // anchored to character and horizontal aligned at character.
1049 (_nAnchorId
== RndStdIds::FLY_AT_CHAR
) &&
1050 _eHoriRelOrient
== text::RelOrientation::CHAR
)
1054 if ( _pToCharContentPos
)
1056 pTextFrame
->GetAutoPos( aChRect
, *_pToCharContentPos
->GetContentAnchor() );
1060 // No content position provided. Thus, use a default one.
1061 SwPosition
aDefaultContentPos(*(pTextFrame
->GetTextNodeFirst()));
1062 pTextFrame
->GetAutoPos( aChRect
, aDefaultContentPos
);
1064 nLeft
= aRectFnSet
.GetLeft(aChRect
);
1065 if ( aRectFnSet
.IsVert() || aRectFnSet
.IsVertL2R() )
1074 if ( aRectFnSet
.IsVert() || aRectFnSet
.IsVertL2R() )
1076 _orRect
= SwRect( aVertEnvironRect
.Left(),
1077 aHoriEnvironRect
.Top(),
1078 aVertEnvironRect
.Width(),
1079 aHoriEnvironRect
.Height() );
1083 _orRect
= SwRect( aHoriEnvironRect
.Left(),
1084 aVertEnvironRect
.Top(),
1085 aHoriEnvironRect
.Width(),
1086 aVertEnvironRect
.Height() );
1091 if( _opRef
&& pFly
&& pFly
->IsFlyInContentFrame() )
1092 *_opRef
= static_cast<const SwFlyInContentFrame
*>( pFly
)->GetRefPoint();
1094 _orRect
= pUpper
->getFrameArea();
1095 if( !pUpper
->IsBodyFrame() )
1097 _orRect
+= pUpper
->getFramePrintArea().Pos();
1098 _orRect
.SSize( pUpper
->getFramePrintArea().SSize() );
1099 if ( pUpper
->IsCellFrame() )//MA_FLY_HEIGHT
1101 const SwFrame
* pTab
= pUpper
->FindTabFrame();
1102 tools::Long nBottom
= aRectFnSet
.GetPrtBottom(*pTab
->GetUpper());
1103 aRectFnSet
.SetBottom( _orRect
, nBottom
);
1106 // only use 90% of height for character bound
1108 if( aRectFnSet
.IsVert() || aRectFnSet
.IsVertL2R() )
1109 _orRect
.Width( (_orRect
.Width()*9)/10 );
1111 _orRect
.Height( (_orRect
.Height()*9)/10 );
1115 const SwTwips nBaseOfstForFly
= ( pFrame
->IsTextFrame() && pFly
) ?
1116 static_cast<const SwTextFrame
*>(pFrame
)->GetBaseOffsetForFly( !bWrapThrough
) :
1118 if( aRectFnSet
.IsVert() || aRectFnSet
.IsVertL2R() )
1120 bVertic
= aRectFnSet
.IsVert();
1121 bVerticalL2R
= aRectFnSet
.IsVertL2R();
1124 switch ( _eHoriRelOrient
)
1126 case text::RelOrientation::FRAME_RIGHT
:
1128 aPos
.setY(aPos
.getY() + pFrame
->getFramePrintArea().Height());
1129 aPos
+= aRectFnSet
.GetPos(pFrame
->getFramePrintArea());
1132 case text::RelOrientation::PRINT_AREA
:
1134 aPos
+= aRectFnSet
.GetPos(pFrame
->getFramePrintArea());
1135 aPos
.setY(aPos
.getY() + nBaseOfstForFly
);
1138 case text::RelOrientation::PAGE_RIGHT
:
1140 aPos
.setY(pPage
->getFrameArea().Top() + pPage
->getFramePrintArea().Bottom());
1143 case text::RelOrientation::PAGE_PRINT_AREA
:
1145 aPos
.setY(pPage
->getFrameArea().Top() + pPage
->getFramePrintArea().Top());
1148 case text::RelOrientation::PAGE_LEFT
:
1149 case text::RelOrientation::PAGE_FRAME
:
1151 aPos
.setY(pPage
->getFrameArea().Top());
1154 case text::RelOrientation::FRAME
:
1156 aPos
.setY(aPos
.getY() + nBaseOfstForFly
);
1164 switch ( _eHoriRelOrient
)
1166 case text::RelOrientation::FRAME_RIGHT
: aPos
.setX(aPos
.getX() + pFrame
->getFramePrintArea().Left()); break;
1167 case text::RelOrientation::FRAME
:
1168 case text::RelOrientation::FRAME_LEFT
: aPos
.setX(aPos
.getX() + pFrame
->getFrameArea().Width()); break;
1169 case text::RelOrientation::PRINT_AREA
: aPos
.setX(aPos
.getX() + pFrame
->getFramePrintArea().Right()); break;
1170 case text::RelOrientation::PAGE_LEFT
:
1171 case text::RelOrientation::PAGE_FRAME
: aPos
.setX(pPage
->getFrameArea().Right()); break;
1172 case text::RelOrientation::PAGE_PRINT_AREA
: aPos
.setX(pPage
->getFrameArea().Left()
1173 + pPage
->getFramePrintArea().Left()); break;
1179 switch ( _eHoriRelOrient
)
1181 case text::RelOrientation::FRAME_LEFT
:
1182 aPos
.setX(pFrame
->getFrameArea().Left() +
1183 pFrame
->getFramePrintArea().Left());
1186 case text::RelOrientation::PRINT_AREA
:
1187 aPos
.setX(pFrame
->getFrameArea().Left() + pFrame
->getFramePrintArea().Left() +
1188 pFrame
->getFramePrintArea().Width());
1189 aPos
.setX(aPos
.getX() + nBaseOfstForFly
);
1192 case text::RelOrientation::PAGE_LEFT
:
1193 aPos
.setX(pPage
->getFrameArea().Left() + pPage
->getFramePrintArea().Left());
1196 case text::RelOrientation::PAGE_PRINT_AREA
:
1197 aPos
.setX(pPage
->getFrameArea().Left() + pPage
->getFramePrintArea().Left() +
1198 pPage
->getFramePrintArea().Width());
1201 case text::RelOrientation::PAGE_RIGHT
:
1202 case text::RelOrientation::PAGE_FRAME
:
1203 aPos
.setX(pPage
->getFrameArea().Right());
1206 case text::RelOrientation::FRAME
:
1207 aPos
.setX(aPos
.getX() + nBaseOfstForFly
);
1214 switch ( _eHoriRelOrient
)
1216 case text::RelOrientation::FRAME_RIGHT
:
1217 aPos
.AdjustX(pFrame
->getFramePrintArea().Width() );
1218 aPos
+= pFrame
->getFramePrintArea().Pos();
1220 case text::RelOrientation::PRINT_AREA
:
1221 aPos
+= pFrame
->getFramePrintArea().Pos();
1222 aPos
.setX(aPos
.getX() + nBaseOfstForFly
);
1224 case text::RelOrientation::PAGE_RIGHT
:
1225 aPos
.setX(pPage
->getFrameArea().Left() + pPage
->getFramePrintArea().Right());
1227 case text::RelOrientation::PAGE_PRINT_AREA
:
1228 aPos
.setX(pPage
->getFrameArea().Left() + pPage
->getFramePrintArea().Left());
1230 case text::RelOrientation::PAGE_LEFT
:
1231 case text::RelOrientation::PAGE_FRAME
:
1232 aPos
.setX(pPage
->getFrameArea().Left());
1234 case text::RelOrientation::FRAME
:
1235 aPos
.setX(aPos
.getX() + nBaseOfstForFly
);
1245 if( bVertic
&& !bVerticalL2R
)
1246 _orRect
.Pos( aPos
.getX() - _orRect
.Width() - _orRect
.Left(), _orRect
.Top() - aPos
.getY() );
1247 else if( bVerticalL2R
)
1248 _orRect
.Pos( _orRect
.Left() - aPos
.getX(), _orRect
.Top() - aPos
.getY() );
1250 _orRect
.Pos( - ( _orRect
.Right() - aPos
.getX() ), _orRect
.Top() - aPos
.getY() );
1252 _orRect
.Pos( _orRect
.Left() - aPos
.getX(), _orRect
.Top() - aPos
.getY() );
1254 _orRect
.Pos( -_orRect
.Right(), _orRect
.Top() );
1257 Size
SwFEShell::GetGraphicDefaultSize() const
1260 SwFlyFrame
*pFly
= GetSelectedFlyFrame();
1263 // #i32951# - due to issue #i28701# no format of a
1264 // newly inserted Writer fly frame or its anchor frame is performed
1265 // any more. Thus, it could be possible (e.g. on insert of a horizontal
1266 // line) that the anchor frame isn't formatted and its printing area
1267 // size is (0,0). If this is the case the printing area of the upper
1268 // of the anchor frame is taken.
1269 const SwFrame
* pAnchorFrame
= pFly
->GetAnchorFrame();
1270 aRet
= pAnchorFrame
->getFramePrintArea().SSize();
1271 if ( aRet
.IsEmpty() && pAnchorFrame
->GetUpper() )
1273 aRet
= pAnchorFrame
->GetUpper()->getFramePrintArea().SSize();
1277 CalcBoundRect( aBound
, pFly
->GetFormat()->GetAnchor().GetAnchorId());
1278 if ( pFly
->GetAnchorFrame()->IsVertical() )
1279 aRet
.setWidth( aBound
.Width() );
1281 aRet
.setHeight( aBound
.Height() );
1286 bool SwFEShell::IsFrameVertical(const bool bEnvironment
, bool& bRTL
, bool& bVertL2R
) const
1292 if ( Imp()->HasDrawView() )
1294 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1295 if( rMrkList
.GetMarkCount() != 1 )
1298 SdrObject
* pObj
= rMrkList
.GetMark( 0 )->GetMarkedSdrObj();
1301 OSL_FAIL( "<SwFEShell::IsFrameVertical(..)> - missing SdrObject instance in marked object list -> This is a serious situation" );
1305 SwContact
* pContact
= GetUserCall( pObj
);
1308 OSL_FAIL( "<SwFEShell::IsFrameVertical(..)> - missing SwContact instance at marked object -> This is a serious situation" );
1311 const SwFrame
* pRef
= pContact
->GetAnchoredObj( pObj
)->GetAnchorFrame();
1314 OSL_FAIL( "<SwFEShell::IsFrameVertical(..)> - missing anchor frame at marked object -> This is a serious situation" );
1318 if ( !bEnvironment
)
1319 if ( auto pVirtFly
= dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) )
1320 pRef
= pVirtFly
->GetFlyFrame();
1322 bVert
= pRef
->IsVertical();
1323 bRTL
= pRef
->IsRightToLeft();
1324 bVertL2R
= pRef
->IsVertLR();
1330 void SwFEShell::MoveObjectIfActive( svt::EmbeddedObjectRef
&, const Point
& )
1332 // does not do anything, only avoids crash if the method is used for wrong shell
1335 void SwFEShell::ToggleHeaderFooterEdit()
1337 // Clear objects selection
1338 if ( Imp()->GetDrawView()->AreObjectsMarked() )
1340 Imp()->GetDrawView()->UnmarkAll();
1344 SwCursorShell::ToggleHeaderFooterEdit();
1347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */