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