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