LibreOffice Module sw (master)  1
SwNumberTree.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <algorithm>
21 #include <SwNumberTree.hxx>
22 #include <osl/diagnose.h>
23 #include <sal/log.hxx>
24 
25 #include <cassert>
26 
27 using std::vector;
28 using std::find;
29 
31  : mpParent( nullptr ),
32  mnNumber( 0 ),
33  mbContinueingPreviousSubTree( false ),
34  mbPhantom( false )
35 {
36  mItLastValid = mChildren.end();
37 }
38 
40 {
41  if (GetChildCount() > 0)
42  {
43  if (HasOnlyPhantoms())
44  {
45  delete *mChildren.begin();
46 
47  mChildren.clear();
48  mItLastValid = mChildren.end();
49  }
50  else
51  {
52  OSL_FAIL("lost children!");
53  }
54  }
55 
56  OSL_ENSURE( IsPhantom() || mpParent == nullptr, ": I'm not supposed to have a parent.");
57 
58  mpParent = reinterpret_cast<SwNumberTreeNode *>(0xdeadbeef);
59 
60  OSL_ENSURE(mChildren.empty(), "children left!");
61 }
62 
64 {
65  SwNumberTreeNode * pNew = nullptr;
66 
67  if (! mChildren.empty() &&
68  (*mChildren.begin())->IsPhantom())
69  {
70  OSL_FAIL("phantom already present");
71  }
72  else
73  {
74  pNew = Create();
75  pNew->mbPhantom = true;
76  pNew->mpParent = this;
77 
78  std::pair<tSwNumberTreeChildren::iterator, bool> aInsert =
79  mChildren.insert(pNew);
80 
81  if (! aInsert.second)
82  {
83  OSL_FAIL("insert of phantom failed!");
84 
85  delete pNew;
86  pNew = nullptr;
87  }
88  }
89 
90  return pNew;
91 }
92 
94 {
95  SwNumberTreeNode * pResult = mpParent;
96 
97  if (pResult)
98  while (pResult->mpParent)
99  pResult = pResult->mpParent;
100 
101  return pResult;
102 }
103 
105 {
106  tSwNumberTreeChildren::iterator aIt = mChildren.begin();
107 
108  if (!(aIt != mChildren.end() && (*aIt)->IsPhantom()))
109  return;
110 
111  (*aIt)->ClearObsoletePhantoms();
112 
113  if ((*aIt)->mChildren.empty())
114  {
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());
120 
121  delete *aIt;
122  mChildren.erase(aIt);
123  }
124 }
125 
127 {
128  tSwNumberTreeChildren::const_iterator aValidateIt =
129  GetIterator(pNode);
130 
131  if (aValidateIt == mChildren.end())
132  return;
133 
134  OSL_ENSURE((*aValidateIt)->mpParent == this, "wrong parent");
135 
136  tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
137 
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
152  {
153  aIt = mChildren.begin();
154  (*aIt)->mbContinueingPreviousSubTree = false;
155 
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() ) )
161  {
162  --nTmpNumber;
163  }
164 
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() ||
171  if ( !(*aIt)->IsRestart() &&
172  GetParent() && !bParentCounted )
173  {
174  tSwNumberTreeChildren::const_iterator aParentChildIt =
175  GetParent()->GetIterator( this );
176  while ( aParentChildIt != GetParent()->mChildren.begin() )
177  {
178  --aParentChildIt;
179  SwNumberTreeNode* pPrevNode( *aParentChildIt );
180  if ( pPrevNode->GetChildCount() > 0 )
181  {
182  (*aIt)->mbContinueingPreviousSubTree = true;
183  nTmpNumber = (*(pPrevNode->mChildren.rbegin()))->GetNumber();
184  if ( (*aIt)->IsCounted() &&
185  ( !(*aIt)->IsPhantom() ||
186  (*aIt)->HasPhantomCountedParent() ) )
187  {
188  ++nTmpNumber;
189  }
190  break;
191  }
192  else if ( pPrevNode->IsCounted() )
193  {
194  break;
195  }
196  else
197  {
198  // Previous node has no children and is not counted.
199  // Thus, next turn and check for the previous node.
200  }
201  }
202  }
203 
204  (*aIt)->mnNumber = nTmpNumber;
205  }
206 
207  while (aIt != aValidateIt)
208  {
209  ++aIt;
210  (*aIt)->mbContinueingPreviousSubTree = false;
211 
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() )
216  {
217  if ((*aIt)->IsRestart())
218  nTmpNumber = (*aIt)->GetStartValue();
219  else
220  ++nTmpNumber;
221  }
222 
223  (*aIt)->mnNumber = nTmpNumber;
224  }
225 
226  SetLastValid(aIt, true);
227 }
228 
230 {
231  tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
232 
233  do
234  {
235  if (aIt == mChildren.end())
236  {
237  aIt = mChildren.begin();
238  }
239  else
240  ++aIt;
241 
242  if (aIt != mChildren.end())
243  {
244  SwNumberTree::tSwNumTreeNumber nTmpNumber = 0;
245  SwNumberTreeNode * pPred = (*aIt)->GetPred();
246 
247  // #i64311#
248  // correct consideration of phantoms
249  // correct consideration of restart at a number tree node
250  if ( pPred )
251  {
252  if ( !(*aIt)->IsCounted() )
253  // #i65284#
254  nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() );
255  else
256  {
257  if ( (*aIt)->IsRestart() )
258  nTmpNumber = (*aIt)->GetStartValue();
259  else
260  nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() ) + 1;
261  }
262  }
263  else
264  {
265  if ( !(*aIt)->IsCounted() )
266  nTmpNumber = GetStartValue() - 1;
267  else
268  {
269  if ( (*aIt)->IsRestart() )
270  nTmpNumber = (*aIt)->GetStartValue();
271  else
272  nTmpNumber = GetStartValue();
273  }
274  }
275 
276  (*aIt)->mnNumber = nTmpNumber;
277  }
278  }
279  while (aIt != mChildren.end() && *aIt != pNode);
280 
281  // #i74748# - applied patch from garnier_romain
282  // number tree node has to be validated.
283  SetLastValid( aIt, true );
284 }
285 
287 {
288  if (! IsValid(pNode))
289  {
290  if (IsContinuous())
291  ValidateContinuous(pNode);
292  else
293  ValidateHierarchical(pNode);
294  }
295 }
296 
298  bool bValidate) const
299 {
300  if (mpParent)
301  {
302  mpParent->GetNumberVector_(rVector, bValidate);
303  rVector.push_back(GetNumber(bValidate));
304  }
305 }
306 
308 {
309  if (IsPhantom())
310  return (*mChildren.begin())->GetFirstNonPhantomChild();
311 
312  return this;
313 }
314 
319  SwNumberTreeNode& _rDestNode )
320 {
321  if ( mChildren.empty() )
322  return;
323 
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()))
328  {
329  aItUpper = mChildren.begin();
330  }
331  else
332  {
333  aItUpper = mChildren.upper_bound(&_rCompareNode);
334  }
335 
336  // move children
337  if (aItUpper != mChildren.end())
338  {
339  tSwNumberTreeChildren::iterator aIt;
340  for (aIt = aItUpper; aIt != mChildren.end(); ++aIt)
341  (*aIt)->mpParent = &_rDestNode;
342 
343  _rDestNode.mChildren.insert(aItUpper, mChildren.end());
344 
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() );
350 
351  mChildren.erase(aItUpper, mChildren.end());
352 
353  // #i60652#
354  if ( !mChildren.empty() )
355  {
356  SetLastValid( --(mChildren.end()) );
357  }
358  }
359 
360 #ifdef DBG_UTIL
361  IsSane(false);
362  _rDestNode.IsSane(true);
363 #endif
364 }
365 
367 {
368  if (! mChildren.empty())
369  {
370  tSwNumberTreeChildren::iterator aItBegin = mChildren.begin();
371  SwNumberTreeNode * pMyFirst = *mChildren.begin();
372 
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());
378 
379  if (pMyFirst->IsPhantom())
380  {
381  SwNumberTreeNode * pDestLast = nullptr;
382 
383  if (pDest->mChildren.empty())
384  pDestLast = pDest->CreatePhantom();
385  else
386  pDestLast = *pDest->mChildren.rbegin();
387 
388  pMyFirst->MoveChildren(pDestLast);
389 
390  delete pMyFirst;
391  mChildren.erase(aItBegin);
392 
393  aItBegin = mChildren.begin();
394  }
395 
396  for (auto& rpChild : mChildren)
397  rpChild->mpParent = pDest;
398 
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();
404  }
405 
406  OSL_ENSURE(mChildren.empty(), "MoveChildren failed!");
407 
408 #ifdef DBG_UTIL
409  IsSane(false);
410  pDest->IsSane(false);
411 #endif
412 }
413 
415  const int nDepth,
416  const SwDoc& rDoc)
417 {
418  /*
419  Algorithm:
420 
421  Search first child A that is greater than pChild,
422  A may be the end of children.
423  If nDepth > 0 then
424  {
425  if A is first child then
426  create new phantom child B at beginning of child list
427  else
428  B is A
429 
430  Add child to B with depth nDepth - 1.
431  }
432  else
433  {
434  Insert pNode before A.
435 
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.
439  }
440 
441 */
442 
443  if ( nDepth < 0 )
444  {
445  OSL_FAIL( "<SwNumberTreeNode::AddChild(..)> - parameter <nDepth> out of valid range. Serious defect." );
446  return;
447  }
448 
449  if ( pChild->GetParent() != nullptr || pChild->GetChildCount() > 0 )
450  {
451  OSL_FAIL("only orphans allowed.");
452  return;
453  }
454 
455  if (nDepth > 0)
456  {
457  tSwNumberTreeChildren::iterator aInsertDeepIt =
458  mChildren.upper_bound(pChild);
459 
460  OSL_ENSURE(! (aInsertDeepIt != mChildren.end() &&
461  (*aInsertDeepIt)->IsPhantom()), " unexpected phantom");
462 
463  if (aInsertDeepIt == mChildren.begin())
464  {
465  SwNumberTreeNode * pNew = CreatePhantom();
466 
467  SetLastValid(mChildren.end());
468 
469  if (pNew)
470  pNew->AddChild(pChild, nDepth - 1, rDoc);
471  }
472  else
473  {
474  --aInsertDeepIt;
475  (*aInsertDeepIt)->AddChild(pChild, nDepth - 1, rDoc);
476  }
477 
478  }
479  else
480  {
481  pChild->PreAdd();
482  std::pair<tSwNumberTreeChildren::iterator, bool> aResult =
483  mChildren.insert(pChild);
484 
485  if (aResult.second)
486  {
487  pChild->mpParent = this;
488  bool bNotification = pChild->IsNotificationEnabled(rDoc);
489  tSwNumberTreeChildren::iterator aInsertedIt = aResult.first;
490 
491  if (aInsertedIt != mChildren.begin())
492  {
493  tSwNumberTreeChildren::iterator aPredIt = aInsertedIt;
494  --aPredIt;
495 
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 )
505  {
506  // move children
507  pPrevChildNode->MoveGreaterChildren( *pChild, *pDestNode );
508 
509  // prepare next loop:
510  // - search of last child of <pPrevChildNode
511  // - If found, determine destination node
512  if ( pPrevChildNode->GetChildCount() > 0 )
513  {
514  tSwNumberTreeChildren::reverse_iterator aIt =
515  pPrevChildNode->mChildren.rbegin();
516  pPrevChildNode = *aIt;
517  // determine new destination node
518  if ( pDestNode->GetChildCount() > 0 )
519  {
520  pDestNode = *(pDestNode->mChildren.begin());
521  if ( !pDestNode->IsPhantom() )
522  {
523  pDestNode = pDestNode->mpParent->CreatePhantom();
524  }
525  }
526  else
527  {
528  pDestNode = pDestNode->CreatePhantom();
529  }
530  }
531  else
532  {
533  // ready -> break loop.
534  break;
535  }
536  }
537  // assure that unnecessary created phantoms at <pChild> are deleted.
538  pChild->ClearObsoletePhantoms();
539 
540  if ((*aPredIt)->IsValid())
541  SetLastValid(aPredIt);
542  }
543  else
544  SetLastValid(mChildren.end());
545 
547 
548  if( bNotification )
549  {
550  // invalidation of not counted parent
551  // and notification of its siblings.
552  if ( !IsCounted() )
553  {
554  InvalidateMe();
555  NotifyInvalidSiblings(rDoc);
556  }
557  NotifyInvalidChildren(rDoc);
558  }
559  }
560  }
561 
562 #ifdef DBG_UTIL
563  IsSane(false);
564 #endif
565 }
566 
568 {
569  /*
570  Algorithm:
571 
572  if pChild has predecessor A then
573  B is A
574  else
575  create phantom child B at beginning of child list
576 
577  Move children of pChild to B.
578  */
579 
580  if (pChild->IsPhantom())
581  {
582  OSL_FAIL("not applicable to phantoms!");
583 
584  return;
585  }
586 
587  tSwNumberTreeChildren::const_iterator aRemoveIt = GetIterator(pChild);
588 
589  if (aRemoveIt != mChildren.end())
590  {
591  SwNumberTreeNode * pRemove = *aRemoveIt;
592 
593  pRemove->mpParent = nullptr;
594 
595  tSwNumberTreeChildren::const_iterator aItPred = mChildren.end();
596 
597  if (aRemoveIt == mChildren.begin())
598  {
599  if (! pRemove->mChildren.empty())
600  {
601  CreatePhantom();
602 
603  aItPred = mChildren.begin();
604  }
605  }
606  else
607  {
608  aItPred = aRemoveIt;
609  --aItPred;
610  }
611 
612  if (! pRemove->mChildren.empty())
613  {
614  pRemove->MoveChildren(*aItPred);
615  (*aItPred)->InvalidateTree();
616  (*aItPred)->NotifyInvalidChildren(rDoc);
617  }
618 
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);
627 
628  mChildren.erase(aRemoveIt);
629 
630  NotifyInvalidChildren(rDoc);
631  }
632  else
633  {
634  OSL_FAIL("RemoveChild: failed!");
635  }
636 
637  pChild->PostRemove();
638 }
639 
641 {
642  if (!mpParent)
643  return;
644 
645  SwNumberTreeNode * pSavedParent = mpParent;
646 
647  pSavedParent->RemoveChild(this, rDoc);
648 
649  while (pSavedParent && pSavedParent->IsPhantom() &&
650  pSavedParent->HasOnlyPhantoms())
651  pSavedParent = pSavedParent->GetParent();
652 
653  if (pSavedParent)
654  pSavedParent->ClearObsoletePhantoms();
655 
656 #ifdef DBG_UTIL
657  IsSane(false);
658 #endif
659 }
660 
662 {
663  return mpParent && mpParent->IsValid(this);
664 }
665 
667  const
668 {
669  if (bValidate && mpParent)
670  mpParent->Validate(this);
671 
672  return mnNumber;
673 }
674 
675 
677 {
678  vector<SwNumberTree::tSwNumTreeNumber> aResult;
679 
680  GetNumberVector_(aResult);
681 
682  return aResult;
683 }
684 
685 bool SwNumberTreeNode::IsValid(const SwNumberTreeNode * pChild) const
686 {
687  bool bResult = false;
688 
689  if (mItLastValid != mChildren.end())
690  {
691  if (pChild && pChild->mpParent == this)
692  {
693  bResult = ! (*mItLastValid)->LessThan(*pChild);
694  }
695  }
696 
697  return bResult;
698 }
699 
700 
702 {
703  bool bResult = false;
704 
705  if (GetChildCount() == 1)
706  {
707  tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
708 
709  bResult = (*aIt)->IsPhantom() && (*aIt)->HasOnlyPhantoms();
710  }
711  else if (GetChildCount() == 0)
712  bResult = true;
713 
714  return bResult;
715 }
716 
718 {
719  return !IsPhantom() ||
721 }
722 
724 {
725  bool bRet( false );
726 
727  OSL_ENSURE( IsPhantom(),
728  "<SwNumberTreeNode::HasPhantomCountedParent()> - wrong usage of method - it's only for phantoms" );
729  if ( IsPhantom() && mpParent )
730  {
731  if ( mpParent == GetRoot() )
732  {
733  bRet = true;
734  }
735  else if ( !mpParent->IsPhantom() )
736  {
737  bRet = mpParent->IsCounted();
738  }
739  else
740  {
742  }
743  }
744 
745  return bRet;
746 }
747 
749 {
750  tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
751 
752  if ((*aIt)->IsPhantom())
753  ++aIt;
754 
755  return *aIt == pNode;
756 }
757 
759 {
760  bool bResult = true;
761 
762  if (GetParent())
763  {
764  if (GetParent()->IsFirst(this))
765  {
766  SwNumberTreeNode * pNode = GetParent();
767 
768  while (pNode)
769  {
770  if (!pNode->IsPhantom() && pNode->GetParent())
771  {
772  bResult = false;
773  break;
774  }
775 
776  pNode = pNode->GetParent();
777  }
778 
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() )
785  {
786  bResult = false;
787  }
788  }
789  else
790  bResult = false;
791  }
792 
793  return bResult;
794 }
795 
796 void SwNumberTreeNode::SetLevelInListTree(const int nLevel, const SwDoc& rDoc)
797 {
798  if ( nLevel < 0 )
799  {
800  OSL_FAIL( "<SwNumberTreeNode::SetLevelInListTree(..)> - parameter <nLevel> out of valid range. Serious defect." );
801  return;
802  }
803 
804  OSL_ENSURE( GetParent(),
805  "<SwNumberTreeNode::SetLevelInListTree(..)> - can only be called for number tree nodes in a list tree" );
806  if ( GetParent() )
807  {
808  if ( nLevel != GetLevelInListTree() )
809  {
810  SwNumberTreeNode* pRootTreeNode = GetRoot();
811  OSL_ENSURE( pRootTreeNode,
812  "<SwNumberTreeNode::SetLevelInListTree(..)> - no root tree node found. Serious defect." );
813 
814  RemoveMe(rDoc);
815  pRootTreeNode->AddChild(this, nLevel, rDoc);
816  }
817  }
818 }
819 
821 {
822  if (mpParent)
823  return mpParent->GetLevelInListTree() + 1;
824 
825  return -1;
826 }
827 
828 SwNumberTreeNode::tSwNumberTreeChildren::size_type
830 {
831  return mChildren.size();
832 }
833 
834 #ifdef DBG_UTIL
835 void SwNumberTreeNode::IsSane(bool bRecursive) const
836 {
837  vector<const SwNumberTreeNode*> aParents;
838 
839  return IsSane(bRecursive, aParents);
840 }
841 
842 void SwNumberTreeNode::IsSane(bool bRecursive,
843  vector<const SwNumberTreeNode *> rParents)
844  const
845 {
846  assert(find(rParents.begin(), rParents.end(), this) == rParents.end());
847 
848  assert(rParents.empty() || rParents.back() == mpParent);
849 
850  rParents.push_back(this);
851 
852  bool bFirst = true;
853  for (const auto& rpChild : mChildren)
854  {
855  if (rpChild)
856  {
857  if (rpChild->IsPhantom())
858  {
859  SAL_WARN_IF(rpChild->HasOnlyPhantoms(), "sw.core",
860  "HasOnlyPhantoms: is this an error?");
861 
862  assert(bFirst && "found phantom not at first position.");
863  }
864 
865  assert(rpChild->mpParent == this);
866 
867  if (mpParent)
868  {
869  assert(rpChild->IsPhantom() || !rpChild->LessThan(*this));
870  }
871  }
872  else
873  {
874  assert(!"found child that is NULL");
875  }
876 
877  if (bRecursive)
878  {
879  rpChild->IsSane(bRecursive, rParents);
880  }
881 
882  bFirst = false;
883  }
884 
885  rParents.pop_back();
886 }
887 #endif // DBG_UTIL
888 
889 SwNumberTreeNode::tSwNumberTreeChildren::const_iterator
891 {
892  tSwNumberTreeChildren::const_iterator aItResult =
893  mChildren.find(const_cast<SwNumberTreeNode *>(pChild));
894 
895  OSL_ENSURE( aItResult != mChildren.end(),
896  "something went wrong getting the iterator for a child");
897 
898  return aItResult;
899 }
900 
902  const SwNumberTreeNode * pB)
903 {
904  bool bResult = false;
905 
906  if (pA == nullptr && pB != nullptr)
907  bResult = true;
908  else if (pA != nullptr && pB != nullptr)
909  bResult = pA->LessThan(*pB);
910 
911  return bResult;
912 }
913 
915 {
916  SwNumberTreeNode * pResult = nullptr;
917  tSwNumberTreeChildren::const_reverse_iterator aIt = mChildren.rbegin();
918 
919  if (aIt != mChildren.rend())
920  {
921  pResult = (*aIt)->GetLastDescendant();
922 
923  if (! pResult)
924  pResult = *aIt;
925  }
926 
927  return pResult;
928 }
929 
930 bool SwNumberTreeNode::LessThan(const SwNumberTreeNode & rTreeNode) const
931 {
932  return this < &rTreeNode;
933 }
934 
936 {
937  SwNumberTreeNode * pResult = nullptr;
938 
939  if (mpParent)
940  {
941  tSwNumberTreeChildren::const_iterator aIt =
942  mpParent->GetIterator(this);
943 
944  if ( aIt == mpParent->mChildren.begin() )
945  {
946  // #i64311#
947  // root node is no valid predecessor
948  pResult = mpParent->GetParent() ? mpParent : nullptr;
949  }
950  else
951  {
952  --aIt;
953 
954  if ( !bSibling )
955  pResult = (*aIt)->GetLastDescendant();
956  else
957  pResult = (*aIt);
958 
959  if (! pResult)
960  pResult = (*aIt);
961  }
962  }
963 
964  return pResult;
965 }
966 
968  ( const SwNumberTreeNode::tSwNumberTreeChildren::const_iterator& aItValid,
969  bool bValidating ) const
970 {
971  OSL_ENSURE( (aItValid == mChildren.end() || GetIterator(*aItValid) != mChildren.end()),
972  "last-valid iterator");
973 
974  if (
975  bValidating ||
976  aItValid == mChildren.end() ||
977  (mItLastValid != mChildren.end() &&
978  (*aItValid)->LessThan(**mItLastValid))
979  )
980  {
981  mItLastValid = aItValid;
982  // invalidation of children of next not counted is needed
983  if ( GetParent() )
984  {
985  tSwNumberTreeChildren::const_iterator aParentChildIt =
986  GetParent()->GetIterator( this );
987  ++aParentChildIt;
988  if ( aParentChildIt != GetParent()->mChildren.end() )
989  {
990  SwNumberTreeNode* pNextNode( *aParentChildIt );
991  if ( !pNextNode->IsCounted() )
992  {
993  pNextNode->InvalidateChildren();
994  }
995  }
996  }
997  }
998 
999  {
1000  if (IsContinuous())
1001  {
1002  tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
1003 
1004  if (aIt != mChildren.end())
1005  ++aIt;
1006  else
1007  aIt = mChildren.begin();
1008 
1009  while (aIt != mChildren.end())
1010  {
1011  (*aIt)->InvalidateTree();
1012 
1013  ++aIt;
1014  }
1015 
1016  if (mpParent)
1017  {
1018  mpParent->SetLastValid(mpParent->GetIterator(this), bValidating);
1019  }
1020  }
1021  }
1022 }
1023 
1025 {
1026  // do not call SetInvalid, would cause loop !!!
1027  mItLastValid = mChildren.end();
1028 
1029  for (const auto& rpChild : mChildren)
1030  rpChild->InvalidateTree();
1031 }
1032 
1034 {
1035  if (pChild->IsValid())
1036  {
1037  tSwNumberTreeChildren::const_iterator aIt = GetIterator(pChild);
1038 
1039  if (aIt != mChildren.begin())
1040  --aIt;
1041  else
1042  aIt = mChildren.end();
1043 
1044  SetLastValid(aIt);
1045 
1046  }
1047 }
1048 
1050 {
1051  if (mpParent)
1052  mpParent->Invalidate(this);
1053 }
1054 
1056 {
1057  if (mpParent)
1058  mpParent->Validate(this);
1059 }
1060 
1062 {
1063  if (IsNotifiable(rDoc))
1064  {
1065  if (! IsPhantom())
1066  NotifyNode();
1067 
1068  for (auto& rpChild : mChildren)
1069  rpChild->Notify(rDoc);
1070  }
1071 }
1072 
1074 {
1075  if (IsNotifiable(rDoc))
1076  {
1077  tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
1078 
1079  if (aIt == mChildren.end())
1080  aIt = mChildren.begin();
1081  else
1082  ++aIt;
1083 
1084  while (aIt != mChildren.end())
1085  {
1086  (*aIt)->Notify(rDoc);
1087 
1088  ++aIt;
1089  }
1090  // notification of next not counted node is also needed.
1091  if ( GetParent() )
1092  {
1093  tSwNumberTreeChildren::const_iterator aParentChildIt =
1094  GetParent()->GetIterator( this );
1095  ++aParentChildIt;
1096  if ( aParentChildIt != GetParent()->mChildren.end() )
1097  {
1098  SwNumberTreeNode* pNextNode( *aParentChildIt );
1099  if ( !pNextNode->IsCounted() )
1100  {
1101  pNextNode->NotifyInvalidChildren(rDoc);
1102  }
1103  }
1104  }
1105 
1106  }
1107 
1108  if (IsContinuous() && mpParent)
1110 }
1111 
1113 {
1114  if (mpParent != nullptr)
1116 }
1117 
1118 // #i81002#
1120  const SwNumberTreeNode& rNode ) const
1121 {
1122  const SwNumberTreeNode* pPrecedingNode( nullptr );
1123 
1124  if ( GetChildCount() > 0 )
1125  {
1126  tSwNumberTreeChildren::const_iterator aUpperBoundIt =
1127  mChildren.upper_bound( const_cast<SwNumberTreeNode*>(&rNode) );
1128  if ( aUpperBoundIt != mChildren.begin() )
1129  {
1130  --aUpperBoundIt;
1131  pPrecedingNode = (*aUpperBoundIt)->GetPrecedingNodeOf( rNode );
1132  }
1133  }
1134 
1135  if ( pPrecedingNode == nullptr && GetRoot() )
1136  {
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 )) )
1142  {
1143  pPrecedingNode = this;
1144  }
1145  }
1146 
1147  return pPrecedingNode;
1148 }
1149 
1150 void SwNumberTreeNode::NotifyNodesOnListLevel( const int nListLevel )
1151 {
1152  if ( nListLevel < 0 )
1153  {
1154  OSL_FAIL( "<SwNumberTreeNode::NotifyNodesOnListLevel(..)> - invalid list level provided" );
1155  return;
1156  }
1157 
1158  SwNumberTreeNode* pRootNode = GetParent() ? GetRoot() : this;
1159 
1160  pRootNode->NotifyChildrenOnDepth( nListLevel );
1161 }
1162 
1164 {
1165  OSL_ENSURE( nDepth >= 0,
1166  "<SwNumberTreeNode::NotifyChildrenOnDepth(..)> - misusage" );
1167 
1168  for ( const auto& rpChild : mChildren )
1169  {
1170  if ( nDepth == 0 )
1171  {
1172  rpChild->NotifyNode();
1173  }
1174  else
1175  {
1176  rpChild->NotifyChildrenOnDepth( nDepth - 1 );
1177  }
1178  }
1179 }
1180 
1181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool HasPhantomCountedParent() const
virtual bool IsNotifiable(const SwDoc &rDoc) const =0
Return if this node is notifiable.
virtual bool IsNotificationEnabled(const SwDoc &rDoc) const =0
Return if the notification is not disabled on global conditions.
virtual void NotifyNode()=0
Notifies the node.
bool IsValid() const
Returns if this node is valid.
SwNumberTreeNode * GetLastDescendant() const
Returns the last descendant of a node, if it has children.
bool IsFirst() const
Return if this node if the first non-phantom node in the tree.
void RemoveChild(SwNumberTreeNode *pChild, const SwDoc &rDoc)
Remove a child.
virtual bool LessThan(const SwNumberTreeNode &rTreeNode) const
Returns if this node is less than another node.
A tree of numbered nodes.
const SwNumberTreeNode * GetPrecedingNodeOf(const SwNumberTreeNode &rNode) const
determines the node, which is preceding the node
virtual SwNumberTree::tSwNumTreeNumber GetStartValue() const =0
Return start value.
SwNumberTreeNode * GetPred(bool bSibling=false) const
Returns the greatest descendant of the root that is smaller than this node, aka the predecessor of th...
SwNumberTreeNode * GetParent() const
Returns the parent of this node.
void RemoveMe(const SwDoc &rDoc)
Remove this child from the tree.
void ClearObsoletePhantoms()
Removes recursively phantoms that have no children.
virtual bool HasCountedChildren() const =0
Definition: doc.hxx:188
bool SwNumberTreeNodeLessThan(const SwNumberTreeNode *pA, const SwNumberTreeNode *pB)
void Validate(const SwNumberTreeNode *pNode) const
Validates a child.
SwNumberTree::tNumberVector GetNumberVector() const
Returns level numbers of this node.
void GetNumberVector_(SwNumberTree::tNumberVector &rVector, bool bValidate=true) const
Calls GetNumberVector_ on parent and adds number of this node at the end.
int GetLevelInListTree() const
Return level of this node.
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
SwNumberTreeNode * GetRoot() const
Returns the root node of the tree this node is part of.
void SetLevelInListTree(const int nLevel, const SwDoc &rDoc)
set level of this node
void NotifyInvalidSiblings(const SwDoc &rDoc)
Notifies all invalid siblings of this node.
tSwNumberTreeChildren::const_iterator GetIterator(const SwNumberTreeNode *pChild) const
tSwNumberTreeChildren mChildren
the children
void InvalidateMe()
Notifies the node.
void NotifyInvalidChildren(const SwDoc &rDoc)
Notifies all invalid children of this node.
void MoveChildren(SwNumberTreeNode *pDest)
Moves all children to a given destination node.
void AddChild(SwNumberTreeNode *pChild, const int nDepth, const SwDoc &rDoc)
Add a child.
bool mbPhantom
true this node is a phantom false this node is NOT a phantom
bool IsPhantom() const
Return if this node is a phantom.
tools::Long tSwNumTreeNumber
void SetLastValid(const tSwNumberTreeChildren::const_iterator &aItLastValid, bool bValidating=false) const
Set the last valid child of this node.
void ValidateHierarchical(const SwNumberTreeNode *pNode) const
Validates a child using hierarchical numbering.
virtual void PreAdd()=0
void Invalidate(SwNumberTreeNode const *pChild)
Invalidates a child.
SwNumberTreeNode * CreatePhantom()
Creates a phantom.
virtual bool IsContinuous() const =0
Return if this node is counted continuous.
SwNumberTreeNode * mpParent
he parent node
bool IsValid(const SwNumberTreeNode *pChild) const
Returns if a child A this node is valid.
tSwNumberTreeChildren::const_iterator mItLastValid
Iterator to the last valid element.
SwNumberTree::tSwNumTreeNumber GetNumber(bool bValidate=true) const
Returns number of this node.
virtual ~SwNumberTreeNode()
void ValidateMe()
Validates this node.
SwNumberTreeNode * GetFirstNonPhantomChild()
HB, OD : return node, if it isn't a phantom, otherwise return first non-phantom descendant.
void IsSane(bool bRecursive) const
Sanity check.
void Notify(const SwDoc &rDoc)
Notifies this node (NotifyNode) and all descendants.
std::vector< tSwNumTreeNumber > tNumberVector
RegionData_Impl * mpParent
virtual bool IsCountPhantoms() const =0
Return if phantoms are counted.
void ValidateContinuous(const SwNumberTreeNode *pNode) const
Validates a child using continuous numbering.
void InvalidateChildren()
Invalidation of all children.
void MoveGreaterChildren(SwNumberTreeNode &_rCompareNode, SwNumberTreeNode &_rDestNode)
Moves all children of this node that are greater than a given node to the destination node...
#define SAL_WARN_IF(condition, area, stream)
bool HasOnlyPhantoms() const
Return if all descendants of this node are phantoms.
tSwNumberTreeChildren::size_type GetChildCount() const
Returns how many children this node has got.
virtual SwNumberTreeNode * Create() const =0
Creates a new node of the same class.
void NotifyChildrenOnDepth(const int nDepth)
notification of children nodes on certain depth
virtual void PostRemove()=0
SwNumberTree::tSwNumTreeNumber mnNumber
the number of the node
void InvalidateTree() const
Invalidate this node and all its descendants.
virtual bool IsCounted() const
Return if this node is counted.
void NotifyNodesOnListLevel(const int nListLevel)
notification of all nodes in the list tree on certain list level