LibreOffice Module sw (master) 1
objectformatter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
23#include <sortedobjs.hxx>
24#include <rootfrm.hxx>
25#include <pagefrm.hxx>
26#include <flyfrms.hxx>
27#include <txtfrm.hxx>
28#include <layact.hxx>
30#include <osl/diagnose.h>
31
32#include <vector>
33
34// --> #i26945# - Additionally the type of the anchor text frame
35// is collected - by type is meant 'master' or 'follow'.
37{
38 private:
39 struct tEntry
40 {
44 };
45
46 std::vector< tEntry > maObjList;
47
48 public:
50 {
51 }
52
53 void Collect( SwAnchoredObject& _rAnchoredObj )
54 {
55 tEntry aNewEntry;
56 aNewEntry.mpAnchoredObj = &_rAnchoredObj;
57 // #i33751#, #i34060# - method <GetPageFrameOfAnchor()>
58 // is replaced by method <FindPageFrameOfAnchor()>. It's return value
59 // have to be checked.
60 SwPageFrame* pPageFrameOfAnchor = _rAnchoredObj.FindPageFrameOfAnchor();
61 if ( pPageFrameOfAnchor )
62 {
63 aNewEntry.mnPageNumOfAnchor = pPageFrameOfAnchor->GetPhyPageNum();
64 }
65 else
66 {
67 aNewEntry.mnPageNumOfAnchor = 0;
68 }
69 // --> #i26945# - collect type of anchor
70 SwTextFrame* pAnchorCharFrame = _rAnchoredObj.FindAnchorCharFrame();
71 if ( pAnchorCharFrame )
72 {
73 aNewEntry.mbAnchoredAtMaster = !pAnchorCharFrame->IsFollow();
74 }
75 else
76 {
77 aNewEntry.mbAnchoredAtMaster = true;
78 }
79 maObjList.push_back( aNewEntry );
80 }
81
82 SwAnchoredObject* operator[]( sal_uInt32 _nIndex )
83 {
84 return maObjList[_nIndex].mpAnchoredObj;
85 }
86
87 sal_uInt32 GetPageNum( sal_uInt32 _nIndex ) const
88 {
89 return maObjList[_nIndex].mnPageNumOfAnchor;
90 }
91
92 // --> #i26945#
93 bool AnchoredAtMaster( sal_uInt32 _nIndex )
94 {
95 return maObjList[_nIndex].mbAnchoredAtMaster;
96 }
97
98 sal_uInt32 Count() const
99 {
100 return maObjList.size();
101 }
102};
103
105 SwLayAction* _pLayAction,
106 const bool _bCollectPgNumOfAnchors )
107 : mrPageFrame( _rPageFrame ),
108 mbConsiderWrapOnObjPos( _rPageFrame.GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) ),
109 mpLayAction( _pLayAction ),
110 // --> #i26945#
111 mpPgNumAndTypeOfAnchors( _bCollectPgNumOfAnchors ? new SwPageNumAndTypeOfAnchors() : nullptr )
112{
113}
114
116{
117}
118
119std::unique_ptr<SwObjectFormatter> SwObjectFormatter::CreateObjFormatter(
120 SwFrame& _rAnchorFrame,
121 const SwPageFrame& _rPageFrame,
122 SwLayAction* _pLayAction )
123{
124 std::unique_ptr<SwObjectFormatter> pObjFormatter;
125 if ( _rAnchorFrame.IsTextFrame() )
126 {
128 static_cast<SwTextFrame&>(_rAnchorFrame),
129 _rPageFrame, _pLayAction );
130 }
131 else if ( _rAnchorFrame.IsLayoutFrame() )
132 {
134 static_cast<SwLayoutFrame&>(_rAnchorFrame),
135 _rPageFrame, _pLayAction );
136 }
137 else
138 {
139 OSL_FAIL( "<SwObjectFormatter::CreateObjFormatter(..)> - unexpected type of anchor frame" );
140 }
141
142 return pObjFormatter;
143}
144
148 const SwPageFrame& _rPageFrame,
149 SwLayAction* _pLayAction )
150{
151 bool bSuccess( true );
152
153 // create corresponding object formatter
154 std::unique_ptr<SwObjectFormatter> pObjFormatter =
155 SwObjectFormatter::CreateObjFormatter( _rAnchorFrame, _rPageFrame, _pLayAction );
156
157 if ( pObjFormatter )
158 {
159 // format anchored floating screen objects
160 bSuccess = pObjFormatter->DoFormatObjs();
161 }
162
163 return bSuccess;
164}
165
169 SwFrame* _pAnchorFrame,
170 const SwPageFrame* _pPageFrame )
171{
172 bool bSuccess( true );
173
174 OSL_ENSURE( _pAnchorFrame || _rAnchoredObj.GetAnchorFrame(),
175 "<SwObjectFormatter::FormatObj(..)> - missing anchor frame" );
176 SwFrame& rAnchorFrame = _pAnchorFrame ? *_pAnchorFrame : *(_rAnchoredObj.AnchorFrame());
177
178 OSL_ENSURE( _pPageFrame || rAnchorFrame.FindPageFrame(),
179 "<SwObjectFormatter::FormatObj(..)> - missing page frame" );
180 const SwPageFrame& rPageFrame = _pPageFrame ? *_pPageFrame : *(rAnchorFrame.FindPageFrame());
181
182 // create corresponding object formatter
183 std::unique_ptr<SwObjectFormatter> pObjFormatter =
184 SwObjectFormatter::CreateObjFormatter( rAnchorFrame, rPageFrame, nullptr/*_pLayAction*/ );
185
186 if ( pObjFormatter )
187 {
188 // format given floating screen object
189 // --> #i40147# - check for moved forward anchor frame
190 bSuccess = pObjFormatter->DoFormatObj( _rAnchoredObj, true );
191 }
192
193 return bSuccess;
194}
195
206{
207 _rLayoutFrame.Calc(_rLayoutFrame.getRootFrame()->GetCurrShell()->GetOut());
208
209 SwFrame* pLowerFrame = _rLayoutFrame.Lower();
210 while ( pLowerFrame )
211 {
212 if ( pLowerFrame->IsLayoutFrame() )
213 {
214 FormatLayout_( *static_cast<SwLayoutFrame*>(pLowerFrame) );
215 }
216 pLowerFrame = pLowerFrame->GetNext();
217 }
218}
219
226{
227 if ( !_rAnchoredObj.DynCastFlyFrame() )
228 {
229 // only Writer fly frames have content
230 return;
231 }
232
233 SwFlyFrame& rFlyFrame = static_cast<SwFlyFrame&>(_rAnchoredObj);
234 SwContentFrame* pContent = rFlyFrame.ContainsContent();
235
236 while ( pContent )
237 {
238 // format content
239 pContent->OptCalc();
240
241 // format floating screen objects at content text frame
242 // #i23129#, #i36347# - pass correct page frame to
243 // the object formatter
244 if ( pContent->IsTextFrame() &&
246 *(pContent->FindPageFrame()),
247 GetLayAction() ) )
248 {
249 // restart format with first content
250 pContent = rFlyFrame.ContainsContent();
251 continue;
252 }
253
254 // continue with next content
255 pContent = pContent->GetNextContentFrame();
256 }
257}
258
264{
265 // collect anchor object and its 'anchor' page number, if requested
267 {
268 mpPgNumAndTypeOfAnchors->Collect( _rAnchoredObj );
269 }
270
271 if ( auto pFlyFrame = _rAnchoredObj.DynCastFlyFrame() )
272 {
273 // --> #i34753# - reset flag, which prevents a positioning
274 if ( pFlyFrame->IsFlyLayFrame() )
275 {
276 static_cast<SwFlyLayFrame*>(pFlyFrame)->SetNoMakePos( false );
277 }
278
279 // #i81146# new loop control
280 int nLoopControlRuns = 0;
281 const int nLoopControlMax = 15;
282
283 do {
284 if ( mpLayAction )
285 {
286 mpLayAction->FormatLayoutFly( pFlyFrame );
287 // --> consider, if the layout action
288 // has to be restarted due to a delete of a page frame.
289 if ( mpLayAction->IsAgain() )
290 {
291 break;
292 }
293 }
294 else
295 {
296 FormatLayout_( *pFlyFrame );
297 }
298 // --> #i34753# - prevent further positioning, if
299 // to-page|to-fly anchored Writer fly frame is already clipped.
300 if ( pFlyFrame->IsFlyLayFrame() && pFlyFrame->IsClipped() )
301 {
302 static_cast<SwFlyLayFrame*>(pFlyFrame)->SetNoMakePos( true );
303 }
304 // #i23129#, #i36347# - pass correct page frame
305 // to the object formatter
307 *(pFlyFrame->FindPageFrame()),
308 mpLayAction );
309 if ( mpLayAction )
310 {
311 mpLayAction->FormatFlyContent( pFlyFrame );
312 // --> consider, if the layout action
313 // has to be restarted due to a delete of a page frame.
314 if ( mpLayAction->IsAgain() )
315 {
316 break;
317 }
318 }
319 else
320 {
321 FormatObjContent( *pFlyFrame );
322 }
323
324 if ( ++nLoopControlRuns >= nLoopControlMax )
325 {
326 OSL_FAIL( "LoopControl in SwObjectFormatter::FormatObj_: Stage 3!!!" );
327 pFlyFrame->ValidateThisAndAllLowers( 2 );
328 nLoopControlRuns = 0;
329 }
330
331 // --> #i57917#
332 // stop formatting of anchored object, if restart of layout process is requested.
333 } while ( !pFlyFrame->isFrameAreaDefinitionValid() &&
334 !_rAnchoredObj.RestartLayoutProcess() &&
335 pFlyFrame->GetAnchorFrame() == &GetAnchorFrame() );
336 }
337 else if ( dynamic_cast<const SwAnchoredDrawObject*>( &_rAnchoredObj) != nullptr )
338 {
339 _rAnchoredObj.MakeObjPos();
340 }
341}
342
353{
354 // --> #i26945#
355 SwFrame* pAnchorFrame( nullptr );
356 if ( GetAnchorFrame().IsTextFrame() &&
357 static_cast<SwTextFrame&>(GetAnchorFrame()).IsFollow() &&
358 _pMasterTextFrame )
359 {
360 pAnchorFrame = _pMasterTextFrame;
361 }
362 else
363 {
364 pAnchorFrame = &GetAnchorFrame();
365 }
366 if ( !pAnchorFrame->GetDrawObjs() )
367 {
368 // nothing to do, if no floating screen object is registered at the anchor frame.
369 return true;
370 }
371
372 bool bSuccess( true );
373
374 for ( size_t i = 0; i < pAnchorFrame->GetDrawObjs()->size(); ++i )
375 {
376 SwAnchoredObject* pAnchoredObj = (*pAnchorFrame->GetDrawObjs())[i];
377
378 // check, if object's anchor is on the given page frame or
379 // object is registered at the given page frame.
380 // --> #i26945# - check, if the anchor character of the
381 // anchored object is located in a follow text frame. If this anchor
382 // follow text frame differs from the given anchor frame, the given
383 // anchor frame is a 'master' text frame of the anchor follow text frame.
384 // If the anchor follow text frame is in the same body as its 'master'
385 // text frame, do not format the anchored object.
386 // E.g., this situation can occur during the table row splitting algorithm.
387 SwTextFrame* pAnchorCharFrame = pAnchoredObj->FindAnchorCharFrame();
388 const bool bAnchoredAtFollowInSameBodyAsMaster =
389 pAnchorCharFrame && pAnchorCharFrame->IsFollow() &&
390 pAnchorCharFrame != pAnchoredObj->GetAnchorFrame() &&
391 pAnchorCharFrame->FindBodyFrame() ==
392 static_cast<SwTextFrame*>(pAnchoredObj->AnchorFrame())->FindBodyFrame();
393 if ( bAnchoredAtFollowInSameBodyAsMaster )
394 {
395 continue;
396 }
397 // #i33751#, #i34060# - method <GetPageFrameOfAnchor()>
398 // is replaced by method <FindPageFrameOfAnchor()>. It's return value
399 // have to be checked.
400 SwPageFrame* pPageFrameOfAnchor = pAnchoredObj->FindPageFrameOfAnchor();
401 OSL_ENSURE( pPageFrameOfAnchor,
402 "<SwObjectFormatter::FormatObjsAtFrame_()> - missing page frame." );
403 // --> #i26945#
404 if ( pPageFrameOfAnchor && pPageFrameOfAnchor == &mrPageFrame )
405 {
406 // if format of object fails, stop formatting and pass fail to
407 // calling method via the return value.
408 if ( !DoFormatObj( *pAnchoredObj ) )
409 {
410 bSuccess = false;
411 break;
412 }
413
414 // considering changes at <pAnchorFrame->GetDrawObjs()> during
415 // format of the object.
416 if ( !pAnchorFrame->GetDrawObjs() ||
417 i > pAnchorFrame->GetDrawObjs()->size() )
418 {
419 break;
420 }
421 else
422 {
423 const size_t nActPosOfObj =
424 pAnchorFrame->GetDrawObjs()->ListPosOf( *pAnchoredObj );
425 if ( nActPosOfObj == pAnchorFrame->GetDrawObjs()->size() ||
426 nActPosOfObj > i )
427 {
428 --i;
429 }
430 else if ( nActPosOfObj < i )
431 {
432 i = nActPosOfObj;
433 }
434 }
435 }
436 } // end of loop on <pAnchorFrame->.GetDrawObjs()>
437
438 return bSuccess;
439}
440
446{
447 return mpPgNumAndTypeOfAnchors ? (*mpPgNumAndTypeOfAnchors)[_nIndex] : nullptr;
448}
449
454sal_uInt32 SwObjectFormatter::GetPgNumOfCollected( const sal_uInt32 _nIndex )
455{
456 return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->GetPageNum(_nIndex) : 0;
457}
458
464{
465 return mpPgNumAndTypeOfAnchors == nullptr
466 || mpPgNumAndTypeOfAnchors->AnchoredAtMaster(_nIndex);
467}
468
474{
476}
477
478/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ CONSIDER_WRAP_ON_OBJECT_POSITION
class for the positioning of drawing objects
wrapper class for the positioning of Writer fly frames and drawing objects
const SwFrame * GetAnchorFrame() const
SwTextFrame * FindAnchorCharFrame()
get frame, which contains the anchor character, if the object is anchored at-character or as-characte...
SwFrame * AnchorFrame()
bool RestartLayoutProcess() const
virtual void MakeObjPos()=0
method to determine position for the object and set the position at the object
SwPageFrame * FindPageFrameOfAnchor()
method to determine the page frame, on which the 'anchor' of the given anchored object is.
virtual const SwFlyFrame * DynCastFlyFrame() const
SwContentFrame is the layout for content nodes: a common base class for text (paragraph) and non-text...
Definition: cntfrm.hxx:59
SwContentFrame * GetNextContentFrame() const
Definition: cntfrm.hxx:120
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
Flys that are bound to layout frames (to-frame) and not to/as content.
Definition: flyfrms.hxx:151
Base class of the Writer layout elements.
Definition: frame.hxx:315
const SwBodyFrame * FindBodyFrame() const
Definition: frame.hxx:1126
bool IsTextFrame() const
Definition: frame.hxx:1240
SwFrame * GetNext()
Definition: frame.hxx:682
void OptCalc() const
Definition: frame.hxx:1086
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1799
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:568
SwRootFrame * getRootFrame()
Definition: frame.hxx:685
SwPageFrame * FindPageFrame()
Definition: frame.hxx:686
bool IsLayoutFrame() const
Definition: frame.hxx:1176
The usage of LayAction is always the same:
Definition: layact.hxx:59
void FormatLayoutFly(SwFlyFrame *)
Definition: layact.cxx:1455
bool IsAgain() const
Definition: layact.hxx:170
void FormatFlyContent(const SwFlyFrame *)
Definition: layact.cxx:1925
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame.
Definition: layfrm.hxx:36
const SwContentFrame * ContainsContent() const
Checks if the frame contains one or more ContentFrame's anywhere in his subsidiary structure; if so t...
Definition: findfrm.cxx:72
const SwFrame * Lower() const
Definition: layfrm.hxx:101
static std::unique_ptr< SwObjectFormatterLayFrame > CreateObjFormatter(SwLayoutFrame &_rAnchorLayFrame, const SwPageFrame &_rPageFrame, SwLayAction *_pLayAction)
static std::unique_ptr< SwObjectFormatterTextFrame > CreateObjFormatter(SwTextFrame &_rAnchorTextFrame, const SwPageFrame &_rPageFrame, SwLayAction *_pLayAction)
method to create an instance of <SwObjectFormatterTextFrame> is necessary.
SwLayAction * GetLayAction()
virtual bool DoFormatObj(SwAnchoredObject &_rAnchoredObj, const bool _bCheckForMovedFwd=false)=0
intrinsic method to format a certain floating screen object
static std::unique_ptr< SwObjectFormatter > CreateObjFormatter(SwFrame &_rAnchorFrame, const SwPageFrame &_rPageFrame, SwLayAction *_pLayAction)
virtual SwFrame & GetAnchorFrame()=0
SwAnchoredObject * GetCollectedObj(const sal_uInt32 _nIndex)
accessor to collected anchored object
void FormatObj_(SwAnchoredObject &_rAnchoredObj)
performs the intrinsic format of a given floating screen object and its content.
bool FormatObjsAtFrame_(SwTextFrame *_pMasterTextFrame=nullptr)
invokes the intrinsic format method for all floating screen objects, anchored at anchor frame on the ...
static bool FormatObjsAtFrame(SwFrame &_rAnchorFrame, const SwPageFrame &_rPageFrame, SwLayAction *_pLayAction=nullptr)
method to format all floating screen objects at the given anchor frame
virtual ~SwObjectFormatter()
static bool FormatObj(SwAnchoredObject &_rAnchoredObj, SwFrame *_pAnchorFrame=nullptr, const SwPageFrame *_pPageFrame=nullptr)
method to format a given floating screen object
SwObjectFormatter(const SwPageFrame &_rPageFrame, SwLayAction *_pLayAction, const bool _bCollectPgNumOfAnchors=false)
const SwPageFrame & mrPageFrame
void FormatObjContent(SwAnchoredObject &_rAnchoredObj)
helper method for method <FormatObj_(..)> - performs the intrinsic format of the content of the given...
void FormatLayout_(SwLayoutFrame &_rLayoutFrame)
helper method for method <FormatObj_(..)> - performs the intrinsic format of the layout of the given ...
sal_uInt32 GetPgNumOfCollected(const sal_uInt32 _nIndex)
accessor to 'anchor' page number of collected anchored object
SwLayAction * mpLayAction
bool IsCollectedAnchoredAtMaster(const sal_uInt32 _nIndex)
accessor to 'anchor' type of collected anchored object
sal_uInt32 CountOfCollected()
accessor to total number of collected anchored objects
std::unique_ptr< SwPageNumAndTypeOfAnchors > mpPgNumAndTypeOfAnchors
A page of the document layout.
Definition: pagefrm.hxx:60
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:209
std::vector< tEntry > maObjList
sal_uInt32 GetPageNum(sal_uInt32 _nIndex) const
SwAnchoredObject * operator[](sal_uInt32 _nIndex)
void Collect(SwAnchoredObject &_rAnchoredObj)
bool AnchoredAtMaster(sal_uInt32 _nIndex)
sal_uInt32 Count() const
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:215
size_t size() const
Definition: sortedobjs.cxx:43
size_t ListPosOf(const SwAnchoredObject &_rAnchoredObj) const
Position of object <_rAnchoredObj> in sorted list.
Definition: sortedobjs.cxx:277
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:365
virtual SotClipboardFormatId GetFormat(const TransferableDataHelper &aHelper) override
size
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)