LibreOffice Module sw (master) 1
sortedobjs.cxx
Go to the documentation of this file.
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>
27#include <frmfmt.hxx>
28#include <pam.hxx>
29#include <svx/svdobj.hxx>
31#include <osl/diagnose.h>
32
33using namespace ::com::sun::star;
34
36{
37}
38
40{
41}
42
43size_t SwSortedObjs::size() const
44{
45 return maSortedObjLst.size();
46}
47
49{
50 SwAnchoredObject* pAnchoredObj = nullptr;
51
52 if ( _nIndex >= size() )
53 {
54 OSL_FAIL( "<SwSortedObjs::operator[]> - index out of range" );
55 }
56 else
57 {
58 pAnchoredObj = maSortedObjLst[ _nIndex ];
59 }
60
61 return pAnchoredObj;
62}
63
64namespace
65{
66 int GetAnchorWeight(RndStdIds eAnchor)
67 {
68 if (eAnchor == RndStdIds::FLY_AT_CHAR)
69 return 0;
70 if (eAnchor == RndStdIds::FLY_AS_CHAR)
71 return 1;
72 return 2;
73 }
74
75struct ObjAnchorOrder
76{
77 bool operator()( const SwAnchoredObject* _pListedAnchoredObj,
78 const SwAnchoredObject* _pNewAnchoredObj )
79 {
80 // get attributes of listed object
81 const SwFrameFormat& rFormatListed = _pListedAnchoredObj->GetFrameFormat();
82 const SwFormatAnchor* pAnchorListed = &(rFormatListed.GetAnchor());
83
84 // get attributes of new object
85 const SwFrameFormat& rFormatNew = _pNewAnchoredObj->GetFrameFormat();
86 const SwFormatAnchor* pAnchorNew = &(rFormatNew.GetAnchor());
87
88 // check for to-page anchored objects
89 if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_PAGE) &&
90 (pAnchorNew ->GetAnchorId() != RndStdIds::FLY_AT_PAGE))
91 {
92 return true;
93 }
94 else if ((pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_PAGE) &&
95 (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_PAGE))
96 {
97 return false;
98 }
99 else if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_PAGE) &&
100 (pAnchorNew ->GetAnchorId() == RndStdIds::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() == RndStdIds::FLY_AT_FLY) &&
108 (pAnchorNew ->GetAnchorId() != RndStdIds::FLY_AT_FLY))
109 {
110 return true;
111 }
112 else if ((pAnchorListed->GetAnchorId() != RndStdIds::FLY_AT_FLY) &&
113 (pAnchorNew ->GetAnchorId() == RndStdIds::FLY_AT_FLY))
114 {
115 return false;
116 }
117 else if ((pAnchorListed->GetAnchorId() == RndStdIds::FLY_AT_FLY) &&
118 (pAnchorNew ->GetAnchorId() == RndStdIds::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 SwNode* pContentAnchorListed = pAnchorListed->GetAnchorNode();
126 const SwNode* pContentAnchorNew = pAnchorNew->GetAnchorNode();
127 if ( pContentAnchorListed && pContentAnchorNew &&
128 *pContentAnchorListed != *pContentAnchorNew )
129 {
130 return *pContentAnchorListed < *pContentAnchorNew;
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 (pContentAnchorListed && pContentAnchorNew)
138 {
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)
144 {
145 return nListedIndex < nNewIndex;
146 }
147 }
148
149 int nAnchorListedWeight = GetAnchorWeight(pAnchorListed->GetAnchorId());
150 int nAnchorNewWeight = GetAnchorWeight(pAnchorNew->GetAnchorId());
151 if (nAnchorListedWeight != nAnchorNewWeight)
152 {
153 return nAnchorListedWeight < nAnchorNewWeight;
154 }
155
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 )
171 {
172 return !bWrapThroughOrHellListed;
173 }
174 else if ( bWrapThroughOrHellListed && bWrapThroughOrHellNew )
175 {
176 return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
177 }
178
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 ) )
188 {
189 // #i35017# - constant name has changed
190 return pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true )
191 == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE;
192 }
193
194 // objects anchored at the same content position/page/fly with same
195 // wrap influence.
196 // Thus, compare anchor order number
197 return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
198 }
199};
200
201}
202
204{
205 return std::is_sorted(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
206}
207
209{
210 // #i51941#
211 if ( Contains( _rAnchoredObj ) )
212 {
213 // list already contains object
214 OSL_FAIL( "<SwSortedObjs::Insert()> - already contains object" );
215 return true;
216 }
217
218 // find insert position
219 std::vector< SwAnchoredObject* >::iterator aInsPosIter =
220 std::lower_bound( maSortedObjLst.begin(), maSortedObjLst.end(),
221 &_rAnchoredObj, ObjAnchorOrder() );
222
223 // insert object into list
224 maSortedObjLst.insert( aInsPosIter, &_rAnchoredObj );
225
226 return Contains( _rAnchoredObj );
227}
228
230{
231 std::vector< SwAnchoredObject* >::iterator aDelPosIter =
232 std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
233
234 if ( aDelPosIter == maSortedObjLst.end() )
235 {
236 // object not found.
237 OSL_FAIL( "<SwSortedObjs::Remove()> - object not found" );
238 }
239 else
240 {
241 maSortedObjLst.erase( aDelPosIter );
242 }
243}
244
245bool SwSortedObjs::Contains( const SwAnchoredObject& _rAnchoredObj ) const
246{
247 std::vector< SwAnchoredObject* >::const_iterator aIter =
248 std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
249
250 return aIter != maSortedObjLst.end();
251}
252
254{
255 if ( !Contains( _rAnchoredObj ) )
256 {
257 // given anchored object not found in list
258 OSL_FAIL( "<SwSortedObjs::Update(..) - sorted list doesn't contain given anchored object" );
259 return;
260 }
261
262 if ( size() == 1 )
263 {
264 // given anchored object is the only one in the list.
265 return;
266 }
267
268 Remove( _rAnchoredObj );
269 Insert( _rAnchoredObj );
270}
271
273{
274 std::stable_sort(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
275}
276
277size_t SwSortedObjs::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
278{
279 std::vector< SwAnchoredObject* >::const_iterator aIter =
280 std::find( maSortedObjLst.begin(), maSortedObjLst.end(), &_rAnchoredObj );
281
282 if ( aIter != maSortedObjLst.end() )
283 {
284 // #i51941#
285 std::vector< SwAnchoredObject* >::difference_type nPos =
286 aIter - maSortedObjLst.begin();
287 return static_cast<size_t>( nPos );
288 }
289
290 return size();
291}
292
293/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual SdrLayerID GetHellId() const =0
virtual SdrLayerID GetInvisibleHellId() const =0
virtual SdrLayerID GetLayer() const
wrapper class for the positioning of Writer fly frames and drawing objects
virtual SwFrameFormat & GetFrameFormat()=0
const SdrObject * GetDrawObj() const
FlyAnchors.
Definition: fmtanchr.hxx:37
sal_Int32 GetAnchorContentOffset() const
Definition: atrfrm.cxx:1631
sal_uInt32 GetOrder() const
Definition: fmtanchr.hxx:80
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:67
SwNode * GetAnchorNode() const
Definition: atrfrm.cxx:1614
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
Allows positioning of floating screen objects without considering their own wrapping type and the wra...
sal_Int16 GetWrapInfluenceOnObjPos(const bool _bIterativeAsOnceConcurrent=false) const
to control, if value <ITERATIVE> has to be treated as <ONCE_CONCURRENT>
const SwFormatWrapInfluenceOnObjPos & GetWrapInfluenceOnObjPos(bool=true) const
const IDocumentDrawModelAccess & getIDocumentDrawModelAccess() const
Provides access to the document draw model interface.
Definition: format.cxx:712
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:88
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
Style of a layout element.
Definition: frmfmt.hxx:72
Base class of the Writer document model elements.
Definition: node.hxx:98
bool Contains(const SwAnchoredObject &_rAnchoredObj) const
Definition: sortedobjs.cxx:245
bool Insert(SwAnchoredObject &_rAnchoredObj)
Definition: sortedobjs.cxx:208
std::vector< SwAnchoredObject * > maSortedObjLst
Definition: sortedobjs.hxx:51
SwAnchoredObject * operator[](size_t _nIndex) const
direct access to the entries
Definition: sortedobjs.cxx:48
bool is_sorted() const
Definition: sortedobjs.cxx:203
size_t size() const
Definition: sortedobjs.cxx:43
void Update(SwAnchoredObject &_rAnchoredObj)
method to update the position of the given anchored object in the sorted list
Definition: sortedobjs.cxx:253
size_t ListPosOf(const SwAnchoredObject &_rAnchoredObj) const
Position of object <_rAnchoredObj> in sorted list.
Definition: sortedobjs.cxx:277
void Remove(SwAnchoredObject &_rAnchoredObj)
Definition: sortedobjs.cxx:229
void UpdateAll()
Definition: sortedobjs.cxx:272
sal_uInt16 nPos
RndStdIds