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 <numrule.hxx>
22 #include <SwNodeNum.hxx>
25 #include <IDocumentListItems.hxx>
28 SwNodeNum::SwNodeNum(SwTextNode
* pTextNode
, bool const isHiddenRedlines
)
29 : mpTextNode( pTextNode
)
30 , mpNumRule( nullptr )
31 , m_isHiddenRedlines(isHiddenRedlines
)
35 SwNodeNum::SwNodeNum( SwNumRule
* pNumRule
)
36 : mpTextNode( nullptr )
37 , mpNumRule( pNumRule
)
38 , m_isHiddenRedlines(false)
42 SwNodeNum::~SwNodeNum()
47 void SwNodeNum::ChangeNumRule( SwNumRule
& rNumRule
)
49 OSL_ENSURE( GetNumRule() && GetTextNode(),
50 "<SwNodeNum::ChangeNumRule(..)> - missing list style and/or text node. Serious defect -> please inform OD." );
51 if ( GetNumRule() && GetTextNode() )
53 GetNumRule()->RemoveTextNode( *(GetTextNode()) );
56 mpNumRule
= &rNumRule
;
58 if ( GetNumRule() && GetTextNode() )
60 GetNumRule()->AddTextNode( *(GetTextNode()) );
64 SwPosition
SwNodeNum::GetPosition() const
66 OSL_ENSURE( GetTextNode(),
67 "<SwNodeNum::GetPosition()> - no text node set at <SwNodeNum> instance" );
68 return SwPosition(*mpTextNode
);
71 SwNumberTreeNode
* SwNodeNum::Create() const
73 SwNodeNum
* pResult
= new SwNodeNum( GetNumRule() );
78 void SwNodeNum::PreAdd()
80 OSL_ENSURE( GetTextNode(),
81 "<SwNodeNum::PreAdd()> - no text node set at <SwNodeNum> instance" );
82 if ( !GetNumRule() && GetTextNode() )
84 mpNumRule
= GetTextNode()->GetNumRule();
86 OSL_ENSURE( GetNumRule(),
87 "<SwNodeNum::PreAdd()> - no list style set at <SwNodeNum> instance" );
88 if (!m_isHiddenRedlines
&& GetNumRule() && GetTextNode())
90 GetNumRule()->AddTextNode( *(GetTextNode()) );
93 if (!m_isHiddenRedlines
)
96 GetTextNode()->GetNodes().IsDocNodes() )
98 GetTextNode()->getIDocumentListItems().addListItem( *this );
103 void SwNodeNum::PostRemove()
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" );
110 if (!m_isHiddenRedlines
&& GetTextNode())
112 GetTextNode()->getIDocumentListItems().removeListItem( *this );
117 if (!m_isHiddenRedlines
&& GetTextNode())
119 GetNumRule()->RemoveTextNode( *(GetTextNode()) );
125 bool SwNodeNum::IsNotifiable(const SwDoc
& rDoc
) const
129 if (const SwTextNode
* pTextNode
= GetTextNode())
130 aResult
= pTextNode
->IsNotifiable();
132 aResult
= IsNotificationEnabled(rDoc
);
137 bool SwNodeNum::IsNotificationEnabled(const SwDoc
& rDoc
) const
141 if (const SwTextNode
* pTextNode
= GetTextNode())
142 aResult
= pTextNode
->IsNotificationEnabled();
144 aResult
= !rDoc
.IsInReading() && !rDoc
.IsInDtor();
149 bool SwNodeNum::IsContinuous() const
151 bool aResult
= false;
156 aResult
= mpNumRule
->IsContinusNum();
158 else if ( GetParent() )
160 aResult
= GetParent()->IsContinuous();
164 OSL_FAIL( "<SwNodeNum::IsContinuous()> - OD debug" );
170 bool SwNodeNum::IsCounted() const
172 bool aResult
= false;
177 // <SwTextNode::IsCounted()> determines, if a text node is counted for numbering
178 aResult
= GetTextNode()->IsCountedInList();
181 aResult
= SwNumberTreeNode::IsCounted();
187 bool SwNodeNum::HasCountedChildren() const
189 return std::any_of(mChildren
.begin(), mChildren
.end(),
190 [](SwNumberTreeNode
* pNode
) {
191 SwNodeNum
* pChild( dynamic_cast<SwNodeNum
*>(pNode
) );
192 OSL_ENSURE( pChild
, "<SwNodeNum::HasCountedChildren()> - unexpected type of child" );
193 return pChild
&& (pChild
->IsCountedForNumbering() || pChild
->HasCountedChildren());
197 bool SwNodeNum::IsCountedForNumbering() const
199 return IsCounted() &&
200 ( IsPhantom() || // phantoms
201 !GetTextNode() || // root node
202 GetTextNode()->HasNumber() || // text node
203 GetTextNode()->HasBullet() ); // text node
206 void SwNodeNum::NotifyNode()
212 mpTextNode
->NumRuleChgd();
216 bool SwNodeNum::LessThan(const SwNumberTreeNode
& rNode
) const
218 bool bResult
= false;
219 const SwNodeNum
& rTmpNode
= static_cast<const SwNodeNum
&>(rNode
);
221 if (mpTextNode
== nullptr && rTmpNode
.mpTextNode
!= nullptr)
223 else if (mpTextNode
!= nullptr && rTmpNode
.mpTextNode
!= nullptr)
225 // #i83479# - refactoring
226 // simplify comparison by comparing the indexes of the text nodes
227 bResult
= ( mpTextNode
->GetIndex() < rTmpNode
.mpTextNode
->GetIndex() );
233 bool SwNodeNum::IsRestart() const
235 bool bIsRestart
= false;
239 bIsRestart
= GetTextNode()->IsListRestart();
245 bool SwNodeNum::IsCountPhantoms() const
250 // phantoms aren't counted in consecutive numbering rules
252 bResult
= !mpNumRule
->IsContinusNum() &&
253 mpNumRule
->IsCountPhantoms();
256 OSL_FAIL( "<SwNodeNum::IsCountPhantoms(): missing numbering rule" );
262 SwNumberTree::tSwNumTreeNumber
SwNodeNum::GetStartValue() const
264 SwNumberTree::tSwNumTreeNumber aResult
= 1;
266 if ( IsRestart() && GetTextNode() )
268 aResult
= GetTextNode()->GetActualListStartValue();
272 SwNumRule
* pRule
= GetNumRule();
276 int nLevel
= GetParent() ? GetLevelInListTree() : 0;
278 if (nLevel
>= 0 && nLevel
< MAXLEVEL
)
280 const SwNumFormat
* pFormat
= pRule
->GetNumFormat( o3tl::narrowing
<sal_uInt16
>(nLevel
));
283 aResult
= pFormat
->GetStart();
291 void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum
& rNodeNum
)
293 SwNodeNum
* pRootNode
= rNodeNum
.GetParent()
294 ? dynamic_cast<SwNodeNum
*>(rNodeNum
.GetRoot())
298 // no root node -> nothing do.
302 // unregister all number tree node entries, which correspond to a text node,
303 // about the deletion of the number tree root node.
304 UnregisterMeAndChildrenDueToRootDelete( *pRootNode
);
307 void SwNodeNum::UnregisterMeAndChildrenDueToRootDelete( SwNodeNum
& rNodeNum
)
309 const bool bIsPhantom( rNodeNum
.IsPhantom() );
310 tSwNumberTreeChildren::size_type
nAllowedChildCount( 0 );
313 rNodeNum
.GetChildCount() > nAllowedChildCount
)
315 SwNodeNum
* pChildNode( dynamic_cast<SwNodeNum
*>((*rNodeNum
.mChildren
.begin())) );
318 OSL_FAIL( "<SwNodeNum::UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" );
319 ++nAllowedChildCount
;
323 // Unregistering the last child of a phantom will destroy the phantom.
324 // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to
326 if ( bIsPhantom
&& rNodeNum
.GetChildCount() == 1 )
331 UnregisterMeAndChildrenDueToRootDelete( *pChildNode
);
337 SwTextNode
* pTextNode( rNodeNum
.GetTextNode() );
341 pTextNode
->RemoveFromList();
342 // --> clear all list attributes and the list style
343 const o3tl::sorted_vector
<sal_uInt16
> aResetAttrsArray
{
344 RES_PARATR_LIST_ID
, RES_PARATR_LIST_LEVEL
, RES_PARATR_LIST_ISRESTART
,
345 RES_PARATR_LIST_RESTARTVALUE
, RES_PARATR_LIST_ISCOUNTED
, 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: */