Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / layout / sortedobjs.cxx
blobce581bb663eff33baa554aa4f6e2e960b1a36494
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 <sortedobjs.hxx>
22 #include <algorithm>
23 #include <anchoredobject.hxx>
24 #include <fmtanchr.hxx>
25 #include <fmtsrnd.hxx>
26 #include <fmtwrapinfluenceonobjpos.hxx>
27 #include <frmfmt.hxx>
28 #include <pam.hxx>
29 #include <svx/svdobj.hxx>
30 #include <IDocumentDrawModelAccess.hxx>
31 #include <osl/diagnose.h>
33 using namespace ::com::sun::star;
35 SwSortedObjs::SwSortedObjs()
39 SwSortedObjs::~SwSortedObjs()
43 size_t SwSortedObjs::size() const
45 return maSortedObjLst.size();
48 SwAnchoredObject* SwSortedObjs::operator[]( size_t _nIndex ) const
50 SwAnchoredObject* pAnchoredObj = nullptr;
52 if ( _nIndex >= size() )
54 OSL_FAIL( "<SwSortedObjs::operator[]> - index out of range" );
56 else
58 pAnchoredObj = maSortedObjLst[ _nIndex ];
61 return pAnchoredObj;
64 namespace
66 int GetAnchorWeight(RndStdIds eAnchor)
68 if (eAnchor == RndStdIds::FLY_AT_CHAR)
69 return 0;
70 if (eAnchor == RndStdIds::FLY_AS_CHAR)
71 return 1;
72 return 2;
75 struct ObjAnchorOrder
77 bool operator()( const SwAnchoredObject* _pListedAnchoredObj,
78 const SwAnchoredObject* _pNewAnchoredObj )
80 // get attributes of listed object
81 const SwFrameFormat& rFormatListed = _pListedAnchoredObj->GetFrameFormat();
82 const SwFormatAnchor* pAnchorListed = &(rFormatListed.GetAnchor());
84 // get attributes of new object
85 const SwFrameFormat& rFormatNew = _pNewAnchoredObj->GetFrameFormat();
86 const SwFormatAnchor* pAnchorNew = &(rFormatNew.GetAnchor());
88 // check for to-page anchored objects
89 if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_PAGE) &&
90 (pAnchorNew ->GetAnchorId() != RndStdIds::FLY_AT_PAGE))
92 return true;
94 else if ((pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_PAGE) &&
95 (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_PAGE))
97 return false;
99 else if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_PAGE) &&
100 (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_PAGE))
102 return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
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))
110 return true;
112 else if ((pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_FLY) &&
113 (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_FLY))
115 return false;
117 else if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_FLY) &&
118 (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_FLY))
120 return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
123 // Both objects aren't anchor to page or to fly
124 // Thus, compare content anchor nodes, if existing.
125 const SwNode* pContentAnchorListed = pAnchorListed->GetAnchorNode();
126 const SwNode* pContentAnchorNew = pAnchorNew->GetAnchorNode();
127 if ( pContentAnchorListed && pContentAnchorNew &&
128 *pContentAnchorListed != *pContentAnchorNew )
130 return *pContentAnchorListed < *pContentAnchorNew;
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)
139 sal_Int32 nListedIndex = pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_PARA ?
140 pAnchorListed->GetAnchorContentOffset() : 0;
141 sal_Int32 nNewIndex = pAnchorNew->GetAnchorId() != RndStdIds::FLY_AT_PARA ?
142 pAnchorNew->GetAnchorContentOffset() : 0;
143 if (nListedIndex != nNewIndex)
145 return nListedIndex < nNewIndex;
149 int nAnchorListedWeight = GetAnchorWeight(pAnchorListed->GetAnchorId());
150 int nAnchorNewWeight = GetAnchorWeight(pAnchorNew->GetAnchorId());
151 if (nAnchorListedWeight != nAnchorNewWeight)
153 return nAnchorListedWeight < nAnchorNewWeight;
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 )
172 return !bWrapThroughOrHellListed;
174 else if ( bWrapThroughOrHellListed && bWrapThroughOrHellNew )
176 return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
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 ) )
189 // #i35017# - constant name has changed
190 return pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true )
191 == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE;
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();
203 bool SwSortedObjs::is_sorted() const
205 return std::is_sorted(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
208 bool SwSortedObjs::Insert( SwAnchoredObject& _rAnchoredObj )
210 if (!is_sorted())
212 SAL_WARN("sw.core", "SwSortedObjs::Insert: object list is not sorted");
213 UpdateAll();
216 // #i51941#
217 if ( Contains( _rAnchoredObj ) )
219 // list already contains object
220 OSL_FAIL( "<SwSortedObjs::Insert()> - already contains object" );
221 return true;
224 // find insert position
225 std::vector< SwAnchoredObject* >::iterator aInsPosIter =
226 std::lower_bound( maSortedObjLst.begin(), maSortedObjLst.end(),
227 &_rAnchoredObj, ObjAnchorOrder() );
229 // insert object into list
230 maSortedObjLst.insert( aInsPosIter, &_rAnchoredObj );
232 return Contains( _rAnchoredObj );
235 void SwSortedObjs::Remove( SwAnchoredObject& _rAnchoredObj )
237 std::vector< SwAnchoredObject* >::iterator aDelPosIter =
238 std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
240 if ( aDelPosIter == maSortedObjLst.end() )
242 // object not found.
243 OSL_FAIL( "<SwSortedObjs::Remove()> - object not found" );
245 else
247 maSortedObjLst.erase( aDelPosIter );
251 bool SwSortedObjs::Contains( const SwAnchoredObject& _rAnchoredObj ) const
253 std::vector< SwAnchoredObject* >::const_iterator aIter =
254 std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
256 return aIter != maSortedObjLst.end();
259 void SwSortedObjs::Update( SwAnchoredObject& _rAnchoredObj )
261 if ( !Contains( _rAnchoredObj ) )
263 // given anchored object not found in list
264 OSL_FAIL( "<SwSortedObjs::Update(..) - sorted list doesn't contain given anchored object" );
265 return;
268 if ( size() == 1 )
270 // given anchored object is the only one in the list.
271 return;
274 Remove( _rAnchoredObj );
275 Insert( _rAnchoredObj );
278 void SwSortedObjs::UpdateAll()
280 std::stable_sort(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
283 size_t SwSortedObjs::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
285 std::vector< SwAnchoredObject* >::const_iterator aIter =
286 std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
288 if ( aIter != maSortedObjLst.end() )
290 // #i51941#
291 std::vector< SwAnchoredObject* >::difference_type nPos =
292 aIter - maSortedObjLst.begin();
293 return static_cast<size_t>( nPos );
296 return size();
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */