LibreOffice Module sw (master)  1
sortedobjs.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 
20 #include <sortedobjs.hxx>
21 
22 #include <algorithm>
23 #include <anchoredobject.hxx>
24 #include <fmtanchr.hxx>
25 #include <fmtsrnd.hxx>
27 #include <frmfmt.hxx>
28 #include <pam.hxx>
29 #include <svx/svdobj.hxx>
31 
32 using namespace ::com::sun::star;
33 
35 {
36 }
37 
39 {
40 }
41 
42 size_t SwSortedObjs::size() const
43 {
44  return maSortedObjLst.size();
45 }
46 
48 {
49  SwAnchoredObject* pAnchoredObj = nullptr;
50 
51  if ( _nIndex >= size() )
52  {
53  OSL_FAIL( "<SwSortedObjs::operator[]> - index out of range" );
54  }
55  else
56  {
57  pAnchoredObj = maSortedObjLst[ _nIndex ];
58  }
59 
60  return pAnchoredObj;
61 }
62 
63 namespace
64 {
65  int GetAnchorWeight(RndStdIds eAnchor)
66  {
67  if (eAnchor == RndStdIds::FLY_AT_CHAR)
68  return 0;
69  if (eAnchor == RndStdIds::FLY_AS_CHAR)
70  return 1;
71  return 2;
72  }
73 
74 struct ObjAnchorOrder
75 {
76  bool operator()( const SwAnchoredObject* _pListedAnchoredObj,
77  const SwAnchoredObject* _pNewAnchoredObj )
78  {
79  // get attributes of listed object
80  const SwFrameFormat& rFormatListed = _pListedAnchoredObj->GetFrameFormat();
81  const SwFormatAnchor* pAnchorListed = &(rFormatListed.GetAnchor());
82 
83  // get attributes of new object
84  const SwFrameFormat& rFormatNew = _pNewAnchoredObj->GetFrameFormat();
85  const SwFormatAnchor* pAnchorNew = &(rFormatNew.GetAnchor());
86 
87  // check for to-page anchored objects
88  if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_PAGE) &&
89  (pAnchorNew ->GetAnchorId() != RndStdIds::FLY_AT_PAGE))
90  {
91  return true;
92  }
93  else if ((pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_PAGE) &&
94  (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_PAGE))
95  {
96  return false;
97  }
98  else if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_PAGE) &&
99  (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_PAGE))
100  {
101  return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
102  }
103 
104  // Both objects aren't anchored to page.
105  // Thus, check for to-fly anchored objects
106  if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_FLY) &&
107  (pAnchorNew ->GetAnchorId() != RndStdIds::FLY_AT_FLY))
108  {
109  return true;
110  }
111  else if ((pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_FLY) &&
112  (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_FLY))
113  {
114  return false;
115  }
116  else if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_FLY) &&
117  (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_FLY))
118  {
119  return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
120  }
121 
122  // Both objects aren't anchor to page or to fly
123  // Thus, compare content anchor nodes, if existing.
124  const SwPosition* pContentAnchorListed = pAnchorListed->GetContentAnchor();
125  const SwPosition* pContentAnchorNew = pAnchorNew->GetContentAnchor();
126  if ( pContentAnchorListed && pContentAnchorNew &&
127  pContentAnchorListed->nNode != pContentAnchorNew->nNode )
128  {
129  return pContentAnchorListed->nNode < pContentAnchorNew->nNode;
130  }
131 
132  // objects anchored at the same content.
133  // --> OD 2006-11-29 #???# - objects have to be ordered by anchor node position
134  // Thus, compare content anchor node positions and anchor type,
135  // if not anchored at-paragraph
136  if (pContentAnchorListed && pContentAnchorNew)
137  {
138  sal_Int32 nListedIndex = pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_PARA ?
139  pContentAnchorListed->nContent.GetIndex() : 0;
140  sal_Int32 nNewIndex = pAnchorNew->GetAnchorId() != RndStdIds::FLY_AT_PARA ?
141  pContentAnchorNew->nContent.GetIndex() : 0;
142  if (nListedIndex != nNewIndex)
143  {
144  return nListedIndex < nNewIndex;
145  }
146  }
147 
148  int nAnchorListedWeight = GetAnchorWeight(pAnchorListed->GetAnchorId());
149  int nAnchorNewWeight = GetAnchorWeight(pAnchorNew->GetAnchorId());
150  if (nAnchorListedWeight != nAnchorNewWeight)
151  {
152  return nAnchorListedWeight < nAnchorNewWeight;
153  }
154 
155  // objects anchored at the same content and at the same content anchor
156  // node position with the same anchor type
157  // Thus, compare its wrapping style including its layer
158  const IDocumentDrawModelAccess& rIDDMA = rFormatListed.getIDocumentDrawModelAccess();
159  const SdrLayerID nHellId = rIDDMA.GetHellId();
160  const SdrLayerID nInvisibleHellId = rIDDMA.GetInvisibleHellId();
161  const bool bWrapThroughOrHellListed =
162  rFormatListed.GetSurround().GetSurround() == css::text::WrapTextMode_THROUGH ||
163  _pListedAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
164  _pListedAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
165  const bool bWrapThroughOrHellNew =
166  rFormatNew.GetSurround().GetSurround() == css::text::WrapTextMode_THROUGH ||
167  _pNewAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
168  _pNewAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
169  if ( bWrapThroughOrHellListed != bWrapThroughOrHellNew )
170  {
171  return !bWrapThroughOrHellListed;
172  }
173  else if ( bWrapThroughOrHellListed && bWrapThroughOrHellNew )
174  {
175  return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
176  }
177 
178  // objects anchored at the same content with a set text wrapping
179  // Thus, compare wrap influences on object position
180  const SwFormatWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosListed =
181  &(rFormatListed.GetWrapInfluenceOnObjPos());
182  const SwFormatWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosNew =
183  &(rFormatNew.GetWrapInfluenceOnObjPos());
184  // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
185  if ( pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true ) !=
186  pWrapInfluenceOnObjPosNew->GetWrapInfluenceOnObjPos( true ) )
187  {
188  // #i35017# - constant name has changed
189  return pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true )
190  == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE;
191  }
192 
193  // objects anchored at the same content position/page/fly with same
194  // wrap influence.
195  // Thus, compare anchor order number
196  return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
197  }
198 };
199 
200 }
201 
203 {
204  return std::is_sorted(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
205 }
206 
208 {
209  // #i51941#
210  if ( Contains( _rAnchoredObj ) )
211  {
212  // list already contains object
213  OSL_FAIL( "<SwSortedObjs::Insert()> - already contains object" );
214  return true;
215  }
216 
217  // find insert position
218  std::vector< SwAnchoredObject* >::iterator aInsPosIter =
219  std::lower_bound( maSortedObjLst.begin(), maSortedObjLst.end(),
220  &_rAnchoredObj, ObjAnchorOrder() );
221 
222  // insert object into list
223  maSortedObjLst.insert( aInsPosIter, &_rAnchoredObj );
224 
225  return Contains( _rAnchoredObj );
226 }
227 
229 {
230  std::vector< SwAnchoredObject* >::iterator aDelPosIter =
231  std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
232 
233  if ( aDelPosIter == maSortedObjLst.end() )
234  {
235  // object not found.
236  OSL_FAIL( "<SwSortedObjs::Remove()> - object not found" );
237  }
238  else
239  {
240  maSortedObjLst.erase( aDelPosIter );
241  }
242 }
243 
244 bool SwSortedObjs::Contains( const SwAnchoredObject& _rAnchoredObj ) const
245 {
246  std::vector< SwAnchoredObject* >::const_iterator aIter =
247  std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
248 
249  return aIter != maSortedObjLst.end();
250 }
251 
253 {
254  if ( !Contains( _rAnchoredObj ) )
255  {
256  // given anchored object not found in list
257  OSL_FAIL( "<SwSortedObjs::Update(..) - sorted list doesn't contain given anchored object" );
258  return;
259  }
260 
261  if ( size() == 1 )
262  {
263  // given anchored object is the only one in the list.
264  return;
265  }
266 
267  Remove( _rAnchoredObj );
268  Insert( _rAnchoredObj );
269 }
270 
272 {
273  std::stable_sort(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
274 }
275 
276 size_t SwSortedObjs::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
277 {
278  std::vector< SwAnchoredObject* >::const_iterator aIter =
279  std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
280 
281  if ( aIter != maSortedObjLst.end() )
282  {
283  // #i51941#
284  std::vector< SwAnchoredObject* >::difference_type nPos =
285  aIter - maSortedObjLst.begin();
286  return static_cast<size_t>( nPos );
287  }
288 
289  return size();
290 }
291 
292 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void UpdateAll()
Definition: sortedobjs.cxx:271
Marks a position in the document model.
Definition: pam.hxx:35
SwNodeIndex nNode
Definition: pam.hxx:37
bool is_sorted() const
Definition: sortedobjs.cxx:202
void Update(SwAnchoredObject &_rAnchoredObj)
method to update the position of the given anchored object in the sorted list
Definition: sortedobjs.cxx:252
wrapper class for the positioning of Writer fly frames and drawing objects
SwIndex nContent
Definition: pam.hxx:38
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
SwAnchoredObject * operator[](size_t _nIndex) const
direct access to the entries
Definition: sortedobjs.cxx:47
virtual SdrLayerID GetInvisibleHellId() const =0
Style of a layout element.
Definition: frmfmt.hxx:57
const SdrObject * GetDrawObj() const
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
void Remove(SwAnchoredObject &_rAnchoredObj)
Definition: sortedobjs.cxx:228
bool Insert(SwAnchoredObject &_rAnchoredObj)
Definition: sortedobjs.cxx:207
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
size_t size() const
Definition: sortedobjs.cxx:42
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
FlyAnchors.
Definition: fmtanchr.hxx:34
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
std::vector< SwAnchoredObject * > maSortedObjLst
Definition: sortedobjs.hxx:51
virtual SdrLayerID GetHellId() const =0
virtual SdrLayerID GetLayer() const
virtual SwFrameFormat & GetFrameFormat()=0
sal_uInt32 GetOrder() const
Definition: fmtanchr.hxx:69
sal_Int32 GetIndex() const
Definition: index.hxx:95
size_t ListPosOf(const SwAnchoredObject &_rAnchoredObj) const
Position of object <_rAnchoredObj> in sorted list.
Definition: sortedobjs.cxx:276
const SwFormatWrapInfluenceOnObjPos & GetWrapInfluenceOnObjPos(bool=true) const
bool Contains(const SwAnchoredObject &_rAnchoredObj) const
Definition: sortedobjs.cxx:244
RndStdIds
sal_Int16 GetWrapInfluenceOnObjPos(const bool _bIterativeAsOnceConcurrent=false) const
to control, if value has to be treated as
sal_uInt16 nPos
const IDocumentDrawModelAccess & getIDocumentDrawModelAccess() const
Provides access to the document draw model interface.
Definition: format.cxx:758