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 <editeng/svxenum.hxx>
21 : #include <numrule.hxx>
22 : #include <SwNodeNum.hxx>
23 : #include <ndtxt.hxx>
24 : #include <pam.hxx>
25 : #include <IDocumentListItems.hxx>
26 : #include <doc.hxx>
27 :
28 5676 : SwNodeNum::SwNodeNum( SwTextNode* pTextNode )
29 : : SwNumberTreeNode(),
30 : mpTextNode( pTextNode ),
31 5676 : mpNumRule( 0 )
32 : {
33 5676 : }
34 :
35 114160 : SwNodeNum::SwNodeNum( SwNumRule* pNumRule )
36 : : SwNumberTreeNode(),
37 : mpTextNode( 0 ),
38 114160 : mpNumRule( pNumRule )
39 : {
40 114160 : }
41 :
42 239526 : SwNodeNum::~SwNodeNum()
43 : {
44 239526 : }
45 :
46 :
47 :
48 0 : void SwNodeNum::ChangeNumRule( SwNumRule& rNumRule )
49 : {
50 : OSL_ENSURE( GetNumRule() && GetTextNode(),
51 : "<SwNodeNum::ChangeNumRule(..)> - missing list style and/or text node. Serious defect -> please informm OD." );
52 0 : if ( GetNumRule() && GetTextNode() )
53 : {
54 0 : GetNumRule()->RemoveTextNode( *(GetTextNode()) );
55 : }
56 :
57 0 : mpNumRule = &rNumRule;
58 :
59 0 : if ( GetNumRule() && GetTextNode() )
60 : {
61 0 : GetNumRule()->AddTextNode( *(GetTextNode()) );
62 : }
63 0 : }
64 :
65 5620 : SwPosition SwNodeNum::GetPosition() const
66 : {
67 : OSL_ENSURE( GetTextNode(),
68 : "<SwNodeNum::GetPosition()> - no text node set at <SwNodeNum> instance" );
69 5620 : return SwPosition(*mpTextNode);
70 : }
71 :
72 1215 : SwNumberTreeNode * SwNodeNum::Create() const
73 : {
74 1215 : SwNodeNum * pResult = new SwNodeNum( GetNumRule() );
75 :
76 1215 : return pResult;
77 : }
78 :
79 6187 : void SwNodeNum::PreAdd()
80 : {
81 : OSL_ENSURE( GetTextNode(),
82 : "<SwNodeNum::PreAdd()> - no text node set at <SwNodeNum> instance" );
83 6187 : if ( !GetNumRule() && GetTextNode() )
84 : {
85 6187 : mpNumRule = GetTextNode()->GetNumRule();
86 : }
87 : OSL_ENSURE( GetNumRule(),
88 : "<SwNodeNum::PreAdd()> - no list style set at <SwNodeNum> instance" );
89 6187 : if ( GetNumRule() && GetTextNode() )
90 : {
91 6187 : GetNumRule()->AddTextNode( *(GetTextNode()) );
92 : }
93 :
94 : {
95 12374 : if ( GetTextNode() &&
96 6187 : GetTextNode()->GetNodes().IsDocNodes() )
97 : {
98 6187 : GetTextNode()->getIDocumentListItems().addListItem( *this );
99 : }
100 : }
101 6187 : }
102 :
103 6187 : void SwNodeNum::PostRemove()
104 : {
105 : OSL_ENSURE( GetTextNode(),
106 : "<SwNodeNum::PostRemove()> - no text node set at <SwNodeNum> instance" );
107 : OSL_ENSURE( GetNumRule(),
108 : "<SwNodeNum::PostRemove()> - no list style set at <SwNodeNum> instance" );
109 :
110 6187 : if ( GetTextNode() )
111 : {
112 6187 : GetTextNode()->getIDocumentListItems().removeListItem( *this );
113 : }
114 :
115 6187 : if ( GetNumRule() )
116 : {
117 6187 : if ( GetTextNode() )
118 : {
119 6187 : GetNumRule()->RemoveTextNode( *(GetTextNode()) );
120 : }
121 6187 : mpNumRule = 0;
122 : }
123 6187 : }
124 :
125 86051 : bool SwNodeNum::IsNotifiable() const
126 : {
127 86051 : bool aResult = true;
128 :
129 86051 : if ( GetTextNode() )
130 77268 : aResult = GetTextNode()->IsNotifiable();
131 :
132 86051 : return aResult;
133 : }
134 :
135 6187 : bool SwNodeNum::IsNotificationEnabled() const
136 : {
137 6187 : bool aResult = true;
138 :
139 6187 : if ( GetTextNode() )
140 6187 : aResult = GetTextNode()->IsNotificationEnabled();
141 :
142 6187 : return aResult;
143 : }
144 :
145 23321 : bool SwNodeNum::IsContinuous() const
146 : {
147 23321 : bool aResult = false;
148 :
149 : // #i64311#
150 23321 : if ( GetNumRule() )
151 : {
152 23321 : aResult = mpNumRule->IsContinusNum();
153 : }
154 0 : else if ( GetParent() )
155 : {
156 0 : aResult = GetParent()->IsContinuous();
157 : }
158 : else
159 : {
160 : OSL_FAIL( "<SwNodeNum::IsContinuous()> - OD debug" );
161 : }
162 :
163 23321 : return aResult;
164 : }
165 :
166 7530 : bool SwNodeNum::IsCounted() const
167 : {
168 7530 : bool aResult = false;
169 :
170 7530 : if ( GetTextNode() )
171 : {
172 : // #i59559#
173 : // <SwTextNode::IsCounted()> determines, if a text node is counted for numbering
174 6706 : aResult = GetTextNode()->IsCountedInList();
175 : }
176 : else
177 824 : aResult = SwNumberTreeNode::IsCounted();
178 :
179 7530 : return aResult;
180 : }
181 :
182 : // #i64010#
183 1196 : bool SwNodeNum::HasCountedChildren() const
184 : {
185 1196 : bool bResult = false;
186 :
187 1196 : tSwNumberTreeChildren::const_iterator aIt;
188 :
189 2002 : for (aIt = mChildren.begin(); aIt != mChildren.end(); ++aIt)
190 : {
191 894 : SwNodeNum* pChild( dynamic_cast<SwNodeNum*>(*aIt) );
192 : OSL_ENSURE( pChild,
193 : "<SwNodeNum::HasCountedChildren()> - unexpected type of child -> please inform OD" );
194 1876 : if ( pChild &&
195 1700 : ( pChild->IsCountedForNumbering() ||
196 806 : pChild->HasCountedChildren() ) )
197 : {
198 88 : bResult = true;
199 :
200 88 : break;
201 : }
202 : }
203 :
204 1196 : return bResult;
205 : }
206 : // #i64010#
207 894 : bool SwNodeNum::IsCountedForNumbering() const
208 : {
209 1688 : return IsCounted() &&
210 1397 : ( IsPhantom() || // phantoms
211 1382 : !GetTextNode() || // root node
212 1315 : GetTextNode()->HasNumber() || // text node
213 1518 : GetTextNode()->HasBullet() ); // text node
214 : }
215 :
216 2916 : void SwNodeNum::NotifyNode()
217 : {
218 2916 : ValidateMe();
219 :
220 2916 : if (mpTextNode)
221 : {
222 2886 : mpTextNode->NumRuleChgd();
223 : }
224 2916 : }
225 :
226 237407 : bool SwNodeNum::LessThan(const SwNumberTreeNode & rNode) const
227 : {
228 237407 : bool bResult = false;
229 237407 : const SwNodeNum & rTmpNode = static_cast<const SwNodeNum &>(rNode);
230 :
231 237407 : if (mpTextNode == NULL && rTmpNode.mpTextNode != NULL)
232 1446 : bResult = true;
233 235961 : else if (mpTextNode != NULL && rTmpNode.mpTextNode != NULL)
234 : {
235 : // #i83479# - refactoring
236 : // simplify comparison by comparing the indexes of the text nodes
237 223667 : bResult = ( mpTextNode->GetIndex() < rTmpNode.mpTextNode->GetIndex() );
238 : }
239 :
240 237407 : return bResult;
241 : }
242 :
243 3893 : bool SwNodeNum::IsRestart() const
244 : {
245 3893 : bool bIsRestart = false;
246 :
247 3893 : if ( GetTextNode() )
248 : {
249 3798 : bIsRestart = GetTextNode()->IsListRestart();
250 : }
251 :
252 3893 : return bIsRestart;
253 : }
254 :
255 361 : bool SwNodeNum::IsCountPhantoms() const
256 : {
257 361 : bool bResult = true;
258 :
259 : // #i64311#
260 : // phantoms aren't counted in consecutive numbering rules
261 361 : if ( mpNumRule )
262 722 : bResult = !mpNumRule->IsContinusNum() &&
263 722 : mpNumRule->IsCountPhantoms();
264 : else
265 : {
266 : OSL_FAIL( "<SwNodeNum::IsCountPhantoms(): missing numbering rule - please inform OD" );
267 : }
268 :
269 361 : return bResult;
270 : }
271 :
272 776 : SwNumberTree::tSwNumTreeNumber SwNodeNum::GetStartValue() const
273 : {
274 776 : SwNumberTree::tSwNumTreeNumber aResult = 1;
275 :
276 776 : if ( IsRestart() && GetTextNode() )
277 : {
278 221 : aResult = GetTextNode()->GetActualListStartValue();
279 : }
280 : else
281 : {
282 555 : SwNumRule * pRule = GetNumRule();
283 :
284 555 : if (pRule)
285 : {
286 555 : int nLevel = GetParent() ? GetLevelInListTree() : 0;
287 :
288 555 : if (nLevel >= 0 && nLevel < MAXLEVEL)
289 : {
290 555 : const SwNumFormat * pFormat = pRule->GetNumFormat( static_cast<sal_uInt16>(nLevel));
291 :
292 555 : if (pFormat)
293 484 : aResult = pFormat->GetStart();
294 : }
295 : }
296 : }
297 :
298 776 : return aResult;
299 : }
300 :
301 112900 : void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum& rNodeNum )
302 : {
303 112900 : SwNodeNum* pRootNode = rNodeNum.GetParent()
304 0 : ? dynamic_cast<SwNodeNum*>(rNodeNum.GetRoot())
305 112900 : : &rNodeNum;
306 112900 : if ( !pRootNode )
307 : {
308 : // no root node -> nothing do.
309 112900 : return;
310 : }
311 :
312 : // unregister all number tree node entries, which correspond to a text node,
313 : // about the deletion of the number tree root node.
314 112900 : _UnregisterMeAndChildrenDueToRootDelete( *pRootNode );
315 : }
316 :
317 112900 : void SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete( SwNodeNum& rNodeNum )
318 : {
319 112900 : const bool bIsPhantom( rNodeNum.IsPhantom() );
320 112900 : tSwNumberTreeChildren::size_type nAllowedChildCount( 0 );
321 112900 : bool bDone( false );
322 338700 : while ( !bDone &&
323 112900 : rNodeNum.GetChildCount() > nAllowedChildCount )
324 : {
325 0 : SwNodeNum* pChildNode( dynamic_cast<SwNodeNum*>((*rNodeNum.mChildren.begin())) );
326 0 : if ( !pChildNode )
327 : {
328 : OSL_FAIL( "<SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" );
329 0 : ++nAllowedChildCount;
330 0 : continue;
331 : }
332 :
333 : // Unregistering the last child of a phantom will destroy the phantom.
334 : // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to
335 : // be suppressed.
336 0 : if ( bIsPhantom && rNodeNum.GetChildCount() == 1 )
337 : {
338 0 : bDone = true;
339 : }
340 :
341 0 : _UnregisterMeAndChildrenDueToRootDelete( *pChildNode );
342 : }
343 :
344 112900 : if ( !bIsPhantom )
345 : {
346 112900 : SwTextNode* pTextNode( rNodeNum.GetTextNode() );
347 112900 : if ( pTextNode )
348 : {
349 0 : pTextNode->RemoveFromList();
350 : // --> clear all list attributes and the list style
351 0 : std::set<sal_uInt16> aResetAttrsArray;
352 0 : aResetAttrsArray.insert( aResetAttrsArray.end(), RES_PARATR_LIST_ID );
353 0 : aResetAttrsArray.insert( aResetAttrsArray.end(), RES_PARATR_LIST_LEVEL );
354 0 : aResetAttrsArray.insert( aResetAttrsArray.end(), RES_PARATR_LIST_ISRESTART );
355 0 : aResetAttrsArray.insert( aResetAttrsArray.end(), RES_PARATR_LIST_RESTARTVALUE );
356 0 : aResetAttrsArray.insert( aResetAttrsArray.end(), RES_PARATR_LIST_ISCOUNTED );
357 0 : aResetAttrsArray.insert( aResetAttrsArray.end(), RES_PARATR_NUMRULE );
358 0 : SwPaM aPam( *pTextNode );
359 : pTextNode->GetDoc()->ResetAttrs( aPam, false,
360 : aResetAttrsArray,
361 0 : false );
362 : }
363 : }
364 112900 : }
365 :
366 : // #i81002#
367 56 : const SwNodeNum* SwNodeNum::GetPrecedingNodeNumOf( const SwTextNode& rTextNode ) const
368 : {
369 56 : const SwNodeNum* pPrecedingNodeNum( 0 );
370 :
371 : // #i83479#
372 56 : SwNodeNum aNodeNumForTextNode( const_cast<SwTextNode*>(&rTextNode) );
373 :
374 : pPrecedingNodeNum = dynamic_cast<const SwNodeNum*>(
375 56 : GetRoot()
376 56 : ? GetRoot()->GetPrecedingNodeOf( aNodeNumForTextNode )
377 112 : : GetPrecedingNodeOf( aNodeNumForTextNode ) );
378 :
379 56 : return pPrecedingNodeNum;
380 177 : }
381 :
382 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|