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