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 .
21 #include <SwNumberTree.hxx>
22 #include <osl/diagnose.h>
23 #include <sal/log.hxx>
30 SwNumberTreeNode::SwNumberTreeNode()
31 : mpParent( nullptr ),
33 mbContinueingPreviousSubTree( false ),
36 mItLastValid
= mChildren
.end();
39 SwNumberTreeNode::~SwNumberTreeNode()
41 if (GetChildCount() > 0)
43 if (HasOnlyPhantoms())
45 delete *mChildren
.begin();
48 mItLastValid
= mChildren
.end();
52 OSL_FAIL("lost children!");
56 OSL_ENSURE( IsPhantom() || mpParent
== nullptr, ": I'm not supposed to have a parent.");
58 mpParent
= reinterpret_cast<SwNumberTreeNode
*>(0xdeadbeef);
60 OSL_ENSURE(mChildren
.empty(), "children left!");
63 SwNumberTreeNode
* SwNumberTreeNode::CreatePhantom()
65 SwNumberTreeNode
* pNew
= nullptr;
67 if (! mChildren
.empty() &&
68 (*mChildren
.begin())->IsPhantom())
70 OSL_FAIL("phantom already present");
75 pNew
->mbPhantom
= true;
76 pNew
->mpParent
= this;
78 std::pair
<tSwNumberTreeChildren::iterator
, bool> aInsert
=
79 mChildren
.insert(pNew
);
83 OSL_FAIL("insert of phantom failed!");
93 SwNumberTreeNode
* SwNumberTreeNode::GetRoot() const
95 SwNumberTreeNode
* pResult
= mpParent
;
98 while (pResult
->mpParent
)
99 pResult
= pResult
->mpParent
;
104 void SwNumberTreeNode::ClearObsoletePhantoms()
106 tSwNumberTreeChildren::iterator aIt
= mChildren
.begin();
108 if (!(aIt
!= mChildren
.end() && (*aIt
)->IsPhantom()))
111 (*aIt
)->ClearObsoletePhantoms();
113 if ((*aIt
)->mChildren
.empty())
116 // Because <mChildren.erase(aIt)> could destroy the element, which
117 // is referenced by <mItLastValid>, it's needed to adjust
118 // <mItLastValid> before erasing <aIt>.
119 SetLastValid(mChildren
.end());
122 mChildren
.erase(aIt
);
126 void SwNumberTreeNode::ValidateHierarchical(const SwNumberTreeNode
* pNode
) const
128 tSwNumberTreeChildren::const_iterator aValidateIt
=
131 if (aValidateIt
== mChildren
.end())
134 OSL_ENSURE((*aValidateIt
)->mpParent
== this, "wrong parent");
136 tSwNumberTreeChildren::const_iterator aIt
= mItLastValid
;
140 // - Only one time checked for <mChildren.end()>.
141 // - Less checks for each loop run.
143 // - consider case that current node isn't counted and isn't the first
144 // child of its parent. In this case the number of last counted child
145 // of the previous node determines the start value for the following
146 // children loop, if all children have to be validated and the first
147 // one doesn't restart the counting.
148 SwNumberTree::tSwNumTreeNumber
nTmpNumber( 0 );
149 if (aIt
!= mChildren
.end())
150 nTmpNumber
= (*aIt
)->mnNumber
;
153 aIt
= mChildren
.begin();
154 (*aIt
)->mbContinueingPreviousSubTree
= false;
156 // determine default start value
157 // consider the case that the first child isn't counted.
158 nTmpNumber
= (*aIt
)->GetStartValue();
159 if ( !(*aIt
)->IsCounted() &&
160 ( !(*aIt
)->HasCountedChildren() || (*aIt
)->IsPhantom() ) )
165 // determine special start value for the case that first child
166 // doesn't restart the numbering and the parent node isn't counted
167 // and isn't the first child.
168 const bool bParentCounted( IsCounted() &&
170 HasPhantomCountedParent() ) );
171 if ( !(*aIt
)->IsRestart() &&
172 GetParent() && !bParentCounted
)
174 tSwNumberTreeChildren::const_iterator aParentChildIt
=
175 GetParent()->GetIterator( this );
176 while ( aParentChildIt
!= GetParent()->mChildren
.begin() )
179 SwNumberTreeNode
* pPrevNode( *aParentChildIt
);
180 if ( pPrevNode
->GetChildCount() > 0 )
182 (*aIt
)->mbContinueingPreviousSubTree
= true;
183 nTmpNumber
= (*(pPrevNode
->mChildren
.rbegin()))->GetNumber();
184 if ( (*aIt
)->IsCounted() &&
185 ( !(*aIt
)->IsPhantom() ||
186 (*aIt
)->HasPhantomCountedParent() ) )
192 else if ( pPrevNode
->IsCounted() )
198 // Previous node has no children and is not counted.
199 // Thus, next turn and check for the previous node.
204 (*aIt
)->mnNumber
= nTmpNumber
;
207 while (aIt
!= aValidateIt
)
210 (*aIt
)->mbContinueingPreviousSubTree
= false;
212 // --> only for counted nodes the number
213 // has to be adjusted, compared to the previous node.
214 // this condition is hold also for nodes, which restart the numbering.
215 if ( (*aIt
)->IsCounted() )
217 if ((*aIt
)->IsRestart())
218 nTmpNumber
= (*aIt
)->GetStartValue();
223 (*aIt
)->mnNumber
= nTmpNumber
;
226 SetLastValid(aIt
, true);
229 void SwNumberTreeNode::ValidateContinuous(const SwNumberTreeNode
* pNode
) const
231 tSwNumberTreeChildren::const_iterator aIt
= mItLastValid
;
235 if (aIt
== mChildren
.end())
237 aIt
= mChildren
.begin();
242 if (aIt
!= mChildren
.end())
244 SwNumberTree::tSwNumTreeNumber nTmpNumber
= 0;
245 SwNumberTreeNode
* pPred
= (*aIt
)->GetPred();
248 // correct consideration of phantoms
249 // correct consideration of restart at a number tree node
252 if ( !(*aIt
)->IsCounted() )
254 nTmpNumber
= pPred
->GetNumber( pPred
->GetParent() != (*aIt
)->GetParent() );
257 if ( (*aIt
)->IsRestart() )
258 nTmpNumber
= (*aIt
)->GetStartValue();
260 nTmpNumber
= pPred
->GetNumber( pPred
->GetParent() != (*aIt
)->GetParent() ) + 1;
265 if ( !(*aIt
)->IsCounted() )
266 nTmpNumber
= GetStartValue() - 1;
269 if ( (*aIt
)->IsRestart() )
270 nTmpNumber
= (*aIt
)->GetStartValue();
272 nTmpNumber
= GetStartValue();
276 (*aIt
)->mnNumber
= nTmpNumber
;
279 while (aIt
!= mChildren
.end() && *aIt
!= pNode
);
281 // #i74748# - applied patch from garnier_romain
282 // number tree node has to be validated.
283 SetLastValid( aIt
, true );
286 void SwNumberTreeNode::Validate(const SwNumberTreeNode
* pNode
) const
288 if (! IsValid(pNode
))
291 ValidateContinuous(pNode
);
293 ValidateHierarchical(pNode
);
297 void SwNumberTreeNode::GetNumberVector_(SwNumberTree::tNumberVector
& rVector
,
298 bool bValidate
) const
302 mpParent
->GetNumberVector_(rVector
, bValidate
);
303 rVector
.push_back(GetNumber(bValidate
));
307 SwNumberTreeNode
* SwNumberTreeNode::GetFirstNonPhantomChild()
310 return (*mChildren
.begin())->GetFirstNonPhantomChild();
315 /** Moves all children of this node that are greater than a given node
316 to the destination node.
318 void SwNumberTreeNode::MoveGreaterChildren( SwNumberTreeNode
& _rCompareNode
,
319 SwNumberTreeNode
& _rDestNode
)
321 if ( mChildren
.empty() )
324 // determine first child, which has to move to <_rDestNode>
325 tSwNumberTreeChildren::iterator
aItUpper( mChildren
.end() );
326 if ((*mChildren
.begin())->IsPhantom() &&
327 _rCompareNode
.LessThan(*(*mChildren
.begin())->GetFirstNonPhantomChild()))
329 aItUpper
= mChildren
.begin();
333 aItUpper
= mChildren
.upper_bound(&_rCompareNode
);
337 if (aItUpper
!= mChildren
.end())
339 tSwNumberTreeChildren::iterator aIt
;
340 for (aIt
= aItUpper
; aIt
!= mChildren
.end(); ++aIt
)
341 (*aIt
)->mpParent
= &_rDestNode
;
343 _rDestNode
.mChildren
.insert(aItUpper
, mChildren
.end());
346 // Because <mChildren.erase(aItUpper, mChildren.end())> could destroy
347 // the element, which is referenced by <mItLastValid>, it's needed to
348 // adjust <mItLastValid> before erasing <aIt>.
349 SetLastValid( mChildren
.end() );
351 mChildren
.erase(aItUpper
, mChildren
.end());
354 if ( !mChildren
.empty() )
356 SetLastValid( --(mChildren
.end()) );
362 _rDestNode
.IsSane(true);
366 void SwNumberTreeNode::MoveChildren(SwNumberTreeNode
* pDest
)
368 if (! mChildren
.empty())
370 tSwNumberTreeChildren::iterator aItBegin
= mChildren
.begin();
371 SwNumberTreeNode
* pMyFirst
= *mChildren
.begin();
374 // Because <mChildren.erase(aItBegin)> could destroy the element,
375 // which is referenced by <mItLastValid>, it's needed to adjust
376 // <mItLastValid> before erasing <aItBegin>.
377 SetLastValid(mChildren
.end());
379 if (pMyFirst
->IsPhantom())
381 SwNumberTreeNode
* pDestLast
= nullptr;
383 if (pDest
->mChildren
.empty())
384 pDestLast
= pDest
->CreatePhantom();
386 pDestLast
= *pDest
->mChildren
.rbegin();
388 pMyFirst
->MoveChildren(pDestLast
);
391 mChildren
.erase(aItBegin
);
393 aItBegin
= mChildren
.begin();
396 for (auto& rpChild
: mChildren
)
397 rpChild
->mpParent
= pDest
;
399 pDest
->mChildren
.insert(mChildren
.begin(), mChildren
.end());
401 // <stl::set.clear()> destroys all existing iterators.
402 // Thus, <mItLastValid> is also destroyed and reset becomes necessary
403 mItLastValid
= mChildren
.end();
406 OSL_ENSURE(mChildren
.empty(), "MoveChildren failed!");
410 pDest
->IsSane(false);
414 void SwNumberTreeNode::AddChild(SwNumberTreeNode
* pChild
,
421 Search first child A that is greater than pChild,
422 A may be the end of children.
425 if A is first child then
426 create new phantom child B at beginning of child list
430 Add child to B with depth nDepth - 1.
434 Insert pNode before A.
436 if A has predecessor B then
437 remove children of B that are greater as A and insert them as
445 OSL_FAIL( "<SwNumberTreeNode::AddChild(..)> - parameter <nDepth> out of valid range. Serious defect." );
449 if ( pChild
->GetParent() != nullptr || pChild
->GetChildCount() > 0 )
451 OSL_FAIL("only orphans allowed.");
457 tSwNumberTreeChildren::iterator aInsertDeepIt
=
458 mChildren
.upper_bound(pChild
);
460 OSL_ENSURE(! (aInsertDeepIt
!= mChildren
.end() &&
461 (*aInsertDeepIt
)->IsPhantom()), " unexpected phantom");
463 if (aInsertDeepIt
== mChildren
.begin())
465 SwNumberTreeNode
* pNew
= CreatePhantom();
467 SetLastValid(mChildren
.end());
470 pNew
->AddChild(pChild
, nDepth
- 1, rDoc
);
475 (*aInsertDeepIt
)->AddChild(pChild
, nDepth
- 1, rDoc
);
482 std::pair
<tSwNumberTreeChildren::iterator
, bool> aResult
=
483 mChildren
.insert(pChild
);
487 pChild
->mpParent
= this;
488 bool bNotification
= pChild
->IsNotificationEnabled(rDoc
);
489 tSwNumberTreeChildren::iterator aInsertedIt
= aResult
.first
;
491 if (aInsertedIt
!= mChildren
.begin())
493 tSwNumberTreeChildren::iterator aPredIt
= aInsertedIt
;
497 // Move greater children of previous node to new child.
498 // This has to be done recursively on the children levels.
499 // Initialize loop variables <pPrevChildNode> and <pDestNode>
500 // for loop on children levels.
501 SwNumberTreeNode
* pPrevChildNode( *aPredIt
);
502 SwNumberTreeNode
* pDestNode( pChild
);
503 while ( pDestNode
&& pPrevChildNode
&&
504 pPrevChildNode
->GetChildCount() > 0 )
507 pPrevChildNode
->MoveGreaterChildren( *pChild
, *pDestNode
);
509 // prepare next loop:
510 // - search of last child of <pPrevChildNode
511 // - If found, determine destination node
512 if ( pPrevChildNode
->GetChildCount() > 0 )
514 tSwNumberTreeChildren::reverse_iterator aIt
=
515 pPrevChildNode
->mChildren
.rbegin();
516 pPrevChildNode
= *aIt
;
517 // determine new destination node
518 if ( pDestNode
->GetChildCount() > 0 )
520 pDestNode
= *(pDestNode
->mChildren
.begin());
521 if ( !pDestNode
->IsPhantom() )
523 pDestNode
= pDestNode
->mpParent
->CreatePhantom();
528 pDestNode
= pDestNode
->CreatePhantom();
533 // ready -> break loop.
537 // assure that unnecessary created phantoms at <pChild> are deleted.
538 pChild
->ClearObsoletePhantoms();
540 if ((*aPredIt
)->IsValid())
541 SetLastValid(aPredIt
);
544 SetLastValid(mChildren
.end());
546 ClearObsoletePhantoms();
550 // invalidation of not counted parent
551 // and notification of its siblings.
555 NotifyInvalidSiblings(rDoc
);
557 NotifyInvalidChildren(rDoc
);
567 void SwNumberTreeNode::RemoveChild(SwNumberTreeNode
* pChild
, const SwDoc
& rDoc
)
572 if pChild has predecessor A then
575 create phantom child B at beginning of child list
577 Move children of pChild to B.
580 if (pChild
->IsPhantom())
582 OSL_FAIL("not applicable to phantoms!");
587 tSwNumberTreeChildren::const_iterator aRemoveIt
= GetIterator(pChild
);
589 if (aRemoveIt
!= mChildren
.end())
591 SwNumberTreeNode
* pRemove
= *aRemoveIt
;
593 pRemove
->mpParent
= nullptr;
595 tSwNumberTreeChildren::const_iterator aItPred
= mChildren
.end();
597 if (aRemoveIt
== mChildren
.begin())
599 if (! pRemove
->mChildren
.empty())
603 aItPred
= mChildren
.begin();
612 if (! pRemove
->mChildren
.empty())
614 pRemove
->MoveChildren(*aItPred
);
615 (*aItPred
)->InvalidateTree();
616 (*aItPred
)->NotifyInvalidChildren(rDoc
);
620 // Because <mChildren.erase(aRemoveIt)> could destroy the element,
621 // which is referenced by <mItLastValid>, it's needed to adjust
622 // <mItLastValid> before erasing <aRemoveIt>.
623 if (aItPred
!= mChildren
.end() && (*aItPred
)->IsPhantom())
624 SetLastValid(mChildren
.end());
626 SetLastValid(aItPred
);
628 mChildren
.erase(aRemoveIt
);
630 NotifyInvalidChildren(rDoc
);
634 OSL_FAIL("RemoveChild: failed!");
637 pChild
->PostRemove();
640 void SwNumberTreeNode::RemoveMe(const SwDoc
& rDoc
)
645 SwNumberTreeNode
* pSavedParent
= mpParent
;
647 pSavedParent
->RemoveChild(this, rDoc
);
649 while (pSavedParent
&& pSavedParent
->IsPhantom() &&
650 pSavedParent
->HasOnlyPhantoms())
651 pSavedParent
= pSavedParent
->GetParent();
654 pSavedParent
->ClearObsoletePhantoms();
661 bool SwNumberTreeNode::IsValid() const
663 return mpParent
&& mpParent
->IsValid(this);
666 SwNumberTree::tSwNumTreeNumber
SwNumberTreeNode::GetNumber(bool bValidate
)
669 if (bValidate
&& mpParent
)
670 mpParent
->Validate(this);
676 SwNumberTree::tNumberVector
SwNumberTreeNode::GetNumberVector() const
678 vector
<SwNumberTree::tSwNumTreeNumber
> aResult
;
680 GetNumberVector_(aResult
);
685 bool SwNumberTreeNode::IsValid(const SwNumberTreeNode
* pChild
) const
687 bool bResult
= false;
689 if (mItLastValid
!= mChildren
.end())
691 if (pChild
&& pChild
->mpParent
== this)
693 bResult
= ! (*mItLastValid
)->LessThan(*pChild
);
701 bool SwNumberTreeNode::HasOnlyPhantoms() const
703 bool bResult
= false;
705 if (GetChildCount() == 1)
707 tSwNumberTreeChildren::const_iterator aIt
= mChildren
.begin();
709 bResult
= (*aIt
)->IsPhantom() && (*aIt
)->HasOnlyPhantoms();
711 else if (GetChildCount() == 0)
717 bool SwNumberTreeNode::IsCounted() const
719 return !IsPhantom() ||
720 ( IsCountPhantoms() && HasCountedChildren() );
723 bool SwNumberTreeNode::HasPhantomCountedParent() const
727 OSL_ENSURE( IsPhantom(),
728 "<SwNumberTreeNode::HasPhantomCountedParent()> - wrong usage of method - it's only for phantoms" );
729 if ( IsPhantom() && mpParent
)
731 if ( mpParent
== GetRoot() )
735 else if ( !mpParent
->IsPhantom() )
737 bRet
= mpParent
->IsCounted();
741 bRet
= mpParent
->IsCounted() && mpParent
->HasPhantomCountedParent();
748 bool SwNumberTreeNode::IsFirst(const SwNumberTreeNode
* pNode
) const
750 tSwNumberTreeChildren::const_iterator aIt
= mChildren
.begin();
752 if ((*aIt
)->IsPhantom())
755 return *aIt
== pNode
;
758 bool SwNumberTreeNode::IsFirst() const
764 if (GetParent()->IsFirst(this))
766 SwNumberTreeNode
* pNode
= GetParent();
770 if (!pNode
->IsPhantom() && pNode
->GetParent())
776 pNode
= pNode
->GetParent();
779 // If node isn't the first child, it is the second child and the
780 // first child is a phantom. In this case check, if the first phantom
781 // child have only phantom children
783 this != *(GetParent()->mChildren
.begin()) &&
784 !(*(GetParent()->mChildren
.begin()))->HasOnlyPhantoms() )
796 void SwNumberTreeNode::SetLevelInListTree(const int nLevel
, const SwDoc
& rDoc
)
800 OSL_FAIL( "<SwNumberTreeNode::SetLevelInListTree(..)> - parameter <nLevel> out of valid range. Serious defect." );
804 OSL_ENSURE( GetParent(),
805 "<SwNumberTreeNode::SetLevelInListTree(..)> - can only be called for number tree nodes in a list tree" );
808 if ( nLevel
!= GetLevelInListTree() )
810 SwNumberTreeNode
* pRootTreeNode
= GetRoot();
811 OSL_ENSURE( pRootTreeNode
,
812 "<SwNumberTreeNode::SetLevelInListTree(..)> - no root tree node found. Serious defect." );
815 pRootTreeNode
->AddChild(this, nLevel
, rDoc
);
820 int SwNumberTreeNode::GetLevelInListTree() const
823 return mpParent
->GetLevelInListTree() + 1;
828 SwNumberTreeNode::tSwNumberTreeChildren::size_type
829 SwNumberTreeNode::GetChildCount() const
831 return mChildren
.size();
835 void SwNumberTreeNode::IsSane(bool bRecursive
) const
837 vector
<const SwNumberTreeNode
*> aParents
;
839 return IsSane(bRecursive
, std::move(aParents
));
842 void SwNumberTreeNode::IsSane(bool bRecursive
,
843 vector
<const SwNumberTreeNode
*> rParents
)
846 assert(find(rParents
.begin(), rParents
.end(), this) == rParents
.end());
848 assert(rParents
.empty() || rParents
.back() == mpParent
);
850 rParents
.push_back(this);
853 for (const auto& rpChild
: mChildren
)
857 if (rpChild
->IsPhantom())
859 SAL_WARN_IF(rpChild
->HasOnlyPhantoms(), "sw.core",
860 "HasOnlyPhantoms: is this an error?");
862 assert(bFirst
&& "found phantom not at first position.");
865 assert(rpChild
->mpParent
== this);
869 assert(rpChild
->IsPhantom() || !rpChild
->LessThan(*this));
874 assert(!"found child that is NULL");
879 rpChild
->IsSane(bRecursive
, rParents
);
889 SwNumberTreeNode::tSwNumberTreeChildren::const_iterator
890 SwNumberTreeNode::GetIterator(const SwNumberTreeNode
* pChild
) const
892 tSwNumberTreeChildren::const_iterator aItResult
=
893 mChildren
.find(const_cast<SwNumberTreeNode
*>(pChild
));
895 OSL_ENSURE( aItResult
!= mChildren
.end(),
896 "something went wrong getting the iterator for a child");
901 bool SwNumberTreeNodeLessThan(const SwNumberTreeNode
* pA
,
902 const SwNumberTreeNode
* pB
)
904 bool bResult
= false;
906 if (pA
== nullptr && pB
!= nullptr)
908 else if (pA
!= nullptr && pB
!= nullptr)
909 bResult
= pA
->LessThan(*pB
);
914 SwNumberTreeNode
* SwNumberTreeNode::GetLastDescendant() const
916 SwNumberTreeNode
* pResult
= nullptr;
917 tSwNumberTreeChildren::const_reverse_iterator aIt
= mChildren
.rbegin();
919 if (aIt
!= mChildren
.rend())
921 pResult
= (*aIt
)->GetLastDescendant();
930 bool SwNumberTreeNode::LessThan(const SwNumberTreeNode
& rTreeNode
) const
932 return this < &rTreeNode
;
935 SwNumberTreeNode
* SwNumberTreeNode::GetPred(bool bSibling
) const
937 SwNumberTreeNode
* pResult
= nullptr;
941 tSwNumberTreeChildren::const_iterator aIt
=
942 mpParent
->GetIterator(this);
944 if ( aIt
== mpParent
->mChildren
.begin() )
947 // root node is no valid predecessor
948 pResult
= mpParent
->GetParent() ? mpParent
: nullptr;
955 pResult
= (*aIt
)->GetLastDescendant();
967 void SwNumberTreeNode::SetLastValid
968 ( const SwNumberTreeNode::tSwNumberTreeChildren::const_iterator
& aItValid
,
969 bool bValidating
) const
971 OSL_ENSURE( (aItValid
== mChildren
.end() || GetIterator(*aItValid
) != mChildren
.end()),
972 "last-valid iterator");
976 aItValid
== mChildren
.end() ||
977 (mItLastValid
!= mChildren
.end() &&
978 (*aItValid
)->LessThan(**mItLastValid
))
981 mItLastValid
= aItValid
;
982 // invalidation of children of next not counted is needed
985 tSwNumberTreeChildren::const_iterator aParentChildIt
=
986 GetParent()->GetIterator( this );
988 if ( aParentChildIt
!= GetParent()->mChildren
.end() )
990 SwNumberTreeNode
* pNextNode( *aParentChildIt
);
991 if ( !pNextNode
->IsCounted() )
993 pNextNode
->InvalidateChildren();
1002 tSwNumberTreeChildren::const_iterator aIt
= mItLastValid
;
1004 if (aIt
!= mChildren
.end())
1007 aIt
= mChildren
.begin();
1009 while (aIt
!= mChildren
.end())
1011 (*aIt
)->InvalidateTree();
1018 mpParent
->SetLastValid(mpParent
->GetIterator(this), bValidating
);
1024 void SwNumberTreeNode::InvalidateTree() const
1026 // do not call SetInvalid, would cause loop !!!
1027 mItLastValid
= mChildren
.end();
1029 for (const auto& rpChild
: mChildren
)
1030 rpChild
->InvalidateTree();
1033 void SwNumberTreeNode::Invalidate(SwNumberTreeNode
const * pChild
)
1035 if (pChild
->IsValid())
1037 tSwNumberTreeChildren::const_iterator aIt
= GetIterator(pChild
);
1039 if (aIt
!= mChildren
.begin())
1042 aIt
= mChildren
.end();
1049 void SwNumberTreeNode::InvalidateMe()
1052 mpParent
->Invalidate(this);
1055 void SwNumberTreeNode::ValidateMe()
1058 mpParent
->Validate(this);
1061 void SwNumberTreeNode::Notify(const SwDoc
& rDoc
)
1063 if (IsNotifiable(rDoc
))
1068 for (auto& rpChild
: mChildren
)
1069 rpChild
->Notify(rDoc
);
1073 void SwNumberTreeNode::NotifyInvalidChildren(const SwDoc
& rDoc
)
1075 if (IsNotifiable(rDoc
))
1077 tSwNumberTreeChildren::const_iterator aIt
= mItLastValid
;
1079 if (aIt
== mChildren
.end())
1080 aIt
= mChildren
.begin();
1084 while (aIt
!= mChildren
.end())
1086 (*aIt
)->Notify(rDoc
);
1090 // notification of next not counted node is also needed.
1093 tSwNumberTreeChildren::const_iterator aParentChildIt
=
1094 GetParent()->GetIterator( this );
1096 if ( aParentChildIt
!= GetParent()->mChildren
.end() )
1098 SwNumberTreeNode
* pNextNode( *aParentChildIt
);
1099 if ( !pNextNode
->IsCounted() )
1101 pNextNode
->NotifyInvalidChildren(rDoc
);
1108 if (IsContinuous() && mpParent
)
1109 mpParent
->NotifyInvalidChildren(rDoc
);
1112 void SwNumberTreeNode::NotifyInvalidSiblings(const SwDoc
& rDoc
)
1114 if (mpParent
!= nullptr)
1115 mpParent
->NotifyInvalidChildren(rDoc
);
1119 const SwNumberTreeNode
* SwNumberTreeNode::GetPrecedingNodeOf(
1120 const SwNumberTreeNode
& rNode
) const
1122 const SwNumberTreeNode
* pPrecedingNode( nullptr );
1124 if ( GetChildCount() > 0 )
1126 tSwNumberTreeChildren::const_iterator aUpperBoundIt
=
1127 mChildren
.upper_bound( const_cast<SwNumberTreeNode
*>(&rNode
) );
1128 if ( aUpperBoundIt
!= mChildren
.begin() )
1131 pPrecedingNode
= (*aUpperBoundIt
)->GetPrecedingNodeOf( rNode
);
1135 if ( pPrecedingNode
== nullptr && GetRoot() )
1137 // <this> node has no children or the given node precedes all its children
1138 // and the <this> node isn't the root node.
1139 // Thus, compare the given node with the <this> node in order to check,
1140 // if the <this> node precedes the given node.
1141 if ( !(rNode
.LessThan( *this )) )
1143 pPrecedingNode
= this;
1147 return pPrecedingNode
;
1150 void SwNumberTreeNode::NotifyNodesOnListLevel( const int nListLevel
)
1152 if ( nListLevel
< 0 )
1154 OSL_FAIL( "<SwNumberTreeNode::NotifyNodesOnListLevel(..)> - invalid list level provided" );
1158 SwNumberTreeNode
* pRootNode
= GetParent() ? GetRoot() : this;
1160 pRootNode
->NotifyChildrenOnDepth( nListLevel
);
1163 void SwNumberTreeNode::NotifyChildrenOnDepth( const int nDepth
)
1165 OSL_ENSURE( nDepth
>= 0,
1166 "<SwNumberTreeNode::NotifyChildrenOnDepth(..)> - misusage" );
1168 for ( const auto& rpChild
: mChildren
)
1172 rpChild
->NotifyNode();
1176 rpChild
->NotifyChildrenOnDepth( nDepth
- 1 );
1181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */