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 <sortedobjs.hxx>
23 #include <anchoredobject.hxx>
24 #include <fmtanchr.hxx>
25 #include <fmtsrnd.hxx>
26 #include <fmtwrapinfluenceonobjpos.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" );
58 pAnchoredObj
= maSortedObjLst
[ _nIndex
];
66 int GetAnchorWeight(RndStdIds eAnchor
)
68 if (eAnchor
== RndStdIds::FLY_AT_CHAR
)
70 if (eAnchor
== RndStdIds::FLY_AS_CHAR
)
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
))
94 else if ((pAnchorListed
->GetAnchorId() != RndStdIds::FLY_AT_PAGE
) &&
95 (pAnchorNew
->GetAnchorId() == RndStdIds::FLY_AT_PAGE
))
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
))
112 else if ((pAnchorListed
->GetAnchorId() != RndStdIds::FLY_AT_FLY
) &&
113 (pAnchorNew
->GetAnchorId() == RndStdIds::FLY_AT_FLY
))
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
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
)
212 SAL_WARN("sw.core", "SwSortedObjs::Insert: object list is not sorted");
217 if ( Contains( _rAnchoredObj
) )
219 // list already contains object
220 OSL_FAIL( "<SwSortedObjs::Insert()> - already contains object" );
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() )
243 OSL_FAIL( "<SwSortedObjs::Remove()> - object not found" );
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" );
270 // given anchored object is the only one in the list.
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() )
291 std::vector
< SwAnchoredObject
* >::difference_type nPos
=
292 aIter
- maSortedObjLst
.begin();
293 return static_cast<size_t>( nPos
);
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */