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