1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/diagnose.h>
21 #include <svl/stritem.hxx>
22 #include <numrule.hxx>
23 #include <SwNodeNum.hxx>
26 #include <IDocumentListItems.hxx>
29 SwNodeNum::SwNodeNum(SwTextNode
* pTextNode
, bool const isHiddenRedlines
)
30 : mpTextNode( pTextNode
)
31 , mpNumRule( nullptr )
32 , m_isHiddenRedlines(isHiddenRedlines
)
36 SwNodeNum::SwNodeNum( SwNumRule
* pNumRule
)
37 : mpTextNode( nullptr )
38 , mpNumRule( pNumRule
)
39 , m_isHiddenRedlines(false)
43 SwNodeNum::~SwNodeNum()
48 void SwNodeNum::ChangeNumRule( SwNumRule
& rNumRule
)
50 OSL_ENSURE( GetNumRule() && GetTextNode(),
51 "<SwNodeNum::ChangeNumRule(..)> - missing list style and/or text node. Serious defect -> please inform OD." );
52 if ( GetNumRule() && GetTextNode() )
54 GetNumRule()->RemoveTextNode( *(GetTextNode()) );
57 mpNumRule
= &rNumRule
;
59 if ( GetNumRule() && GetTextNode() )
61 GetNumRule()->AddTextNode( *(GetTextNode()) );
65 SwPosition
SwNodeNum::GetPosition() const
67 OSL_ENSURE( GetTextNode(),
68 "<SwNodeNum::GetPosition()> - no text node set at <SwNodeNum> instance" );
69 return SwPosition(*mpTextNode
);
72 SwNumberTreeNode
* SwNodeNum::Create() const
74 SwNodeNum
* pResult
= new SwNodeNum( GetNumRule() );
79 void SwNodeNum::PreAdd()
81 OSL_ENSURE( GetTextNode(),
82 "<SwNodeNum::PreAdd()> - no text node set at <SwNodeNum> instance" );
83 if ( !GetNumRule() && GetTextNode() )
85 mpNumRule
= GetTextNode()->GetNumRule();
87 OSL_ENSURE( GetNumRule(),
88 "<SwNodeNum::PreAdd()> - no list style set at <SwNodeNum> instance" );
89 if (!m_isHiddenRedlines
&& GetNumRule() && GetTextNode())
91 GetNumRule()->AddTextNode( *(GetTextNode()) );
94 if (!m_isHiddenRedlines
)
97 GetTextNode()->GetNodes().IsDocNodes() )
99 GetTextNode()->getIDocumentListItems().addListItem( *this );
104 void SwNodeNum::PostRemove()
106 OSL_ENSURE( GetTextNode(),
107 "<SwNodeNum::PostRemove()> - no text node set at <SwNodeNum> instance" );
108 OSL_ENSURE( GetNumRule(),
109 "<SwNodeNum::PostRemove()> - no list style set at <SwNodeNum> instance" );
111 if (!m_isHiddenRedlines
&& GetTextNode())
113 GetTextNode()->getIDocumentListItems().removeListItem( *this );
118 if (!m_isHiddenRedlines
&& GetTextNode())
120 GetNumRule()->RemoveTextNode( *(GetTextNode()) );
126 bool SwNodeNum::IsNotifiable() const
131 aResult
= GetTextNode()->IsNotifiable();
136 bool SwNodeNum::IsNotificationEnabled() const
141 aResult
= GetTextNode()->IsNotificationEnabled();
146 bool SwNodeNum::IsContinuous() const
148 bool aResult
= false;
153 aResult
= mpNumRule
->IsContinusNum();
155 else if ( GetParent() )
157 aResult
= GetParent()->IsContinuous();
161 OSL_FAIL( "<SwNodeNum::IsContinuous()> - OD debug" );
167 bool SwNodeNum::IsCounted() const
169 bool aResult
= false;
174 // <SwTextNode::IsCounted()> determines, if a text node is counted for numbering
175 aResult
= GetTextNode()->IsCountedInList();
178 aResult
= SwNumberTreeNode::IsCounted();
184 bool SwNodeNum::HasCountedChildren() const
186 return std::any_of(mChildren
.begin(), mChildren
.end(),
187 [](SwNumberTreeNode
* pNode
) {
188 SwNodeNum
* pChild( dynamic_cast<SwNodeNum
*>(pNode
) );
189 OSL_ENSURE( pChild
, "<SwNodeNum::HasCountedChildren()> - unexpected type of child" );
190 return pChild
&& (pChild
->IsCountedForNumbering() || pChild
->HasCountedChildren());
194 bool SwNodeNum::IsCountedForNumbering() const
196 return IsCounted() &&
197 ( IsPhantom() || // phantoms
198 !GetTextNode() || // root node
199 GetTextNode()->HasNumber() || // text node
200 GetTextNode()->HasBullet() ); // text node
203 void SwNodeNum::NotifyNode()
209 mpTextNode
->NumRuleChgd();
213 bool SwNodeNum::LessThan(const SwNumberTreeNode
& rNode
) const
215 bool bResult
= false;
216 const SwNodeNum
& rTmpNode
= static_cast<const SwNodeNum
&>(rNode
);
218 if (mpTextNode
== nullptr && rTmpNode
.mpTextNode
!= nullptr)
220 else if (mpTextNode
!= nullptr && rTmpNode
.mpTextNode
!= nullptr)
222 // #i83479# - refactoring
223 // simplify comparison by comparing the indexes of the text nodes
224 bResult
= ( mpTextNode
->GetIndex() < rTmpNode
.mpTextNode
->GetIndex() );
230 bool SwNodeNum::IsRestart() const
232 bool bIsRestart
= false;
236 bIsRestart
= GetTextNode()->IsListRestart();
242 bool SwNodeNum::IsCountPhantoms() const
247 // phantoms aren't counted in consecutive numbering rules
249 bResult
= !mpNumRule
->IsContinusNum() &&
250 mpNumRule
->IsCountPhantoms();
253 OSL_FAIL( "<SwNodeNum::IsCountPhantoms(): missing numbering rule" );
259 SwNumberTree::tSwNumTreeNumber
SwNodeNum::GetStartValue() const
261 SwNumberTree::tSwNumTreeNumber aResult
= 1;
263 if ( IsRestart() && GetTextNode() )
265 aResult
= GetTextNode()->GetActualListStartValue();
269 SwNumRule
* pRule
= GetNumRule();
273 int nLevel
= GetParent() ? GetLevelInListTree() : 0;
275 if (nLevel
>= 0 && nLevel
< MAXLEVEL
)
277 const SwNumFormat
* pFormat
= pRule
->GetNumFormat( static_cast<sal_uInt16
>(nLevel
));
280 aResult
= pFormat
->GetStart();
288 void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum
& rNodeNum
)
290 SwNodeNum
* pRootNode
= rNodeNum
.GetParent()
291 ? dynamic_cast<SwNodeNum
*>(rNodeNum
.GetRoot())
295 // no root node -> nothing do.
299 // unregister all number tree node entries, which correspond to a text node,
300 // about the deletion of the number tree root node.
301 UnregisterMeAndChildrenDueToRootDelete( *pRootNode
);
304 void SwNodeNum::UnregisterMeAndChildrenDueToRootDelete( SwNodeNum
& rNodeNum
)
306 const bool bIsPhantom( rNodeNum
.IsPhantom() );
307 tSwNumberTreeChildren::size_type
nAllowedChildCount( 0 );
310 rNodeNum
.GetChildCount() > nAllowedChildCount
)
312 SwNodeNum
* pChildNode( dynamic_cast<SwNodeNum
*>((*rNodeNum
.mChildren
.begin())) );
315 OSL_FAIL( "<SwNodeNum::UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" );
316 ++nAllowedChildCount
;
320 // Unregistering the last child of a phantom will destroy the phantom.
321 // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to
323 if ( bIsPhantom
&& rNodeNum
.GetChildCount() == 1 )
328 UnregisterMeAndChildrenDueToRootDelete( *pChildNode
);
334 SwTextNode
* pTextNode( rNodeNum
.GetTextNode() );
338 pTextNode
->RemoveFromList();
339 // --> clear all list attributes and the list style
340 o3tl::sorted_vector
<sal_uInt16
> aResetAttrsArray
;
341 aResetAttrsArray
.insert( RES_PARATR_LIST_ID
);
342 aResetAttrsArray
.insert( RES_PARATR_LIST_LEVEL
);
343 aResetAttrsArray
.insert( RES_PARATR_LIST_ISRESTART
);
344 aResetAttrsArray
.insert( RES_PARATR_LIST_RESTARTVALUE
);
345 aResetAttrsArray
.insert( RES_PARATR_LIST_ISCOUNTED
);
346 aResetAttrsArray
.insert( RES_PARATR_NUMRULE
);
347 SwPaM
aPam( *pTextNode
);
348 pTextNode
->GetDoc().ResetAttrs( aPam
, false,
354 const SwNodeNum
* SwNodeNum::GetPrecedingNodeNumOf( const SwTextNode
& rTextNode
) const
356 const SwNodeNum
* pPrecedingNodeNum( nullptr );
359 SwNodeNum
aNodeNumForTextNode( const_cast<SwTextNode
*>(&rTextNode
), false/*doesn't matter*/ );
361 pPrecedingNodeNum
= dynamic_cast<const SwNodeNum
*>(
363 ? GetRoot()->GetPrecedingNodeOf( aNodeNumForTextNode
)
364 : GetPrecedingNodeOf( aNodeNumForTextNode
) );
366 return pPrecedingNodeNum
;
369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */