/* -*- 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 .
*/
if (pResult) while (pResult->mpParent)
pResult = pResult->mpParent;
return pResult;
}
void SwNumberTreeNode::ClearObsoletePhantoms()
{
tSwNumberTreeChildren::iterator aIt = mChildren.begin();
if (!(aIt != mChildren.end() && (*aIt)->IsPhantom())) return;
(*aIt)->ClearObsoletePhantoms();
if ((*aIt)->mChildren.empty())
{ // #i60652# // Because <mChildren.erase(aIt)> could destroy the element, which // is referenced by <mItLastValid>, it's needed to adjust // <mItLastValid> before erasing <aIt>.
SetLastValid(mChildren.end());
tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
// --> // improvement: // - Only one time checked for <mChildren.end()>. // - Less checks for each loop run. // correction: // - consider case that current node isn't counted and isn't the first // child of its parent. In this case the number of last counted child // of the previous node determines the start value for the following // children loop, if all children have to be validated and the first // one doesn't restart the counting.
SwNumberTree::tSwNumTreeNumber nTmpNumber( 0 ); if (aIt != mChildren.end())
nTmpNumber = (*aIt)->mnNumber; else
{
aIt = mChildren.begin();
(*aIt)->mbContinueingPreviousSubTree = false;
// determine default start value // consider the case that the first child isn't counted.
nTmpNumber = (*aIt)->GetStartValue(); if ( !(*aIt)->IsCounted() &&
( !(*aIt)->HasCountedChildren() || (*aIt)->IsPhantom() ) )
{
--nTmpNumber;
}
// determine special start value for the case that first child // doesn't restart the numbering and the parent node isn't counted // and isn't the first child. constbool bParentCounted( IsCounted() &&
( !IsPhantom() ||
HasPhantomCountedParent() ) ); if ( !(*aIt)->IsRestart() &&
GetParent() && !bParentCounted )
{
tSwNumberTreeChildren::const_iterator aParentChildIt =
GetParent()->GetIterator( this ); while ( aParentChildIt != GetParent()->mChildren.begin() )
{
--aParentChildIt;
SwNumberTreeNode* pPrevNode( *aParentChildIt ); if ( pPrevNode->GetChildCount() > 0 )
{
(*aIt)->mbContinueingPreviousSubTree = true;
nTmpNumber = (*(pPrevNode->mChildren.rbegin()))->GetNumber(); if ( (*aIt)->IsCounted() &&
( !(*aIt)->IsPhantom() ||
(*aIt)->HasPhantomCountedParent() ) )
{
++nTmpNumber;
} break;
} elseif ( pPrevNode->IsCounted() )
{ break;
} else
{ // Previous node has no children and is not counted. // Thus, next turn and check for the previous node.
}
}
}
(*aIt)->mnNumber = nTmpNumber;
}
while (aIt != aValidateIt)
{
++aIt;
(*aIt)->mbContinueingPreviousSubTree = false;
// --> only for counted nodes the number // has to be adjusted, compared to the previous node. // this condition is hold also for nodes, which restart the numbering. if ( (*aIt)->IsCounted() )
{ if ((*aIt)->IsRestart())
nTmpNumber = (*aIt)->GetStartValue(); else
++nTmpNumber;
}
SwNumberTreeNode * SwNumberTreeNode::GetFirstNonPhantomChild()
{ if (IsPhantom()) return (*mChildren.begin())->GetFirstNonPhantomChild();
returnthis;
}
/** Moves all children of this node that are greater than a given node to the destination node.
*/ void SwNumberTreeNode::MoveGreaterChildren( SwNumberTreeNode& _rCompareNode,
SwNumberTreeNode& _rDestNode )
{ if ( mChildren.empty() ) return;
// determine first child, which has to move to <_rDestNode>
tSwNumberTreeChildren::iterator aItUpper( mChildren.end() ); if ((*mChildren.begin())->IsPhantom() &&
_rCompareNode.LessThan(*(*mChildren.begin())->GetFirstNonPhantomChild()))
{
aItUpper = mChildren.begin();
} else
{
aItUpper = mChildren.upper_bound(&_rCompareNode);
}
// move children if (aItUpper != mChildren.end())
{
tSwNumberTreeChildren::iterator aIt; for (aIt = aItUpper; aIt != mChildren.end(); ++aIt)
(*aIt)->mpParent = &_rDestNode;
// #i60652# // Because <mChildren.erase(aItUpper, mChildren.end())> could destroy // the element, which is referenced by <mItLastValid>, it's needed to // adjust <mItLastValid> before erasing <aIt>.
SetLastValid( mChildren.end() );
// #i60652# // Because <mChildren.erase(aItBegin)> could destroy the element, // which is referenced by <mItLastValid>, it's needed to adjust // <mItLastValid> before erasing <aItBegin>.
SetLastValid(mChildren.end());
if (pMyFirst->IsPhantom())
{
SwNumberTreeNode * pDestLast = nullptr;
if (pDest->mChildren.empty())
pDestLast = pDest->CreatePhantom(); else
pDestLast = *pDest->mChildren.rbegin();
pMyFirst->MoveChildren(pDestLast);
delete pMyFirst;
mChildren.erase(aItBegin);
aItBegin = mChildren.begin();
}
for (auto& rpChild : mChildren)
rpChild->mpParent = pDest;
pDest->mChildren.insert(mChildren.begin(), mChildren.end());
mChildren.clear(); // <stl::set.clear()> destroys all existing iterators. // Thus, <mItLastValid> is also destroyed and reset becomes necessary
mItLastValid = mChildren.end();
}
Search first child A that is greater than pChild, A may be the end of children. If nDepth > 0 then { if A is first child then create new phantom child B at beginning of child list else B is A
Add child to B with depth nDepth - 1. } else { Insert pNode before A.
if A has predecessor B then remove children of B that are greater as A and insert them as children of A. }
*/
if ( nDepth < 0 )
{
OSL_FAIL( " - parameter out of valid range. Serious defect." ); return;
}
if (aInsertedIt != mChildren.begin())
{
tSwNumberTreeChildren::iterator aPredIt = aInsertedIt;
--aPredIt;
// --> // Move greater children of previous node to new child. // This has to be done recursively on the children levels. // Initialize loop variables <pPrevChildNode> and <pDestNode> // for loop on children levels.
SwNumberTreeNode* pPrevChildNode( *aPredIt );
SwNumberTreeNode* pDestNode( pChild ); while ( pDestNode && pPrevChildNode &&
pPrevChildNode->GetChildCount() > 0 )
{ // move children
pPrevChildNode->MoveGreaterChildren( *pChild, *pDestNode );
// prepare next loop: // - search of last child of <pPrevChildNode // - If found, determine destination node if ( pPrevChildNode->GetChildCount() > 0 )
{
tSwNumberTreeChildren::reverse_iterator aIt =
pPrevChildNode->mChildren.rbegin();
pPrevChildNode = *aIt; // determine new destination node if ( pDestNode->GetChildCount() > 0 )
{
pDestNode = *(pDestNode->mChildren.begin()); if ( !pDestNode->IsPhantom() )
{
pDestNode = pDestNode->mpParent->CreatePhantom();
}
} else
{
pDestNode = pDestNode->CreatePhantom();
}
} else
{ // ready -> break loop. break;
}
} // assure that unnecessary created phantoms at <pChild> are deleted.
pChild->ClearObsoletePhantoms();
if ((*aPredIt)->IsValid())
SetLastValid(aPredIt);
} else
SetLastValid(mChildren.end());
ClearObsoletePhantoms();
if( bNotification )
{ // invalidation of not counted parent // and notification of its siblings. if ( !IsCounted() )
{
InvalidateMe();
NotifyInvalidSiblings(rDoc);
}
NotifyInvalidChildren(rDoc);
}
}
}
if (! pRemove->mChildren.empty())
{
pRemove->MoveChildren(*aItPred);
(*aItPred)->InvalidateTree();
(*aItPred)->NotifyInvalidChildren(rDoc);
}
// #i60652# // Because <mChildren.erase(aRemoveIt)> could destroy the element, // which is referenced by <mItLastValid>, it's needed to adjust // <mItLastValid> before erasing <aRemoveIt>. if (aItPred != mChildren.end() && (*aItPred)->IsPhantom())
SetLastValid(mChildren.end()); else
SetLastValid(aItPred);
if (GetParent())
{ if (GetParent()->IsFirst(this))
{
SwNumberTreeNode * pNode = GetParent();
while (pNode)
{ if (!pNode->IsPhantom() && pNode->GetParent())
{
bResult = false; break;
}
pNode = pNode->GetParent();
}
// If node isn't the first child, it is the second child and the // first child is a phantom. In this case check, if the first phantom // child have only phantom children if ( bResult && this != *(GetParent()->mChildren.begin()) &&
!(*(GetParent()->mChildren.begin()))->HasOnlyPhantoms() )
{
bResult = false;
}
} else
bResult = false;
}
return bResult;
}
void SwNumberTreeNode::SetLevelInListTree(constint nLevel, const SwDoc& rDoc)
{ if ( nLevel < 0 )
{
OSL_FAIL( " - parameter out of valid range. Serious defect." ); return;
}
OSL_ENSURE( GetParent(), " - can only be called for number tree nodes in a list tree" ); if ( GetParent() )
{ if ( nLevel != GetLevelInListTree() )
{
SwNumberTreeNode* pRootTreeNode = GetRoot();
OSL_ENSURE( pRootTreeNode, " - no root tree node found. Serious defect." );
bool bFirst = true; for (constauto& rpChild : mChildren)
{ if (rpChild)
{ if (rpChild->IsPhantom())
{
SAL_WARN_IF(rpChild->HasOnlyPhantoms(), "sw.core", "HasOnlyPhantoms: is this an error?");
assert(bFirst && "found phantom not at first position.");
}
assert(rpChild->mpParent == this);
if (mpParent)
{
assert(rpChild->IsPhantom() || !rpChild->LessThan(*this));
}
} else
{
assert(!"found child that is NULL");
}
if (bRecursive)
{
rpChild->IsSane(bRecursive, rParents);
}
if (
bValidating ||
aItValid == mChildren.end() ||
(mItLastValid != mChildren.end() &&
(*aItValid)->LessThan(**mItLastValid))
)
{
mItLastValid = aItValid; // invalidation of children of next not counted is needed if ( GetParent() )
{
tSwNumberTreeChildren::const_iterator aParentChildIt =
GetParent()->GetIterator( this );
++aParentChildIt; if ( aParentChildIt != GetParent()->mChildren.end() )
{
SwNumberTreeNode* pNextNode( *aParentChildIt ); if ( !pNextNode->IsCounted() )
{
pNextNode->InvalidateChildren();
}
}
}
}
{ if (IsContinuous())
{
tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
if (aIt != mChildren.end())
++aIt; else
aIt = mChildren.begin();
while (aIt != mChildren.end())
{
(*aIt)->InvalidateTree();
++aIt;
}
if (mpParent)
{
mpParent->SetLastValid(mpParent->GetIterator(this), bValidating);
}
}
}
}
void SwNumberTreeNode::InvalidateTree() const
{ // do not call SetInvalid, would cause loop !!!
mItLastValid = mChildren.end();
for (constauto& rpChild : mChildren)
rpChild->InvalidateTree();
}
void SwNumberTreeNode::Invalidate(SwNumberTreeNode const * pChild)
{ if (pChild->IsValid())
{
tSwNumberTreeChildren::const_iterator aIt = GetIterator(pChild);
if (aIt != mChildren.begin())
--aIt; else
aIt = mChildren.end();
SetLastValid(aIt);
}
}
void SwNumberTreeNode::InvalidateMe()
{ if (mpParent)
mpParent->Invalidate(this);
}
void SwNumberTreeNode::ValidateMe()
{ if (mpParent)
mpParent->Validate(this);
}
void SwNumberTreeNode::Notify(const SwDoc& rDoc)
{ if (IsNotifiable(rDoc))
{ if (! IsPhantom())
NotifyNode();
for (auto& rpChild : mChildren)
rpChild->Notify(rDoc);
}
}
void SwNumberTreeNode::NotifyInvalidChildren(const SwDoc& rDoc)
{ if (IsNotifiable(rDoc))
{
tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
if (aIt == mChildren.end())
aIt = mChildren.begin(); else
++aIt;
while (aIt != mChildren.end())
{
(*aIt)->Notify(rDoc);
++aIt;
} // notification of next not counted node is also needed. if ( GetParent() )
{
tSwNumberTreeChildren::const_iterator aParentChildIt =
GetParent()->GetIterator( this );
++aParentChildIt; if ( aParentChildIt != GetParent()->mChildren.end() )
{
SwNumberTreeNode* pNextNode( *aParentChildIt ); if ( !pNextNode->IsCounted() )
{
pNextNode->NotifyInvalidChildren(rDoc);
}
}
}
}
if (IsContinuous() && mpParent)
mpParent->NotifyInvalidChildren(rDoc);
}
if ( pPrecedingNode == nullptr && GetRoot() )
{ // <this> node has no children or the given node precedes all its children // and the <this> node isn't the root node. // Thus, compare the given node with the <this> node in order to check, // if the <this> node precedes the given node. if ( !(rNode.LessThan( *this )) )
{
pPrecedingNode = this;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.