diff options
Diffstat (limited to 'sw/source/core/SwNumberTree/SwNodeNum.cxx')
-rw-r--r-- | sw/source/core/SwNumberTree/SwNodeNum.cxx | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/sw/source/core/SwNumberTree/SwNodeNum.cxx b/sw/source/core/SwNumberTree/SwNodeNum.cxx new file mode 100644 index 000000000..9c160d3c0 --- /dev/null +++ b/sw/source/core/SwNumberTree/SwNodeNum.cxx @@ -0,0 +1,369 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <osl/diagnose.h> +#include <numrule.hxx> +#include <SwNodeNum.hxx> +#include <ndtxt.hxx> +#include <pam.hxx> +#include <IDocumentListItems.hxx> +#include <doc.hxx> + +SwNodeNum::SwNodeNum(SwTextNode* pTextNode, bool const isHiddenRedlines) + : mpTextNode( pTextNode ) + , mpNumRule( nullptr ) + , m_isHiddenRedlines(isHiddenRedlines) +{ +} + +SwNodeNum::SwNodeNum( SwNumRule* pNumRule ) + : mpTextNode( nullptr ) + , mpNumRule( pNumRule ) + , m_isHiddenRedlines(false) +{ +} + +SwNodeNum::~SwNodeNum() +{ +} + + +void SwNodeNum::ChangeNumRule( SwNumRule& rNumRule ) +{ + OSL_ENSURE( GetNumRule() && GetTextNode(), + "<SwNodeNum::ChangeNumRule(..)> - missing list style and/or text node. Serious defect -> please inform OD." ); + if ( GetNumRule() && GetTextNode() ) + { + GetNumRule()->RemoveTextNode( *(GetTextNode()) ); + } + + mpNumRule = &rNumRule; + + if ( GetNumRule() && GetTextNode() ) + { + GetNumRule()->AddTextNode( *(GetTextNode()) ); + } +} + +SwPosition SwNodeNum::GetPosition() const +{ + OSL_ENSURE( GetTextNode(), + "<SwNodeNum::GetPosition()> - no text node set at <SwNodeNum> instance" ); + return SwPosition(*mpTextNode); +} + +SwNumberTreeNode * SwNodeNum::Create() const +{ + SwNodeNum * pResult = new SwNodeNum( GetNumRule() ); + + return pResult; +} + +void SwNodeNum::PreAdd() +{ + OSL_ENSURE( GetTextNode(), + "<SwNodeNum::PreAdd()> - no text node set at <SwNodeNum> instance" ); + if ( !GetNumRule() && GetTextNode() ) + { + mpNumRule = GetTextNode()->GetNumRule(); + } + OSL_ENSURE( GetNumRule(), + "<SwNodeNum::PreAdd()> - no list style set at <SwNodeNum> instance" ); + if (!m_isHiddenRedlines && GetNumRule() && GetTextNode()) + { + GetNumRule()->AddTextNode( *(GetTextNode()) ); + } + + if (!m_isHiddenRedlines) + { + if ( GetTextNode() && + GetTextNode()->GetNodes().IsDocNodes() ) + { + GetTextNode()->getIDocumentListItems().addListItem( *this ); + } + } +} + +void SwNodeNum::PostRemove() +{ + OSL_ENSURE( GetTextNode(), + "<SwNodeNum::PostRemove()> - no text node set at <SwNodeNum> instance" ); + OSL_ENSURE( GetNumRule(), + "<SwNodeNum::PostRemove()> - no list style set at <SwNodeNum> instance" ); + + if (!m_isHiddenRedlines && GetTextNode()) + { + GetTextNode()->getIDocumentListItems().removeListItem( *this ); + } + + if ( GetNumRule() ) + { + if (!m_isHiddenRedlines && GetTextNode()) + { + GetNumRule()->RemoveTextNode( *(GetTextNode()) ); + } + mpNumRule = nullptr; + } +} + +bool SwNodeNum::IsNotifiable(const SwDoc& rDoc) const +{ + bool aResult; + + if (const SwTextNode* pTextNode = GetTextNode()) + aResult = pTextNode->IsNotifiable(); + else + aResult = IsNotificationEnabled(rDoc); + + return aResult; +} + +bool SwNodeNum::IsNotificationEnabled(const SwDoc& rDoc) const +{ + bool aResult; + + if (const SwTextNode* pTextNode = GetTextNode()) + aResult = pTextNode->IsNotificationEnabled(); + else + aResult = !rDoc.IsInReading() && !rDoc.IsInDtor(); + + return aResult; +} + +bool SwNodeNum::IsContinuous() const +{ + bool aResult = false; + + // #i64311# + if ( GetNumRule() ) + { + aResult = mpNumRule->IsContinusNum(); + } + else if ( GetParent() ) + { + aResult = GetParent()->IsContinuous(); + } + else + { + OSL_FAIL( "<SwNodeNum::IsContinuous()> - OD debug" ); + } + + return aResult; +} + +bool SwNodeNum::IsCounted() const +{ + bool aResult = false; + + if ( GetTextNode() ) + { + // #i59559# + // <SwTextNode::IsCounted()> determines, if a text node is counted for numbering + aResult = GetTextNode()->IsCountedInList(); + } + else + aResult = SwNumberTreeNode::IsCounted(); + + return aResult; +} + +// #i64010# +bool SwNodeNum::HasCountedChildren() const +{ + return std::any_of(mChildren.begin(), mChildren.end(), + [](SwNumberTreeNode* pNode) { + SwNodeNum* pChild( dynamic_cast<SwNodeNum*>(pNode) ); + OSL_ENSURE( pChild, "<SwNodeNum::HasCountedChildren()> - unexpected type of child" ); + return pChild && (pChild->IsCountedForNumbering() || pChild->HasCountedChildren()); + }); +} +// #i64010# +bool SwNodeNum::IsCountedForNumbering() const +{ + return IsCounted() && + ( IsPhantom() || // phantoms + !GetTextNode() || // root node + GetTextNode()->HasNumber() || // text node + GetTextNode()->HasBullet() ); // text node +} + +void SwNodeNum::NotifyNode() +{ + ValidateMe(); + + if (mpTextNode) + { + mpTextNode->NumRuleChgd(); + } +} + +bool SwNodeNum::LessThan(const SwNumberTreeNode & rNode) const +{ + bool bResult = false; + const SwNodeNum & rTmpNode = static_cast<const SwNodeNum &>(rNode); + + if (mpTextNode == nullptr && rTmpNode.mpTextNode != nullptr) + bResult = true; + else if (mpTextNode != nullptr && rTmpNode.mpTextNode != nullptr) + { + // #i83479# - refactoring + // simplify comparison by comparing the indexes of the text nodes + bResult = ( mpTextNode->GetIndex() < rTmpNode.mpTextNode->GetIndex() ); + } + + return bResult; +} + +bool SwNodeNum::IsRestart() const +{ + bool bIsRestart = false; + + if ( GetTextNode() ) + { + bIsRestart = GetTextNode()->IsListRestart(); + } + + return bIsRestart; +} + +bool SwNodeNum::IsCountPhantoms() const +{ + bool bResult = true; + + // #i64311# + // phantoms aren't counted in consecutive numbering rules + if ( mpNumRule ) + bResult = !mpNumRule->IsContinusNum() && + mpNumRule->IsCountPhantoms(); + else + { + OSL_FAIL( "<SwNodeNum::IsCountPhantoms(): missing numbering rule" ); + } + + return bResult; +} + +SwNumberTree::tSwNumTreeNumber SwNodeNum::GetStartValue() const +{ + SwNumberTree::tSwNumTreeNumber aResult = 1; + + if ( IsRestart() && GetTextNode() ) + { + aResult = GetTextNode()->GetActualListStartValue(); + } + else + { + SwNumRule * pRule = GetNumRule(); + + if (pRule) + { + int nLevel = GetParent() ? GetLevelInListTree() : 0; + + if (nLevel >= 0 && nLevel < MAXLEVEL) + { + const SwNumFormat * pFormat = pRule->GetNumFormat( o3tl::narrowing<sal_uInt16>(nLevel)); + + if (pFormat) + aResult = pFormat->GetStart(); + } + } + } + + return aResult; +} + +void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum& rNodeNum ) +{ + SwNodeNum* pRootNode = rNodeNum.GetParent() + ? dynamic_cast<SwNodeNum*>(rNodeNum.GetRoot()) + : &rNodeNum; + if ( !pRootNode ) + { + // no root node -> nothing do. + return; + } + + // unregister all number tree node entries, which correspond to a text node, + // about the deletion of the number tree root node. + UnregisterMeAndChildrenDueToRootDelete( *pRootNode ); +} + +void SwNodeNum::UnregisterMeAndChildrenDueToRootDelete( SwNodeNum& rNodeNum ) +{ + const bool bIsPhantom( rNodeNum.IsPhantom() ); + tSwNumberTreeChildren::size_type nAllowedChildCount( 0 ); + bool bDone( false ); + while ( !bDone && + rNodeNum.GetChildCount() > nAllowedChildCount ) + { + SwNodeNum* pChildNode( dynamic_cast<SwNodeNum*>((*rNodeNum.mChildren.begin())) ); + if ( !pChildNode ) + { + OSL_FAIL( "<SwNodeNum::UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" ); + ++nAllowedChildCount; + continue; + } + + // Unregistering the last child of a phantom will destroy the phantom. + // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to + // be suppressed. + if ( bIsPhantom && rNodeNum.GetChildCount() == 1 ) + { + bDone = true; + } + + UnregisterMeAndChildrenDueToRootDelete( *pChildNode ); + } + + if ( bIsPhantom ) + return; + + SwTextNode* pTextNode( rNodeNum.GetTextNode() ); + if ( !pTextNode ) + return; + + pTextNode->RemoveFromList(); + // --> clear all list attributes and the list style + const o3tl::sorted_vector<sal_uInt16> aResetAttrsArray{ + RES_PARATR_LIST_ID, RES_PARATR_LIST_LEVEL, RES_PARATR_LIST_ISRESTART, + RES_PARATR_LIST_RESTARTVALUE, RES_PARATR_LIST_ISCOUNTED, RES_PARATR_NUMRULE + }; + SwPaM aPam( *pTextNode ); + pTextNode->GetDoc().ResetAttrs( aPam, false, + aResetAttrsArray, + false ); +} + +// #i81002# +const SwNodeNum* SwNodeNum::GetPrecedingNodeNumOf( const SwTextNode& rTextNode ) const +{ + const SwNodeNum* pPrecedingNodeNum( nullptr ); + + // #i83479# + SwNodeNum aNodeNumForTextNode( const_cast<SwTextNode*>(&rTextNode), false/*doesn't matter*/ ); + + pPrecedingNodeNum = dynamic_cast<const SwNodeNum*>( + GetRoot() + ? GetRoot()->GetPrecedingNodeOf( aNodeNumForTextNode ) + : GetPrecedingNodeOf( aNodeNumForTextNode ) ); + + return pPrecedingNodeNum; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |