Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / SwNumberTree / SwNumberTree.cxx
blob30cdff34b7bcfd81015365c32ee88c3a3c4a7944
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <algorithm>
21 #include <SwNumberTree.hxx>
22 #include <osl/diagnose.h>
23 #include <sal/log.hxx>
25 #include <cassert>
27 using std::vector;
28 using std::find;
30 SwNumberTreeNode::SwNumberTreeNode()
31 : mpParent( nullptr ),
32 mnNumber( 0 ),
33 mbContinueingPreviousSubTree( false ),
34 mbPhantom( false )
36 mItLastValid = mChildren.end();
39 SwNumberTreeNode::~SwNumberTreeNode()
41 if (GetChildCount() > 0)
43 if (HasOnlyPhantoms())
45 delete *mChildren.begin();
47 mChildren.clear();
48 mItLastValid = mChildren.end();
50 else
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");
72 else
74 pNew = Create();
75 pNew->mbPhantom = true;
76 pNew->mpParent = this;
78 std::pair<tSwNumberTreeChildren::iterator, bool> aInsert =
79 mChildren.insert(pNew);
81 if (! aInsert.second)
83 OSL_FAIL("insert of phantom failed!");
85 delete pNew;
86 pNew = nullptr;
90 return pNew;
93 SwNumberTreeNode * SwNumberTreeNode::GetRoot() const
95 SwNumberTreeNode * pResult = mpParent;
97 if (pResult)
98 while (pResult->mpParent)
99 pResult = pResult->mpParent;
101 return pResult;
104 void SwNumberTreeNode::ClearObsoletePhantoms()
106 tSwNumberTreeChildren::iterator aIt = mChildren.begin();
108 if (!(aIt != mChildren.end() && (*aIt)->IsPhantom()))
109 return;
111 (*aIt)->ClearObsoletePhantoms();
113 if ((*aIt)->mChildren.empty())
115 // #i60652#
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());
121 delete *aIt;
122 mChildren.erase(aIt);
126 void SwNumberTreeNode::ValidateHierarchical(const SwNumberTreeNode * pNode) const
128 tSwNumberTreeChildren::const_iterator aValidateIt =
129 GetIterator(pNode);
131 if (aValidateIt == mChildren.end())
132 return;
134 OSL_ENSURE((*aValidateIt)->mpParent == this, "wrong parent");
136 tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
138 // -->
139 // improvement:
140 // - Only one time checked for <mChildren.end()>.
141 // - Less checks for each loop run.
142 // correction:
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;
151 else
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() ) )
162 --nTmpNumber;
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() &&
169 ( !IsPhantom() ||
170 HasPhantomCountedParent() ) );
171 if ( !(*aIt)->IsRestart() &&
172 GetParent() && !bParentCounted )
174 tSwNumberTreeChildren::const_iterator aParentChildIt =
175 GetParent()->GetIterator( this );
176 while ( aParentChildIt != GetParent()->mChildren.begin() )
178 --aParentChildIt;
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() ) )
188 ++nTmpNumber;
190 break;
192 else if ( pPrevNode->IsCounted() )
194 break;
196 else
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)
209 ++aIt;
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();
219 else
220 ++nTmpNumber;
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();
239 else
240 ++aIt;
242 if (aIt != mChildren.end())
244 SwNumberTree::tSwNumTreeNumber nTmpNumber = 0;
245 SwNumberTreeNode * pPred = (*aIt)->GetPred();
247 // #i64311#
248 // correct consideration of phantoms
249 // correct consideration of restart at a number tree node
250 if ( pPred )
252 if ( !(*aIt)->IsCounted() )
253 // #i65284#
254 nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() );
255 else
257 if ( (*aIt)->IsRestart() )
258 nTmpNumber = (*aIt)->GetStartValue();
259 else
260 nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() ) + 1;
263 else
265 if ( !(*aIt)->IsCounted() )
266 nTmpNumber = GetStartValue() - 1;
267 else
269 if ( (*aIt)->IsRestart() )
270 nTmpNumber = (*aIt)->GetStartValue();
271 else
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))
290 if (IsContinuous())
291 ValidateContinuous(pNode);
292 else
293 ValidateHierarchical(pNode);
297 void SwNumberTreeNode::GetNumberVector_(SwNumberTree::tNumberVector & rVector,
298 bool bValidate) const
300 if (mpParent)
302 mpParent->GetNumberVector_(rVector, bValidate);
303 rVector.push_back(GetNumber(bValidate));
307 SwNumberTreeNode * SwNumberTreeNode::GetFirstNonPhantomChild()
309 if (IsPhantom())
310 return (*mChildren.begin())->GetFirstNonPhantomChild();
312 return this;
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() )
322 return;
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();
331 else
333 aItUpper = mChildren.upper_bound(&_rCompareNode);
336 // move children
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());
345 // #i60652#
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());
353 // #i60652#
354 if ( !mChildren.empty() )
356 SetLastValid( --(mChildren.end()) );
360 #ifdef DBG_UTIL
361 IsSane(false);
362 _rDestNode.IsSane(true);
363 #endif
366 void SwNumberTreeNode::MoveChildren(SwNumberTreeNode * pDest)
368 if (! mChildren.empty())
370 tSwNumberTreeChildren::iterator aItBegin = mChildren.begin();
371 SwNumberTreeNode * pMyFirst = *mChildren.begin();
373 // #i60652#
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();
385 else
386 pDestLast = *pDest->mChildren.rbegin();
388 pMyFirst->MoveChildren(pDestLast);
390 delete pMyFirst;
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());
400 mChildren.clear();
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!");
408 #ifdef DBG_UTIL
409 IsSane(false);
410 pDest->IsSane(false);
411 #endif
414 void SwNumberTreeNode::AddChild(SwNumberTreeNode* pChild,
415 const int nDepth,
416 const SwDoc& rDoc)
419 Algorithm:
421 Search first child A that is greater than pChild,
422 A may be the end of children.
423 If nDepth > 0 then
425 if A is first child then
426 create new phantom child B at beginning of child list
427 else
428 B is A
430 Add child to B with depth nDepth - 1.
432 else
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
438 children of A.
443 if ( nDepth < 0 )
445 OSL_FAIL( "<SwNumberTreeNode::AddChild(..)> - parameter <nDepth> out of valid range. Serious defect." );
446 return;
449 if ( pChild->GetParent() != nullptr || pChild->GetChildCount() > 0 )
451 OSL_FAIL("only orphans allowed.");
452 return;
455 if (nDepth > 0)
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());
469 if (pNew)
470 pNew->AddChild(pChild, nDepth - 1, rDoc);
472 else
474 --aInsertDeepIt;
475 (*aInsertDeepIt)->AddChild(pChild, nDepth - 1, rDoc);
479 else
481 pChild->PreAdd();
482 std::pair<tSwNumberTreeChildren::iterator, bool> aResult =
483 mChildren.insert(pChild);
485 if (aResult.second)
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;
494 --aPredIt;
496 // -->
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 )
506 // move children
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();
526 else
528 pDestNode = pDestNode->CreatePhantom();
531 else
533 // ready -> break loop.
534 break;
537 // assure that unnecessary created phantoms at <pChild> are deleted.
538 pChild->ClearObsoletePhantoms();
540 if ((*aPredIt)->IsValid())
541 SetLastValid(aPredIt);
543 else
544 SetLastValid(mChildren.end());
546 ClearObsoletePhantoms();
548 if( bNotification )
550 // invalidation of not counted parent
551 // and notification of its siblings.
552 if ( !IsCounted() )
554 InvalidateMe();
555 NotifyInvalidSiblings(rDoc);
557 NotifyInvalidChildren(rDoc);
562 #ifdef DBG_UTIL
563 IsSane(false);
564 #endif
567 void SwNumberTreeNode::RemoveChild(SwNumberTreeNode* pChild, const SwDoc& rDoc)
570 Algorithm:
572 if pChild has predecessor A then
573 B is A
574 else
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!");
584 return;
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())
601 CreatePhantom();
603 aItPred = mChildren.begin();
606 else
608 aItPred = aRemoveIt;
609 --aItPred;
612 if (! pRemove->mChildren.empty())
614 pRemove->MoveChildren(*aItPred);
615 (*aItPred)->InvalidateTree();
616 (*aItPred)->NotifyInvalidChildren(rDoc);
619 // #i60652#
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());
625 else
626 SetLastValid(aItPred);
628 mChildren.erase(aRemoveIt);
630 NotifyInvalidChildren(rDoc);
632 else
634 OSL_FAIL("RemoveChild: failed!");
637 pChild->PostRemove();
640 void SwNumberTreeNode::RemoveMe(const SwDoc& rDoc)
642 if (!mpParent)
643 return;
645 SwNumberTreeNode * pSavedParent = mpParent;
647 pSavedParent->RemoveChild(this, rDoc);
649 while (pSavedParent && pSavedParent->IsPhantom() &&
650 pSavedParent->HasOnlyPhantoms())
651 pSavedParent = pSavedParent->GetParent();
653 if (pSavedParent)
654 pSavedParent->ClearObsoletePhantoms();
656 #ifdef DBG_UTIL
657 IsSane(false);
658 #endif
661 bool SwNumberTreeNode::IsValid() const
663 return mpParent && mpParent->IsValid(this);
666 SwNumberTree::tSwNumTreeNumber SwNumberTreeNode::GetNumber(bool bValidate)
667 const
669 if (bValidate && mpParent)
670 mpParent->Validate(this);
672 return mnNumber;
676 SwNumberTree::tNumberVector SwNumberTreeNode::GetNumberVector() const
678 vector<SwNumberTree::tSwNumTreeNumber> aResult;
680 GetNumberVector_(aResult);
682 return 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);
697 return bResult;
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)
712 bResult = true;
714 return bResult;
717 bool SwNumberTreeNode::IsCounted() const
719 return !IsPhantom() ||
720 ( IsCountPhantoms() && HasCountedChildren() );
723 bool SwNumberTreeNode::HasPhantomCountedParent() const
725 bool bRet( false );
727 OSL_ENSURE( IsPhantom(),
728 "<SwNumberTreeNode::HasPhantomCountedParent()> - wrong usage of method - it's only for phantoms" );
729 if ( IsPhantom() && mpParent )
731 if ( mpParent == GetRoot() )
733 bRet = true;
735 else if ( !mpParent->IsPhantom() )
737 bRet = mpParent->IsCounted();
739 else
741 bRet = mpParent->IsCounted() && mpParent->HasPhantomCountedParent();
745 return bRet;
748 bool SwNumberTreeNode::IsFirst(const SwNumberTreeNode * pNode) const
750 tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
752 if ((*aIt)->IsPhantom())
753 ++aIt;
755 return *aIt == pNode;
758 bool SwNumberTreeNode::IsFirst() const
760 bool bResult = true;
762 if (GetParent())
764 if (GetParent()->IsFirst(this))
766 SwNumberTreeNode * pNode = GetParent();
768 while (pNode)
770 if (!pNode->IsPhantom() && pNode->GetParent())
772 bResult = false;
773 break;
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
782 if ( bResult &&
783 this != *(GetParent()->mChildren.begin()) &&
784 !(*(GetParent()->mChildren.begin()))->HasOnlyPhantoms() )
786 bResult = false;
789 else
790 bResult = false;
793 return bResult;
796 void SwNumberTreeNode::SetLevelInListTree(const int nLevel, const SwDoc& rDoc)
798 if ( nLevel < 0 )
800 OSL_FAIL( "<SwNumberTreeNode::SetLevelInListTree(..)> - parameter <nLevel> out of valid range. Serious defect." );
801 return;
804 OSL_ENSURE( GetParent(),
805 "<SwNumberTreeNode::SetLevelInListTree(..)> - can only be called for number tree nodes in a list tree" );
806 if ( GetParent() )
808 if ( nLevel != GetLevelInListTree() )
810 SwNumberTreeNode* pRootTreeNode = GetRoot();
811 OSL_ENSURE( pRootTreeNode,
812 "<SwNumberTreeNode::SetLevelInListTree(..)> - no root tree node found. Serious defect." );
814 RemoveMe(rDoc);
815 pRootTreeNode->AddChild(this, nLevel, rDoc);
820 int SwNumberTreeNode::GetLevelInListTree() const
822 if (mpParent)
823 return mpParent->GetLevelInListTree() + 1;
825 return -1;
828 SwNumberTreeNode::tSwNumberTreeChildren::size_type
829 SwNumberTreeNode::GetChildCount() const
831 return mChildren.size();
834 #ifdef DBG_UTIL
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)
844 const
846 assert(find(rParents.begin(), rParents.end(), this) == rParents.end());
848 assert(rParents.empty() || rParents.back() == mpParent);
850 rParents.push_back(this);
852 bool bFirst = true;
853 for (const auto& rpChild : mChildren)
855 if (rpChild)
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);
867 if (mpParent)
869 assert(rpChild->IsPhantom() || !rpChild->LessThan(*this));
872 else
874 assert(!"found child that is NULL");
877 if (bRecursive)
879 rpChild->IsSane(bRecursive, rParents);
882 bFirst = false;
885 rParents.pop_back();
887 #endif // DBG_UTIL
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");
898 return aItResult;
901 bool SwNumberTreeNodeLessThan(const SwNumberTreeNode * pA,
902 const SwNumberTreeNode * pB)
904 bool bResult = false;
906 if (pA == nullptr && pB != nullptr)
907 bResult = true;
908 else if (pA != nullptr && pB != nullptr)
909 bResult = pA->LessThan(*pB);
911 return bResult;
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();
923 if (! pResult)
924 pResult = *aIt;
927 return pResult;
930 bool SwNumberTreeNode::LessThan(const SwNumberTreeNode & rTreeNode) const
932 return this < &rTreeNode;
935 SwNumberTreeNode * SwNumberTreeNode::GetPred(bool bSibling) const
937 SwNumberTreeNode * pResult = nullptr;
939 if (mpParent)
941 tSwNumberTreeChildren::const_iterator aIt =
942 mpParent->GetIterator(this);
944 if ( aIt == mpParent->mChildren.begin() )
946 // #i64311#
947 // root node is no valid predecessor
948 pResult = mpParent->GetParent() ? mpParent : nullptr;
950 else
952 --aIt;
954 if ( !bSibling )
955 pResult = (*aIt)->GetLastDescendant();
956 else
957 pResult = (*aIt);
959 if (! pResult)
960 pResult = (*aIt);
964 return pResult;
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");
974 if (
975 bValidating ||
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
983 if ( GetParent() )
985 tSwNumberTreeChildren::const_iterator aParentChildIt =
986 GetParent()->GetIterator( this );
987 ++aParentChildIt;
988 if ( aParentChildIt != GetParent()->mChildren.end() )
990 SwNumberTreeNode* pNextNode( *aParentChildIt );
991 if ( !pNextNode->IsCounted() )
993 pNextNode->InvalidateChildren();
1000 if (IsContinuous())
1002 tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
1004 if (aIt != mChildren.end())
1005 ++aIt;
1006 else
1007 aIt = mChildren.begin();
1009 while (aIt != mChildren.end())
1011 (*aIt)->InvalidateTree();
1013 ++aIt;
1016 if (mpParent)
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())
1040 --aIt;
1041 else
1042 aIt = mChildren.end();
1044 SetLastValid(aIt);
1049 void SwNumberTreeNode::InvalidateMe()
1051 if (mpParent)
1052 mpParent->Invalidate(this);
1055 void SwNumberTreeNode::ValidateMe()
1057 if (mpParent)
1058 mpParent->Validate(this);
1061 void SwNumberTreeNode::Notify(const SwDoc& rDoc)
1063 if (IsNotifiable(rDoc))
1065 if (! IsPhantom())
1066 NotifyNode();
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();
1081 else
1082 ++aIt;
1084 while (aIt != mChildren.end())
1086 (*aIt)->Notify(rDoc);
1088 ++aIt;
1090 // notification of next not counted node is also needed.
1091 if ( GetParent() )
1093 tSwNumberTreeChildren::const_iterator aParentChildIt =
1094 GetParent()->GetIterator( this );
1095 ++aParentChildIt;
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);
1118 // #i81002#
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() )
1130 --aUpperBoundIt;
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" );
1155 return;
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 )
1170 if ( nDepth == 0 )
1172 rpChild->NotifyNode();
1174 else
1176 rpChild->NotifyChildrenOnDepth( nDepth - 1 );
1181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */