1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include <sortedobjsimpl.hxx>
27
28 #include <algorithm>
29 #include <anchoredobject.hxx>
30 #include <frmfmt.hxx>
31 #include <svx/svdobj.hxx>
32 #include <pam.hxx>
33 #include <txtfrm.hxx>
34 #include <ndtxt.hxx>
35 #include <fmtsrnd.hxx>
36 #include <fmtwrapinfluenceonobjpos.hxx>
37 #include <IDocumentDrawModelAccess.hxx>
38
39
40 using namespace ::com::sun::star;
41
42 typedef std::vector< SwAnchoredObject* >::iterator tIter;
43 typedef std::vector< SwAnchoredObject* >::const_iterator tConstIter;
44
45
SwSortedObjsImpl()46 SwSortedObjsImpl::SwSortedObjsImpl()
47 {
48 }
49
~SwSortedObjsImpl()50 SwSortedObjsImpl::~SwSortedObjsImpl()
51 {
52 }
53
Count() const54 sal_uInt32 SwSortedObjsImpl::Count() const
55 {
56 return maSortedObjLst.size();
57 }
58
operator [](sal_uInt32 _nIndex)59 SwAnchoredObject* SwSortedObjsImpl::operator[]( sal_uInt32 _nIndex )
60 {
61 SwAnchoredObject* pAnchoredObj = 0L;
62
63 if ( _nIndex >= Count() )
64 {
65 ASSERT( false, "<SwSortedObjsImpl::operator[]> - index out of range" );
66 }
67 else
68 {
69 pAnchoredObj = maSortedObjLst[ _nIndex ];
70 }
71
72 return pAnchoredObj;
73 }
74
75 struct ObjAnchorOrder
76 {
operator ()ObjAnchorOrder77 bool operator()( const SwAnchoredObject* _pListedAnchoredObj,
78 const SwAnchoredObject* _pNewAnchoredObj )
79 {
80 // get attributes of listed object
81 const SwFrmFmt& rFmtListed = _pListedAnchoredObj->GetFrmFmt();
82 const SwFmtAnchor* pAnchorListed = &(rFmtListed.GetAnchor());
83
84 // get attributes of new object
85 const SwFrmFmt& rFmtNew = _pNewAnchoredObj->GetFrmFmt();
86 const SwFmtAnchor* pAnchorNew = &(rFmtNew.GetAnchor());
87
88 // check for to-page anchored objects
89 if ((pAnchorListed->GetAnchorId() == FLY_AT_PAGE) &&
90 (pAnchorNew ->GetAnchorId() != FLY_AT_PAGE))
91 {
92 return true;
93 }
94 else if ((pAnchorListed->GetAnchorId() != FLY_AT_PAGE) &&
95 (pAnchorNew ->GetAnchorId() == FLY_AT_PAGE))
96 {
97 return false;
98 }
99 else if ((pAnchorListed->GetAnchorId() == FLY_AT_PAGE) &&
100 (pAnchorNew ->GetAnchorId() == 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() == FLY_AT_FLY) &&
108 (pAnchorNew ->GetAnchorId() != FLY_AT_FLY))
109 {
110 return true;
111 }
112 else if ((pAnchorListed->GetAnchorId() != FLY_AT_FLY) &&
113 (pAnchorNew ->GetAnchorId() == FLY_AT_FLY))
114 {
115 return false;
116 }
117 else if ((pAnchorListed->GetAnchorId() == FLY_AT_FLY) &&
118 (pAnchorNew ->GetAnchorId() == 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* pCntntAnchorListed = pAnchorListed->GetCntntAnchor();
126 const SwPosition* pCntntAnchorNew = pAnchorNew->GetCntntAnchor();
127 if ( pCntntAnchorListed && pCntntAnchorNew &&
128 pCntntAnchorListed->nNode != pCntntAnchorNew->nNode )
129 {
130 return pCntntAnchorListed->nNode < pCntntAnchorNew->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 ((pAnchorListed->GetAnchorId() != FLY_AT_PARA) &&
138 (pAnchorNew ->GetAnchorId() != FLY_AT_PARA) &&
139 pCntntAnchorListed && pCntntAnchorNew )
140 {
141 if ( pCntntAnchorListed->nContent != pCntntAnchorNew->nContent )
142 {
143 return pCntntAnchorListed->nContent < pCntntAnchorNew->nContent;
144 }
145 else if ((pAnchorListed->GetAnchorId() == FLY_AT_CHAR) &&
146 (pAnchorNew ->GetAnchorId() == FLY_AS_CHAR))
147 {
148 return true;
149 }
150 else if ((pAnchorListed->GetAnchorId() == FLY_AS_CHAR) &&
151 (pAnchorNew ->GetAnchorId() == FLY_AT_CHAR))
152 {
153 return false;
154 }
155 }
156 // <--
157
158 // objects anchored at the same content and at the same content anchor
159 // node position with the same anchor type
160 // Thus, compare its wrapping style including its layer
161 const IDocumentDrawModelAccess* pIDDMA = rFmtListed.getIDocumentDrawModelAccess();
162 const SdrLayerID nHellId = pIDDMA->GetHellId();
163 const SdrLayerID nInvisibleHellId = pIDDMA->GetInvisibleHellId();
164 const bool bWrapThroughOrHellListed =
165 rFmtListed.GetSurround().GetSurround() == SURROUND_THROUGHT ||
166 _pListedAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
167 _pListedAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
168 const bool bWrapThroughOrHellNew =
169 rFmtNew.GetSurround().GetSurround() == SURROUND_THROUGHT ||
170 _pNewAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
171 _pNewAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
172 if ( bWrapThroughOrHellListed != bWrapThroughOrHellNew )
173 {
174 if ( bWrapThroughOrHellListed )
175 return false;
176 else
177 return true;
178 }
179 else if ( bWrapThroughOrHellListed && bWrapThroughOrHellNew )
180 {
181 return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
182 }
183
184 // objects anchored at the same content with a set text wrapping
185 // Thus, compare wrap influences on object position
186 const SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosListed =
187 &(rFmtListed.GetWrapInfluenceOnObjPos());
188 const SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosNew =
189 &(rFmtNew.GetWrapInfluenceOnObjPos());
190 // --> OD 2004-10-18 #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
191 if ( pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true ) !=
192 pWrapInfluenceOnObjPosNew->GetWrapInfluenceOnObjPos( true ) )
193 // <--
194 {
195 // --> OD 2004-10-18 #i35017# - constant name has changed
196 if ( pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true )
197 == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE )
198 // <--
199 return true;
200 else
201 return false;
202 }
203
204 // objects anchored at the same content position/page/fly with same
205 // wrap influence.
206 // Thus, compare anchor order number
207 return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
208 }
209 };
210
Insert(SwAnchoredObject & _rAnchoredObj)211 bool SwSortedObjsImpl::Insert( SwAnchoredObject& _rAnchoredObj )
212 {
213 // --> OD 2005-08-18 #i51941#
214 if ( Contains( _rAnchoredObj ) )
215 {
216 // list already contains object
217 #if OSL_DEBUG_LEVEL > 1
218 ASSERT( false,
219 "<SwSortedObjsImpl::Insert()> - already contains object" );
220 #endif
221 return true;
222 }
223
224 // find insert position
225 tIter aInsPosIter = std::lower_bound( maSortedObjLst.begin(),
226 maSortedObjLst.end(),
227 &_rAnchoredObj, ObjAnchorOrder() );
228
229 // insert object into list
230 maSortedObjLst.insert( aInsPosIter, &_rAnchoredObj );
231
232 return Contains( _rAnchoredObj );
233 }
234
Remove(SwAnchoredObject & _rAnchoredObj)235 bool SwSortedObjsImpl::Remove( SwAnchoredObject& _rAnchoredObj )
236 {
237 bool bRet = true;
238
239 tIter aDelPosIter = std::find( maSortedObjLst.begin(),
240 maSortedObjLst.end(),
241 &_rAnchoredObj );
242
243 if ( aDelPosIter == maSortedObjLst.end() )
244 {
245 // object not found.
246 bRet = false;
247 #if OSL_DEBUG_LEVEL > 1
248 ASSERT( false,
249 "<SwSortedObjsImpl::Remove()> - object not found" );
250 #endif
251 }
252 else
253 {
254 maSortedObjLst.erase( aDelPosIter );
255 }
256
257 return bRet;
258 }
259
Contains(const SwAnchoredObject & _rAnchoredObj) const260 bool SwSortedObjsImpl::Contains( const SwAnchoredObject& _rAnchoredObj ) const
261 {
262 tConstIter aIter = std::find( maSortedObjLst.begin(), maSortedObjLst.end(),
263 &_rAnchoredObj );
264
265 return aIter != maSortedObjLst.end();
266 }
267
Update(SwAnchoredObject & _rAnchoredObj)268 bool SwSortedObjsImpl::Update( SwAnchoredObject& _rAnchoredObj )
269 {
270 if ( !Contains( _rAnchoredObj ) )
271 {
272 // given anchored object not found in list
273 ASSERT( false,
274 "<SwSortedObjsImpl::Update(..) - sorted list doesn't contain given anchored object" );
275 return false;
276 }
277
278 if ( Count() == 1 )
279 {
280 // given anchored object is the only one in the list.
281 return true;
282 }
283
284 Remove( _rAnchoredObj );
285 Insert( _rAnchoredObj );
286
287 return Contains( _rAnchoredObj );
288 }
289
ListPosOf(const SwAnchoredObject & _rAnchoredObj) const290 sal_uInt32 SwSortedObjsImpl::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
291 {
292 sal_uInt32 nRetLstPos = Count();
293
294 tConstIter aIter = std::find( maSortedObjLst.begin(), maSortedObjLst.end(),
295 &_rAnchoredObj );
296
297 if ( aIter != maSortedObjLst.end() )
298 {
299 // --> OD 2005-08-18 #i51941#
300 // nRetLstPos = aIter - maSortedObjLst.begin();
301 std::vector< SwAnchoredObject* >::difference_type nPos =
302 aIter - maSortedObjLst.begin();
303 nRetLstPos = sal_uInt32( nPos );
304 // <--
305 }
306
307 return nRetLstPos;
308 }
309
310