LibreOffice Module vcl (master)  1
treelist.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 <vcl/treelist.hxx>
21 #include <vcl/treelistentry.hxx>
22 #include <vcl/viewdataentry.hxx>
23 #include <tools/debug.hxx>
24 #include <osl/diagnose.h>
25 
26 #include <memory>
27 #include <map>
28 
29 
30 typedef std::map<SvTreeListEntry*, std::unique_ptr<SvViewDataEntry>> SvDataTable;
31 
33 {
35 
36  SvDataTable m_DataTable; // Mapping SvTreeListEntry -> ViewData
37 
41 
42  explicit Impl(SvListView & rThis)
43  : m_rThis(rThis)
44  , m_nVisibleCount(0)
45  , m_nSelectionCount(0)
46  , m_bVisPositionsValid(false)
47  {}
48 
49  void InitTable();
50  void RemoveViewData( SvTreeListEntry* pParent );
51 
52  void ActionMoving(SvTreeListEntry* pEntry);
53  void ActionMoved();
54  void ActionInserted(SvTreeListEntry* pEntry);
55  void ActionInsertedTree(SvTreeListEntry* pEntry);
56  void ActionRemoving(SvTreeListEntry* pEntry);
57  void ActionClear();
58 };
59 
60 
62  mrOwnerListView(listView),
63  mbEnableInvalidate(true)
64 {
65  nEntryCount = 0;
66  bAbsPositionsValid = false;
67  pRootItem.reset(new SvTreeListEntry);
69 }
70 
72 {
73 }
74 
76  SvListAction nActionId,
77  SvTreeListEntry* pEntry1,
78  SvTreeListEntry* pEntry2,
79  sal_uLong nPos
80 )
81 {
82  mrOwnerListView.ModelNotification(nActionId, pEntry1, pEntry2, nPos);
83 }
84 
85 // an entry is visible if all parents are expanded
86 bool SvTreeList::IsEntryVisible( const SvListView* pView, SvTreeListEntry* pEntry ) const
87 {
88  DBG_ASSERT(pView&&pEntry,"IsVisible:Invalid Params");
89  bool bRetVal = false;
90  do
91  {
92  if ( pEntry == pRootItem.get() )
93  {
94  bRetVal = true;
95  break;
96  }
97  pEntry = pEntry->pParent;
98  } while( pView->IsExpanded( pEntry ) );
99  return bRetVal;
100 }
101 
102 sal_uInt16 SvTreeList::GetDepth( const SvTreeListEntry* pEntry ) const
103 {
104  DBG_ASSERT(pEntry && pEntry!=pRootItem.get(),"GetDepth:Bad Entry");
105  sal_uInt16 nDepth = 0;
106  while( pEntry->pParent != pRootItem.get() )
107  {
108  nDepth++;
109  pEntry = pEntry->pParent;
110  }
111  return nDepth;
112 }
113 
114 bool SvTreeList::IsAtRootDepth( const SvTreeListEntry* pEntry ) const
115 {
116  return pEntry->pParent == pRootItem.get();
117 }
118 
120 {
122  pRootItem->ClearChildren();
123  nEntryCount = 0;
125 }
126 
127 bool SvTreeList::IsChild(const SvTreeListEntry* pParent, const SvTreeListEntry* pChild) const
128 {
129  if ( !pParent )
130  pParent = pRootItem.get();
131 
132  if (pParent->m_Children.empty())
133  return false;
134 
135  for (auto const& it : pParent->m_Children)
136  {
137  const SvTreeListEntry* pThis = it.get();
138  if (pThis == pChild)
139  return true;
140  else
141  {
142  bool bIsChild = IsChild(pThis, pChild);
143  if (bIsChild)
144  return true;
145  }
146  }
147  return false;
148 }
149 
150 namespace {
151 
152 class FindByPointer
153 {
154  const SvTreeListEntry* mpEntry;
155 public:
156  explicit FindByPointer(const SvTreeListEntry* p) : mpEntry(p) {}
157 
158  bool operator() (std::unique_ptr<SvTreeListEntry> const& rpEntry) const
159  {
160  return mpEntry == rpEntry.get();
161  }
162 };
163 
164 sal_uLong findEntryPosition(const SvTreeListEntries& rDst, const SvTreeListEntry* pEntry)
165 {
166  SvTreeListEntries::const_iterator itPos = std::find_if(rDst.begin(), rDst.end(), FindByPointer(pEntry));
167  if (itPos == rDst.end())
168  return static_cast<sal_uLong>(~0);
169 
170  return static_cast<sal_uLong>(std::distance(rDst.begin(), itPos));
171 }
172 
173 }
174 
176 {
177  // pDest may be 0!
178  DBG_ASSERT(pSrcEntry,"Entry?");
179  if ( !pTargetParent )
180  pTargetParent = pRootItem.get();
181  DBG_ASSERT(pSrcEntry!=pTargetParent,"Move:Source=Target");
182 
183  Broadcast( SvListAction::MOVING, pSrcEntry, pTargetParent, nListPos );
184 
185  if ( pSrcEntry == pTargetParent )
186  // You can't move an entry onto itself as the parent. Just return its
187  // position and bail out.
188  return pSrcEntry->GetChildListPos();
189 
190  bAbsPositionsValid = false;
191 
192  SvTreeListEntries& rDst = pTargetParent->m_Children;
193  SvTreeListEntries& rSrc = pSrcEntry->pParent->m_Children;
194 
195  bool bSameParent = pTargetParent == pSrcEntry->pParent;
196 
197  // Find the position of the entry being moved in the source container.
198  SvTreeListEntries::iterator itSrcPos = rSrc.begin(), itEnd = rSrc.end();
199  for (; itSrcPos != itEnd; ++itSrcPos)
200  {
201  const SvTreeListEntry* p = (*itSrcPos).get();
202  if (p == pSrcEntry)
203  // Found
204  break;
205  }
206 
207  if (itSrcPos == itEnd)
208  {
209  OSL_FAIL("Source entry not found! This should never happen.");
210  return pSrcEntry->GetChildListPos();
211  }
212 
213  if (bSameParent)
214  {
215  // Moving within the same parent.
216 
217  size_t nSrcPos = std::distance(rSrc.begin(), itSrcPos);
218  if (nSrcPos == nListPos)
219  // Nothing to move here.
220  return pSrcEntry->GetChildListPos();
221 
222  if (nSrcPos < nListPos)
223  // Destination position shifts left after removing the original.
224  --nListPos;
225 
226  // Release the original.
227  std::unique_ptr<SvTreeListEntry> pOriginal(std::move(*itSrcPos));
228  assert(pOriginal.get());
229  rSrc.erase(itSrcPos);
230 
231  // Determine the insertion position.
232  SvTreeListEntries::iterator itDstPos = rSrc.end();
233  if (nListPos < rSrc.size())
234  {
235  itDstPos = rSrc.begin();
236  std::advance(itDstPos, nListPos);
237  }
238  rSrc.insert(itDstPos, std::move(pOriginal));
239  }
240  else
241  {
242  // Moving from one parent to another.
243  SvTreeListEntries::iterator itDstPos = rDst.end();
244  if (nListPos < rDst.size())
245  {
246  itDstPos = rDst.begin();
247  std::advance(itDstPos, nListPos);
248  }
249  std::unique_ptr<SvTreeListEntry> pOriginal(std::move(*itSrcPos));
250  assert(pOriginal.get());
251  rSrc.erase(itSrcPos);
252  rDst.insert(itDstPos, std::move(pOriginal));
253  }
254 
255  // move parent (do this only now, because we need the parent for
256  // deleting the old child list!)
257  pSrcEntry->pParent = pTargetParent;
258 
259  // correct list position in target list
260  SetListPositions(rDst);
261  if (!bSameParent)
262  SetListPositions(rSrc);
263 
264  sal_uLong nRetVal = findEntryPosition(rDst, pSrcEntry);
265  OSL_ENSURE(nRetVal == pSrcEntry->GetChildListPos(), "ListPos not valid");
266  Broadcast( SvListAction::MOVED,pSrcEntry,pTargetParent,nRetVal);
267  return nRetVal;
268 }
269 
271 {
272  // pDest may be 0!
273  DBG_ASSERT(pSrcEntry,"Entry?");
274  if ( !pTargetParent )
275  pTargetParent = pRootItem.get();
276 
277  bAbsPositionsValid = false;
278 
279  sal_uLong nCloneCount = 0;
280  SvTreeListEntry* pClonedEntry = Clone( pSrcEntry, nCloneCount );
281  nEntryCount += nCloneCount;
282 
283  SvTreeListEntries& rDst = pTargetParent->m_Children;
284 
285  pClonedEntry->pParent = pTargetParent; // move parent
286 
287  if (nListPos < rDst.size())
288  {
289  SvTreeListEntries::iterator itPos = rDst.begin(); // insertion position.
290  std::advance(itPos, nListPos);
291  rDst.insert(itPos, std::unique_ptr<SvTreeListEntry>(pClonedEntry));
292  }
293  else
294  rDst.push_back(std::unique_ptr<SvTreeListEntry>(pClonedEntry));
295 
296  SetListPositions(rDst); // correct list position in target list
297 
298  Broadcast( SvListAction::INSERTED_TREE, pClonedEntry );
299  sal_uLong nRetVal = findEntryPosition(rDst, pClonedEntry);
300  return nRetVal;
301 }
302 
303 void SvTreeList::Move( SvTreeListEntry* pSrcEntry, SvTreeListEntry* pDstEntry )
304 {
305  SvTreeListEntry* pParent;
306  sal_uLong nPos;
307 
308  if ( !pDstEntry )
309  {
310  pParent = pRootItem.get();
311  nPos = 0;
312  }
313  else
314  {
315  pParent = pDstEntry->pParent;
316  nPos = pDstEntry->GetChildListPos();
317  nPos++; // (On screen:) insert _below_ pDstEntry
318  }
319  Move( pSrcEntry, pParent, nPos );
320 }
321 
323  SvTreeListEntry* pTargetParent,sal_uLong nListPos)
324 {
325  DBG_ASSERT(pSrcEntry,"InsertTree:Entry?");
326  if ( !pSrcEntry )
327  return;
328 
329  if ( !pTargetParent )
330  pTargetParent = pRootItem.get();
331 
332  // take sorting into account
333  GetInsertionPos( pSrcEntry, pTargetParent, nListPos );
334 
335  bAbsPositionsValid = false;
336 
337  pSrcEntry->pParent = pTargetParent; // move parent
338  SvTreeListEntries& rDst = pTargetParent->m_Children;
339 
340  if (nListPos < rDst.size())
341  {
342  SvTreeListEntries::iterator itPos = rDst.begin();
343  std::advance(itPos, nListPos);
344  rDst.insert(itPos, std::unique_ptr<SvTreeListEntry>(pSrcEntry));
345  }
346  else
347  rDst.push_back(std::unique_ptr<SvTreeListEntry>(pSrcEntry));
348 
349  SetListPositions(rDst); // correct list position in target list
350  nEntryCount += GetChildCount( pSrcEntry );
351  nEntryCount++; // the parent is new, too
352 
354 }
355 
357 {
358  if( aCloneLink.IsSet() )
359  return aCloneLink.Call( pSource );
360  SvTreeListEntry* pEntry = new SvTreeListEntry;
361  pEntry->Clone(pSource);
362  return pEntry;
363 }
364 
366 {
367  SvTreeListEntry* pClonedEntry = CloneEntry( pEntry );
368  nCloneCount = 1;
369  if (!pEntry->m_Children.empty())
370  // Clone the child entries.
371  CloneChildren(pClonedEntry->m_Children, nCloneCount, pEntry->m_Children, *pClonedEntry);
372 
373  return pClonedEntry;
374 }
375 
377  SvTreeListEntries& rDst, sal_uLong& rCloneCount, SvTreeListEntries& rSrc, SvTreeListEntry& rNewParent) const
378 {
379  SvTreeListEntries aClone;
380  for (auto const& elem : rSrc)
381  {
382  SvTreeListEntry& rEntry = *elem;
383  std::unique_ptr<SvTreeListEntry> pNewEntry(CloneEntry(&rEntry));
384  ++rCloneCount;
385  pNewEntry->pParent = &rNewParent;
386  if (!rEntry.m_Children.empty())
387  // Clone entries recursively.
388  CloneChildren(pNewEntry->m_Children, rCloneCount, rEntry.m_Children, *pNewEntry);
389 
390  aClone.push_back(std::move(pNewEntry));
391  }
392 
393  rDst.swap(aClone);
394 }
395 
397 {
398  if ( !pParent )
399  return GetEntryCount();
400 
401  if (pParent->m_Children.empty())
402  return 0;
403 
404  sal_uLong nCount = 0;
405  sal_uInt16 nRefDepth = GetDepth( pParent );
406  sal_uInt16 nActDepth = nRefDepth;
407  do
408  {
409  pParent = Next(const_cast<SvTreeListEntry*>(pParent), &nActDepth);
410  nCount++;
411  } while( pParent && nRefDepth < nActDepth );
412  nCount--;
413  return nCount;
414 }
415 
417 {
418  DBG_ASSERT(pView,"GetVisChildCount:No View");
419  if ( !pParent )
420  pParent = pRootItem.get();
421 
422  if (!pParent || !pView->IsExpanded(pParent) || pParent->m_Children.empty())
423  return 0;
424 
425  sal_uLong nCount = 0;
426  sal_uInt16 nRefDepth = GetDepth( pParent );
427  sal_uInt16 nActDepth = nRefDepth;
428  do
429  {
430  pParent = NextVisible( pView, pParent, &nActDepth );
431  nCount++;
432  } while( pParent && nRefDepth < nActDepth );
433  nCount--;
434  return nCount;
435 }
436 
438 {
439  DBG_ASSERT(pView,"GetChildSelCount:No View");
440  if ( !pParent )
441  pParent = pRootItem.get();
442 
443  if (!pParent || pParent->m_Children.empty())
444  return 0;
445 
446  sal_uLong nCount = 0;
447  sal_uInt16 nRefDepth = GetDepth( pParent );
448  sal_uInt16 nActDepth = nRefDepth;
449  do
450  {
451  pParent = Next( pParent, &nActDepth );
452  if( pParent && pView->IsSelected( pParent ) && nRefDepth < nActDepth)
453  nCount++;
454  } while( pParent && nRefDepth < nActDepth );
455 // nCount--;
456  return nCount;
457 }
458 
460 {
461  if ( nEntryCount )
462  return pRootItem->m_Children[0].get();
463  else
464  return nullptr;
465 }
466 
467 SvTreeListEntry* SvTreeList::Next( SvTreeListEntry* pActEntry, sal_uInt16* pDepth ) const
468 {
469  DBG_ASSERT( pActEntry && pActEntry->pParent, "SvTreeList::Next: invalid entry/parent!" );
470  if ( !pActEntry || !pActEntry->pParent )
471  return nullptr;
472 
473  sal_uInt16 nDepth = 0;
474  bool bWithDepth = false;
475  if ( pDepth )
476  {
477  nDepth = *pDepth;
478  bWithDepth = true;
479  }
480 
481  // Get the list where the current entry belongs to (from its parent).
482  SvTreeListEntries* pActualList = &pActEntry->pParent->m_Children;
483  sal_uLong nActualPos = pActEntry->GetChildListPos();
484 
485  if (!pActEntry->m_Children.empty())
486  {
487  // The current entry has children. Get its first child entry.
488  nDepth++;
489  pActEntry = pActEntry->m_Children[0].get();
490  if ( bWithDepth )
491  *pDepth = nDepth;
492  return pActEntry;
493  }
494 
495  if (pActualList->size() > (nActualPos+1))
496  {
497  // Get the next sibling of the current entry.
498  pActEntry = (*pActualList)[nActualPos+1].get();
499  if ( bWithDepth )
500  *pDepth = nDepth;
501  return pActEntry;
502  }
503 
504  // Move up level(s) until we find the level where the next sibling exists.
505  SvTreeListEntry* pParent = pActEntry->pParent;
506  nDepth--;
507  while( pParent != pRootItem.get() && pParent != nullptr )
508  {
509  DBG_ASSERT(pParent!=nullptr,"TreeData corrupt!");
510  pActualList = &pParent->pParent->m_Children;
511  nActualPos = pParent->GetChildListPos();
512  if (pActualList->size() > (nActualPos+1))
513  {
514  pActEntry = (*pActualList)[nActualPos+1].get();
515  if ( bWithDepth )
516  *pDepth = nDepth;
517  return pActEntry;
518  }
519  pParent = pParent->pParent;
520  nDepth--;
521  }
522  return nullptr;
523 }
524 
526 {
527  DBG_ASSERT(pActEntry!=nullptr,"Entry?");
528 
529  SvTreeListEntries* pActualList = &pActEntry->pParent->m_Children;
530  sal_uLong nActualPos = pActEntry->GetChildListPos();
531 
532  if ( nActualPos > 0 )
533  {
534  pActEntry = (*pActualList)[nActualPos-1].get();
535  while (!pActEntry->m_Children.empty())
536  {
537  pActualList = &pActEntry->m_Children;
538  pActEntry = pActualList->back().get();
539  }
540  return pActEntry;
541  }
542  if ( pActEntry->pParent == pRootItem.get() )
543  return nullptr;
544 
545  pActEntry = pActEntry->pParent;
546 
547  if ( pActEntry )
548  {
549  return pActEntry;
550  }
551  return nullptr;
552 }
553 
555 {
556  SvTreeListEntries* pActList = &pRootItem->m_Children;
557  SvTreeListEntry* pEntry = nullptr;
558  while (!pActList->empty())
559  {
560  pEntry = pActList->back().get();
561  pActList = &pEntry->m_Children;
562  }
563  return pEntry;
564 }
565 
566 sal_uLong SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry const * pEntry ) const
567 {
568  DBG_ASSERT(pView&&pEntry,"View/Entry?");
569 
570  if (!pView->m_pImpl->m_bVisPositionsValid)
571  {
572  // to make GetVisibleCount refresh the positions
573  const_cast<SvListView*>(pView)->m_pImpl->m_nVisibleCount = 0;
574  GetVisibleCount( const_cast<SvListView*>(pView) );
575  }
576  const SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
577  return pViewData->nVisPos;
578 }
579 
581 {
582  assert(pView && "GetVisCount:No View");
583  if( !pView->HasViewData() )
584  return 0;
585  if (pView->m_pImpl->m_nVisibleCount)
586  return pView->m_pImpl->m_nVisibleCount;
587 
588  sal_uLong nPos = 0;
589  SvTreeListEntry* pEntry = First(); // first entry is always visible
590  while ( pEntry )
591  {
592  SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
593  pViewData->nVisPos = nPos;
594  nPos++;
595  pEntry = NextVisible( pView, pEntry );
596  }
597 #ifdef DBG_UTIL
598  if( nPos > 10000000 )
599  {
600  OSL_FAIL("nVisibleCount bad");
601  }
602 #endif
603  pView->m_pImpl->m_nVisibleCount = nPos;
604  pView->m_pImpl->m_bVisPositionsValid = true;
605  return nPos;
606 }
607 
608 
609 // For performance reasons, this function assumes that the passed entry is
610 // already visible.
611 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pActEntry,sal_uInt16* pActDepth) const
612 {
613  DBG_ASSERT(pView,"NextVisible:No View");
614  if ( !pActEntry )
615  return nullptr;
616 
617  sal_uInt16 nDepth = 0;
618  bool bWithDepth = false;
619  if ( pActDepth )
620  {
621  nDepth = *pActDepth;
622  bWithDepth = true;
623  }
624 
625  SvTreeListEntries* pActualList = &pActEntry->pParent->m_Children;
626  sal_uLong nActualPos = pActEntry->GetChildListPos();
627 
628  if ( pView->IsExpanded(pActEntry) )
629  {
630  OSL_ENSURE(!pActEntry->m_Children.empty(), "Pass entry is supposed to have child entries.");
631 
632  nDepth++;
633  pActEntry = pActEntry->m_Children[0].get();
634  if ( bWithDepth )
635  *pActDepth = nDepth;
636  return pActEntry;
637  }
638 
639  nActualPos++;
640  if ( pActualList->size() > nActualPos )
641  {
642  pActEntry = (*pActualList)[nActualPos].get();
643  if ( bWithDepth )
644  *pActDepth = nDepth;
645  return pActEntry;
646  }
647 
648  SvTreeListEntry* pParent = pActEntry->pParent;
649  nDepth--;
650  while( pParent != pRootItem.get() )
651  {
652  pActualList = &pParent->pParent->m_Children;
653  nActualPos = pParent->GetChildListPos();
654  nActualPos++;
655  if ( pActualList->size() > nActualPos )
656  {
657  pActEntry = (*pActualList)[nActualPos].get();
658  if ( bWithDepth )
659  *pActDepth = nDepth;
660  return pActEntry;
661  }
662  pParent = pParent->pParent;
663  nDepth--;
664  }
665  return nullptr;
666 }
667 
668 
669 // For performance reasons, this function assumes that the passed entry is
670 // already visible.
671 
673 {
674  DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
675 
676  sal_uInt16 nDepth = 0;
677 
678  SvTreeListEntries* pActualList = &pActEntry->pParent->m_Children;
679  sal_uLong nActualPos = pActEntry->GetChildListPos();
680 
681  if ( nActualPos > 0 )
682  {
683  pActEntry = (*pActualList)[nActualPos-1].get();
684  while( pView->IsExpanded(pActEntry) )
685  {
686  pActualList = &pActEntry->m_Children;
687  nDepth++;
688  pActEntry = pActualList->back().get();
689  }
690  return pActEntry;
691  }
692 
693  if ( pActEntry->pParent == pRootItem.get() )
694  return nullptr;
695 
696  pActEntry = pActEntry->pParent;
697  if ( pActEntry )
698  {
699  nDepth--;
700  return pActEntry;
701  }
702  return nullptr;
703 }
704 
706 {
707  DBG_ASSERT(pView,"LastVis:No View");
708  SvTreeListEntry* pEntry = Last();
709  while( pEntry && !IsEntryVisible( pView, pEntry ) )
710  pEntry = PrevVisible( pView, pEntry );
711  return pEntry;
712 }
713 
714 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pEntry,sal_uInt16& nDelta) const
715 {
716  DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
717 
718  sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
719  // nDelta entries existent?
720  // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
721  // nNewDelta = 10-nVisPos-1 == 4
722  if (nVisPos+nDelta >= pView->m_pImpl->m_nVisibleCount)
723  {
724  nDelta = static_cast<sal_uInt16>(pView->m_pImpl->m_nVisibleCount-nVisPos);
725  nDelta--;
726  }
727  sal_uInt16 nDeltaTmp = nDelta;
728  while( nDeltaTmp )
729  {
730  pEntry = NextVisible( pView, pEntry );
731  nDeltaTmp--;
732  DBG_ASSERT(pEntry,"Entry?");
733  }
734  return pEntry;
735 }
736 
737 SvTreeListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvTreeListEntry* pEntry, sal_uInt16& nDelta ) const
738 {
739  DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
740 
741  sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
742  // nDelta entries existent?
743  // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
744  // nNewDelta = nNewVisPos
745  if ( nDelta > nVisPos )
746  nDelta = static_cast<sal_uInt16>(nVisPos);
747  sal_uInt16 nDeltaTmp = nDelta;
748  while( nDeltaTmp )
749  {
750  pEntry = PrevVisible( pView, pEntry );
751  nDeltaTmp--;
752  DBG_ASSERT(pEntry,"Entry?");
753  }
754  return pEntry;
755 }
756 
758 {
759  DBG_ASSERT(pView,"FirstSel:No View");
760  if( !pView )
761  return nullptr;
762  SvTreeListEntry* pActSelEntry = First();
763  while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
764  pActSelEntry = NextVisible( pView, pActSelEntry );
765  return pActSelEntry;
766 }
767 
768 
770 {
771  if ( !pParent )
772  pParent = pRootItem.get();
773  SvTreeListEntry* pResult;
774  if (!pParent->m_Children.empty())
775  pResult = pParent->m_Children[0].get();
776  else
777  pResult = nullptr;
778  return pResult;
779 }
780 
782 {
783  DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
784  pEntry = Next( pEntry );
785  while( pEntry && !pView->IsSelected(pEntry) )
786  pEntry = Next( pEntry );
787  return pEntry;
788 }
789 
791 {
792  DBG_ASSERT(pView,"LastSel:No View");
793  SvTreeListEntry* pEntry = Last();
794  while( pEntry && !pView->IsSelected(pEntry) )
795  pEntry = Prev( pEntry );
796  return pEntry;
797 }
798 
800 {
801  DBG_ASSERT( pEntry,"Entry?");
802 
803  if ( !pParent )
804  pParent = pRootItem.get();
805 
806  SvTreeListEntries& rList = pParent->m_Children;
807 
808  // take sorting into account
809  GetInsertionPos( pEntry, pParent, nPos );
810 
811  bAbsPositionsValid = false;
812  pEntry->pParent = pParent;
813 
814  if (nPos < rList.size())
815  {
816  SvTreeListEntries::iterator itPos = rList.begin();
817  std::advance(itPos, nPos);
818  rList.insert(itPos, std::unique_ptr<SvTreeListEntry>(pEntry));
819  }
820  else
821  rList.push_back(std::unique_ptr<SvTreeListEntry>(pEntry));
822 
823  nEntryCount++;
824  if (nPos != TREELIST_APPEND && (nPos != (rList.size()-1)))
825  SetListPositions(rList);
826  else
827  pEntry->nListPos = rList.size()-1;
828 
830  return nPos; // pEntry->nListPos;
831 }
832 
834 {
835  if ( !bAbsPositionsValid )
836  const_cast<SvTreeList*>(this)->SetAbsolutePositions();
837  return pEntry->nAbsPos;
838 }
839 
841 {
842  return pChild->GetChildListPos();
843 }
844 
846 {
847  sal_uLong nPos = 0;
848  SvTreeListEntry* pEntry = First();
849  while ( pEntry )
850  {
851  pEntry->nAbsPos = nPos;
852  nPos++;
853  pEntry = Next( pEntry );
854  }
855  bAbsPositionsValid = true;
856 }
857 
859 {
860  DBG_ASSERT(pEntry,"Expand:View/Entry?");
861  if ( IsExpanded(pEntry) )
862  return;
863 
864  DBG_ASSERT(!pEntry->m_Children.empty(), "SvTreeList::Expand: We expected to have child entries.");
865 
866  SvViewDataEntry* pViewData = GetViewData(pEntry);
867  pViewData->SetExpanded(true);
868  SvTreeListEntry* pParent = pEntry->pParent;
869  // if parent is visible, invalidate status data
870  if ( IsExpanded( pParent ) )
871  {
872  m_pImpl->m_bVisPositionsValid = false;
873  m_pImpl->m_nVisibleCount = 0;
874  }
875 }
876 
878 {
879  DBG_ASSERT(pEntry,"Collapse:View/Entry?");
880  if ( !IsExpanded(pEntry) )
881  return;
882 
883  DBG_ASSERT(!pEntry->m_Children.empty(), "SvTreeList::Collapse: We expected to have child entries.");
884 
885  SvViewDataEntry* pViewData = GetViewData( pEntry );
886  pViewData->SetExpanded(false);
887 
888  SvTreeListEntry* pParent = pEntry->pParent;
889  if ( IsExpanded(pParent) )
890  {
891  m_pImpl->m_nVisibleCount = 0;
892  m_pImpl->m_bVisPositionsValid = false;
893  }
894 }
895 
896 bool SvListView::SelectListEntry( SvTreeListEntry* pEntry, bool bSelect )
897 {
898  DBG_ASSERT(pEntry,"Select:View/Entry?");
899  SvViewDataEntry* pViewData = GetViewData( pEntry );
900  if ( bSelect )
901  {
902  if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
903  return false;
904  else
905  {
906  pViewData->SetSelected(true);
907  m_pImpl->m_nSelectionCount++;
908  }
909  }
910  else
911  {
912  if ( !pViewData->IsSelected() )
913  return false;
914  else
915  {
916  pViewData->SetSelected(false);
917  m_pImpl->m_nSelectionCount--;
918  }
919  }
920  return true;
921 }
922 
923 bool SvTreeList::Remove( const SvTreeListEntry* pEntry )
924 {
925  DBG_ASSERT(pEntry,"Cannot remove root, use clear");
926 
927  if( !pEntry->pParent )
928  {
929  OSL_FAIL("Removing entry not in model!");
930  // Under certain circumstances (which?), the explorer deletes entries
931  // from the view that it hasn't inserted into the view. We don't want
932  // to crash, so we catch this case here.
933  return false;
934  }
935 
936  Broadcast(SvListAction::REMOVING, const_cast<SvTreeListEntry*>(pEntry));
937  sal_uLong nRemoved = 1 + GetChildCount(pEntry);
938  bAbsPositionsValid = false;
939 
940  SvTreeListEntry* pParent = pEntry->pParent;
941  SvTreeListEntries& rList = pParent->m_Children;
942  bool bLastEntry = false;
943 
944  // Since we need the live instance of SvTreeListEntry for broadcasting,
945  // we first need to pop it from the container, broadcast it, then delete
946  // the instance manually at the end.
947 
948  std::unique_ptr<SvTreeListEntry> pEntryDeleter;
949  if ( pEntry->HasChildListPos() )
950  {
951  size_t nListPos = pEntry->GetChildListPos();
952  bLastEntry = (nListPos == (rList.size()-1));
953  SvTreeListEntries::iterator it = rList.begin();
954  std::advance(it, nListPos);
955  pEntryDeleter = std::move(*it);
956  rList.erase(it);
957  }
958  else
959  {
960  SvTreeListEntries::iterator it =
961  std::find_if(rList.begin(), rList.end(), FindByPointer(pEntry));
962  if (it != rList.end())
963  {
964  pEntryDeleter = std::move(*it);
965  rList.erase(it);
966  }
967  }
968 
969  if (!rList.empty() && !bLastEntry)
970  SetListPositions(rList);
971 
972  nEntryCount -= nRemoved;
973  Broadcast(SvListAction::REMOVED, const_cast<SvTreeListEntry*>(pEntry));
974 
975  return true;
976 }
977 
979 {
980  SvTreeListEntry* pEntry = First();
981  while ( nAbsPos && pEntry )
982  {
983  pEntry = Next( pEntry );
984  nAbsPos--;
985  }
986  return pEntry;
987 }
988 
990 {
991  DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
992  SvTreeListEntry* pEntry = First();
993  while ( nVisPos && pEntry )
994  {
995  pEntry = NextVisible( pView, pEntry );
996  nVisPos--;
997  }
998  return pEntry;
999 }
1000 
1002 {
1003  if (rEntries.empty())
1004  return;
1005 
1006  SvTreeListEntry& rFirst = *rEntries.front();
1007  if (rFirst.pParent)
1009 }
1010 
1011 void SvTreeList::EnableInvalidate( bool bEnable )
1012 {
1013  mbEnableInvalidate = bEnable;
1014 }
1015 
1017 {
1018  if (!mbEnableInvalidate)
1019  return;
1020 
1022 }
1023 
1025 {
1026  DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
1027  SvTreeListEntry* pCurParent = nullptr;
1028  if ( pEntry )
1029  {
1030  pCurParent = pEntry->pParent;
1031  if ( pCurParent == pRootItem.get() )
1032  return pEntry; // is its own parent
1033  while( pCurParent && pCurParent->pParent != pRootItem.get() )
1034  pCurParent = pCurParent->pParent;
1035  }
1036  return pCurParent;
1037 }
1038 
1039 std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator>
1041 {
1042  typedef std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator> IteratorPair;
1043 
1044  static SvTreeListEntries dummy; // prevent singular iterator asserts
1045  IteratorPair aRet(dummy.begin(), dummy.end());
1046 
1047  if (!pParent)
1048  pParent = pRootItem.get();
1049 
1050  if (pParent->m_Children.empty())
1051  // This entry has no children.
1052  return aRet;
1053 
1054  aRet.first = pParent->m_Children.begin();
1055  aRet.second = pParent->m_Children.end();
1056 
1057  return aRet;
1058 }
1059 
1060 
1062  : m_pImpl(new Impl(*this))
1063 {
1064  pModel.reset(new SvTreeList(*this));
1065  m_pImpl->InitTable();
1066 }
1067 
1069 {
1070  pModel.reset();
1071 }
1072 
1074 {
1075  m_pImpl->m_DataTable.clear();
1076 }
1077 
1079 { return m_pImpl->m_nSelectionCount; }
1080 
1082 { return m_pImpl->m_DataTable.size() > 1; } // There's always a ROOT
1083 
1084 
1086 {
1087  DBG_ASSERT(m_rThis.pModel,"InitTable:No Model");
1089  "InitTable: Not cleared!");
1090 
1091  if (!m_DataTable.empty())
1092  {
1093  DBG_ASSERT(m_DataTable.size() == 1, "InitTable: TableCount != 1");
1094  // Delete the view data allocated to the Clear in the root.
1095  // Attention: The model belonging to the root entry (and thus the entry
1096  // itself) might already be deleted.
1097  m_DataTable.clear();
1098  }
1099 
1100  SvTreeListEntry* pEntry;
1101 
1102  // insert root entry
1103  pEntry = m_rThis.pModel->pRootItem.get();
1104  std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry);
1105  pViewData->SetExpanded(true);
1106  m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1107  // now all the other entries
1108  pEntry = m_rThis.pModel->First();
1109  while( pEntry )
1110  {
1111  pViewData = std::make_unique<SvViewDataEntry>();
1112  m_rThis.InitViewData( pViewData.get(), pEntry );
1113  m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1114  pEntry = m_rThis.pModel->Next( pEntry );
1115  }
1116 }
1117 
1119 {
1120  m_pImpl->m_DataTable.clear();
1121  m_pImpl->m_nSelectionCount = 0;
1122  m_pImpl->m_nVisibleCount = 0;
1123  m_pImpl->m_bVisPositionsValid = false;
1124  if( pModel )
1125  {
1126  // insert root entry
1127  SvTreeListEntry* pEntry = pModel->pRootItem.get();
1128  std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry);
1129  pViewData->SetExpanded(true);
1130  m_pImpl->m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1131  }
1132 }
1133 
1135 {
1136 }
1137 
1139 {
1140 }
1141 
1143 {
1144 }
1145 
1147 {
1148 }
1149 
1150 
1152 {
1153 }
1154 
1156 {
1157 }
1158 
1160 {
1161  //WARNING WARNING WARNING
1162  //The supplied pointer should have been deleted
1163  //before this call. Be careful not to use it!!!
1164 }
1165 
1167 {
1168 }
1169 
1171 {
1172  SvTreeListEntry* pParent = pEntry->pParent;
1173  DBG_ASSERT(pParent,"Model not consistent");
1174  if (pParent != m_rThis.pModel->pRootItem.get() && pParent->m_Children.size() == 1)
1175  {
1176  SvViewDataEntry* pViewData = m_DataTable.find( pParent )->second.get();
1177  pViewData->SetExpanded(false);
1178  }
1179  // preliminary
1180  m_nVisibleCount = 0;
1181  m_bVisPositionsValid = false;
1182 }
1183 
1185 {
1186  m_nVisibleCount = 0;
1187  m_bVisPositionsValid = false;
1188 }
1189 
1191 {
1192  DBG_ASSERT(pEntry,"Insert:No Entry");
1193  std::unique_ptr<SvViewDataEntry> pData(new SvViewDataEntry());
1194  m_rThis.InitViewData( pData.get(), pEntry );
1195  std::pair<SvDataTable::iterator, bool> aSuccess =
1196  m_DataTable.insert(std::make_pair(pEntry, std::move(pData)));
1197  DBG_ASSERT(aSuccess.second,"Entry already in View");
1198  if (m_nVisibleCount && m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1199  {
1200  m_nVisibleCount = 0;
1201  m_bVisPositionsValid = false;
1202  }
1203 }
1204 
1206 {
1207  if (m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1208  {
1209  m_nVisibleCount = 0;
1210  m_bVisPositionsValid = false;
1211  }
1212  // iterate over entry and its children
1213  SvTreeListEntry* pCurEntry = pEntry;
1214  sal_uInt16 nRefDepth = m_rThis.pModel->GetDepth( pCurEntry );
1215  while( pCurEntry )
1216  {
1217  DBG_ASSERT(m_DataTable.find(pCurEntry) != m_DataTable.end(),"Entry already in Table");
1218  std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry());
1219  m_rThis.InitViewData( pViewData.get(), pEntry );
1220  m_DataTable.insert(std::make_pair(pCurEntry, std::move(pViewData)));
1221  pCurEntry = m_rThis.pModel->Next( pCurEntry );
1222  if ( pCurEntry && m_rThis.pModel->GetDepth(pCurEntry) <= nRefDepth)
1223  pCurEntry = nullptr;
1224  }
1225 }
1226 
1228 {
1229  for (auto const& it : pParent->m_Children)
1230  {
1231  SvTreeListEntry& rEntry = *it;
1232  m_DataTable.erase(&rEntry);
1233  if (rEntry.HasChildren())
1234  RemoveViewData(&rEntry);
1235  }
1236 }
1237 
1238 
1240 {
1241  DBG_ASSERT(pEntry,"Remove:No Entry");
1242 
1243  SvViewDataEntry* pViewData = m_DataTable.find( pEntry )->second.get();
1244  sal_uLong nSelRemoved = 0;
1245  if ( pViewData->IsSelected() )
1246  nSelRemoved = 1 + m_rThis.pModel->GetChildSelectionCount(&m_rThis, pEntry);
1247  m_nSelectionCount -= nSelRemoved;
1248  sal_uLong nVisibleRemoved = 0;
1249  if (m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1250  nVisibleRemoved = 1 + m_rThis.pModel->GetVisibleChildCount(&m_rThis, pEntry);
1251  if( m_nVisibleCount )
1252  {
1253 #ifdef DBG_UTIL
1254  if (m_nVisibleCount < nVisibleRemoved)
1255  {
1256  OSL_FAIL("nVisibleRemoved bad");
1257  }
1258 #endif
1259  m_nVisibleCount -= nVisibleRemoved;
1260  }
1261  m_bVisPositionsValid = false;
1262 
1263  m_DataTable.erase(pEntry);
1264  RemoveViewData( pEntry );
1265 
1266  SvTreeListEntry* pCurEntry = pEntry->pParent;
1267  if (pCurEntry && pCurEntry != m_rThis.pModel->pRootItem.get() && pCurEntry->m_Children.size() == 1)
1268  {
1269  pViewData = m_DataTable.find(pCurEntry)->second.get();
1270  pViewData->SetExpanded(false);
1271  }
1272 }
1273 
1275 {
1276  m_rThis.Clear();
1277 }
1278 
1280  SvTreeListEntry* /*pEntry2*/, sal_uLong /*nPos*/ )
1281 {
1282  switch( nActionId )
1283  {
1285  m_pImpl->ActionInserted( pEntry1 );
1286  ModelHasInserted( pEntry1 );
1287  break;
1289  m_pImpl->ActionInsertedTree( pEntry1 );
1290  ModelHasInsertedTree( pEntry1 );
1291  break;
1293  ModelIsRemoving( pEntry1 );
1294  m_pImpl->ActionRemoving( pEntry1 );
1295  break;
1296  case SvListAction::REMOVED:
1297  ModelHasRemoved( pEntry1 );
1298  break;
1299  case SvListAction::MOVING:
1300  ModelIsMoving( pEntry1 );
1301  m_pImpl->ActionMoving( pEntry1 );
1302  break;
1303  case SvListAction::MOVED:
1304  m_pImpl->ActionMoved();
1305  ModelHasMoved( pEntry1 );
1306  break;
1308  m_pImpl->ActionClear();
1309  ModelHasCleared(); // sic! for compatibility reasons!
1310  break;
1311  case SvListAction::CLEARED:
1312  break;
1314  // no action for the base class
1315  ModelHasEntryInvalidated( pEntry1 );
1316  break;
1318  m_pImpl->m_bVisPositionsValid = false;
1319  break;
1321  break;
1322  default:
1323  OSL_FAIL("unknown ActionId");
1324  }
1325 }
1326 
1328 {
1329 }
1330 
1332 {
1333  DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1334  SvDataTable::const_iterator itr = m_pImpl->m_DataTable.find(pEntry);
1335  DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in Table");
1336  if (itr == m_pImpl->m_DataTable.end())
1337  return false;
1338  return itr->second->IsExpanded();
1339 }
1340 
1342 {
1343  DBG_ASSERT(pEntry,"IsAllExpanded:No Entry");
1344  if (!IsExpanded(pEntry))
1345  return false;
1346  const SvTreeListEntries& rChildren = pEntry->GetChildEntries();
1347  for (auto& rChild : rChildren)
1348  {
1349  if (rChild->HasChildren() || rChild->HasChildrenOnDemand())
1350  {
1351  if (!IsAllExpanded(rChild.get()))
1352  return false;
1353  }
1354  }
1355  return true;
1356 }
1357 
1358 bool SvListView::IsSelected(const SvTreeListEntry* pEntry) const
1359 {
1360  DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1361  SvDataTable::const_iterator itr = m_pImpl->m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry));
1362  if (itr == m_pImpl->m_DataTable.end())
1363  return false;
1364  return itr->second->IsSelected();
1365 }
1366 
1367 void SvListView::SetEntryFocus( SvTreeListEntry* pEntry, bool bFocus )
1368 {
1369  DBG_ASSERT(pEntry,"SetEntryFocus:No Entry");
1370  SvDataTable::iterator itr = m_pImpl->m_DataTable.find(pEntry);
1371  DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in Table");
1372  itr->second->SetFocus(bFocus);
1373 }
1374 
1376 {
1377  SvDataTable::const_iterator itr =
1378  m_pImpl->m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry));
1379  if (itr == m_pImpl->m_DataTable.end())
1380  return nullptr;
1381  return itr->second.get();
1382 }
1383 
1385 {
1386  SvDataTable::iterator itr = m_pImpl->m_DataTable.find( pEntry );
1387  DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in model or wrong view");
1388  return itr->second.get();
1389 }
1390 
1391 sal_Int32 SvTreeList::Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const
1392 {
1393  if( aCompareLink.IsSet())
1394  {
1395  SvSortData aSortData;
1396  aSortData.pLeft = pLeft;
1397  aSortData.pRight = pRight;
1398  return aCompareLink.Call( aSortData );
1399  }
1400  return 0;
1401 }
1402 
1404 {
1405  Broadcast( SvListAction::RESORTING );
1406  bAbsPositionsValid = false;
1407  ResortChildren( pRootItem.get() );
1408  Broadcast( SvListAction::RESORTED );
1409 }
1410 
1411 namespace {
1412 
1413 class SortComparator
1414 {
1415  SvTreeList& mrList;
1416 public:
1417 
1418  explicit SortComparator( SvTreeList& rList ) : mrList(rList) {}
1419 
1420  bool operator() (std::unique_ptr<SvTreeListEntry> const& rpLeft,
1421  std::unique_ptr<SvTreeListEntry> const& rpRight) const
1422  {
1423  int nCompare = mrList.Compare(rpLeft.get(), rpRight.get());
1424  if (nCompare != 0 && mrList.GetSortMode() == SortDescending)
1425  {
1426  if( nCompare < 0 )
1427  nCompare = 1;
1428  else
1429  nCompare = -1;
1430  }
1431  return nCompare < 0;
1432  }
1433 };
1434 
1435 }
1436 
1438 {
1439  DBG_ASSERT(pParent,"Parent not set");
1440 
1441  if (pParent->m_Children.empty())
1442  return;
1443 
1444  SortComparator aComp(*this);
1445  std::sort(pParent->m_Children.begin(), pParent->m_Children.end(), aComp);
1446 
1447  // Recursively sort child entries.
1448  for (auto const& it : pParent->m_Children)
1449  {
1450  SvTreeListEntry& r = *it;
1451  ResortChildren(&r);
1452  }
1453 
1454  SetListPositions(pParent->m_Children); // correct list position in target list
1455 }
1456 
1458  sal_uLong& rPos )
1459 {
1460  DBG_ASSERT(pEntry,"No Entry");
1461 
1462  if( eSortMode == SortNone )
1463  return;
1464 
1465  rPos = TREELIST_ENTRY_NOTFOUND;
1466  const SvTreeListEntries& rChildList = GetChildList(pParent);
1467 
1468  if (rChildList.empty())
1469  return;
1470 
1471  long i = 0;
1472  long j = rChildList.size()-1;
1473  long k;
1474  sal_Int32 nCompare = 1;
1475 
1476  do
1477  {
1478  k = (i+j)/2;
1479  const SvTreeListEntry* pTempEntry = rChildList[k].get();
1480  nCompare = Compare( pEntry, pTempEntry );
1481  if (nCompare != 0 && eSortMode == SortDescending)
1482  {
1483  if( nCompare < 0 )
1484  nCompare = 1;
1485  else
1486  nCompare = -1;
1487  }
1488  if( nCompare > 0 )
1489  i = k + 1;
1490  else
1491  j = k - 1;
1492  } while( (nCompare != 0) && (i <= j) );
1493 
1494  if( nCompare != 0 )
1495  {
1496  if (i > static_cast<long>(rChildList.size()-1)) // not found, end of list
1497  rPos = TREELIST_ENTRY_NOTFOUND;
1498  else
1499  rPos = i; // not found, middle of list
1500  }
1501  else
1502  rPos = k;
1503 }
1504 
1505 bool SvTreeList::HasChildren( const SvTreeListEntry* pEntry ) const
1506 {
1507  if ( !pEntry )
1508  pEntry = pRootItem.get();
1509 
1510  return !pEntry->m_Children.empty();
1511 }
1512 
1513 bool SvTreeList::HasParent( const SvTreeListEntry* pEntry ) const
1514 {
1515  return pEntry->pParent != pRootItem.get();
1516 }
1517 
1519 { if ( !pParent )
1520  pParent = pRootItem.get();
1521  SvTreeListEntry* pRet = nullptr;
1522  if (nPos < pParent->m_Children.size())
1523  pRet = pParent->m_Children[nPos].get();
1524  return pRet;
1525 }
1526 
1528 {
1529  SvTreeListEntry* pRet = nullptr;
1530  if (nEntryCount && nRootPos < pRootItem->m_Children.size())
1531  pRet = pRootItem->m_Children[nRootPos].get();
1532  return pRet;
1533 }
1534 
1536 {
1537  if ( !pParent )
1538  pParent = pRootItem.get();
1539  return pParent->m_Children;
1540 }
1541 
1543 {
1544  if ( !pParent )
1545  pParent = pRootItem.get();
1546  return pParent->m_Children;
1547 }
1548 
1550 {
1551  const SvTreeListEntry* pParent = pEntry->pParent;
1552  if (pParent == pRootItem.get())
1553  pParent = nullptr;
1554  return pParent;
1555 }
1556 
1558 {
1559  SvTreeListEntry* pParent = pEntry->pParent;
1560  if (pParent == pRootItem.get())
1561  pParent = nullptr;
1562  return pParent;
1563 }
1564 
1565 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvListView & m_rThis
Definition: treelist.cxx:34
void dispose()
Definition: treelist.cxx:1068
virtual void ModelHasEntryInvalidated(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1166
SvSortMode eSortMode
Definition: treelist.hxx:71
bool IsSelectable() const
bool HasChildren(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1505
void InvalidateEntry(SvTreeListEntry *)
Definition: treelist.cxx:1016
sal_uLong GetVisibleChildCount(const SvListView *, SvTreeListEntry *pParent) const
Definition: treelist.cxx:416
SvListAction
Definition: treelist.hxx:32
VCL_DLLPRIVATE void GetInsertionPos(SvTreeListEntry const *pEntry, SvTreeListEntry *pParent, sal_uLong &rPos)
Definition: treelist.cxx:1457
std::unique_ptr< ContentProperties > pData
std::unique_ptr< Impl > m_pImpl
Definition: treelist.hxx:212
virtual ~SvListView()
Definition: treelist.cxx:1073
const SvTreeListEntries & GetChildList(SvTreeListEntry *pParent) const
Definition: treelist.cxx:1535
Impl(SvListView &rThis)
Definition: treelist.cxx:42
sal_uIntPtr sal_uLong
sal_Int32 Compare(const SvTreeListEntry *pLeft, const SvTreeListEntry *pRight) const
Definition: treelist.cxx:1391
sal_uInt16 GetDepth(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:102
bool m_bVisPositionsValid
Definition: treelist.cxx:40
sal_uLong GetChildCount(const SvTreeListEntry *pParent) const
Definition: treelist.cxx:396
void EnableInvalidate(bool bEnable)
Definition: treelist.cxx:1011
std::pair< SvTreeListEntries::iterator, SvTreeListEntries::iterator > GetChildIterators(SvTreeListEntry *pParent)
Definition: treelist.cxx:1040
static VCL_DLLPRIVATE void SetListPositions(SvTreeListEntries &rEntries)
Invalidate the cached position data to have them re-generated before the next access.
Definition: treelist.cxx:1001
SvTreeListEntry * LastVisible(const SvListView *) const
Definition: treelist.cxx:705
View-dependent data for a tree list entry created in the virtual function SvTreeListBox::CreateViewDa...
std::unique_ptr< SvTreeListEntry > pRootItem
Definition: treelist.hxx:119
VCL_DLLPRIVATE void CloneChildren(SvTreeListEntries &rDst, sal_uLong &rCloneCount, SvTreeListEntries &rSrc, SvTreeListEntry &rNewParent) const
Definition: treelist.cxx:376
void SetEntryFocus(SvTreeListEntry *pEntry, bool bFocus)
Definition: treelist.cxx:1367
void ActionInsertedTree(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1205
SvTreeListEntry * Next(SvTreeListEntry *pEntry, sal_uInt16 *pDepth=nullptr) const
Definition: treelist.cxx:467
friend class SvTreeList
Definition: treelist.hxx:209
const SvTreeListEntry * GetParent(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1549
SvTreeListEntries m_Children
int nCount
virtual void ModelHasInsertedTree(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1142
SvTreeListEntry * PrevVisible(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:672
SvTreeListEntry * CloneEntry(SvTreeListEntry *pSource) const
Definition: treelist.cxx:356
SvTreeListEntry * GetRootLevelParent(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1024
sal_uLong GetVisibleCount(SvListView *) const
Definition: treelist.cxx:580
void ActionMoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1170
void Broadcast(SvListAction nActionId, SvTreeListEntry *pEntry1=nullptr, SvTreeListEntry *pEntry2=nullptr, sal_uLong nPos=0)
Definition: treelist.cxx:75
bool IsChild(const SvTreeListEntry *pParent, const SvTreeListEntry *pChild) const
Definition: treelist.cxx:127
bool IsEntryVisible(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:86
bool bAbsPositionsValid
Definition: treelist.hxx:73
SvTreeListEntry * GetEntry(SvTreeListEntry *pParent, sal_uLong nPos) const
Definition: treelist.cxx:1518
bool HasViewData() const
Definition: treelist.cxx:1081
void InvalidateChildrensListPositions()
VCL_DLLPRIVATE void SetAbsolutePositions()
Definition: treelist.cxx:845
virtual void InitViewData(SvViewDataEntry *, SvTreeListEntry *pEntry)
Definition: treelist.cxx:1327
SvTreeListEntry * NextSelected(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:781
sal_uLong GetAbsPos(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:833
#define DBG_ASSERT(sCon, aError)
SvTreeListEntry * Clone(SvTreeListEntry *pEntry, sal_uLong &nCloneCount) const
Definition: treelist.cxx:365
int i
bool Remove(const SvTreeListEntry *pEntry)
Definition: treelist.cxx:923
void Clear()
Definition: treelist.cxx:1118
void Clone(SvTreeListEntry *pSource)
void Clear()
Definition: treelist.cxx:119
bool IsSelected(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1358
std::unique_ptr< SvTreeList > pModel
Definition: treelist.hxx:215
sal_uLong GetEntryCount() const
Definition: treelist.hxx:139
void ActionInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1190
sal_uLong Copy(SvTreeListEntry *pSource, SvTreeListEntry *pTargetParent, sal_uLong nListPos)
Definition: treelist.cxx:270
virtual void ModelHasRemoved(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1159
SvTreeListEntry * Last() const
Definition: treelist.cxx:554
static sal_uLong GetRelPos(const SvTreeListEntry *pChild)
Definition: treelist.cxx:840
sal_uLong GetVisiblePos(const SvListView *, SvTreeListEntry const *pEntry) const
Definition: treelist.cxx:566
std::map< SvTreeListEntry *, std::unique_ptr< SvViewDataEntry > > SvDataTable
Definition: treelist.cxx:30
void SetSelected(bool bSelected)
SvTreeListEntry * Prev(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:525
sal_uLong GetChildSelectionCount(const SvListView *, SvTreeListEntry *pParent) const
Definition: treelist.cxx:437
sal_uLong GetChildListPos() const
bool HasChildListPos() const
SvTreeListEntries & GetChildEntries()
SvTreeList()=delete
bool IsAtRootDepth(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:114
bool SelectListEntry(SvTreeListEntry *pEntry, bool bSelect)
Definition: treelist.cxx:896
bool mbEnableInvalidate
Definition: treelist.hxx:75
const SvTreeListEntry * pRight
Definition: treelist.hxx:59
bool HasParent(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1513
SvTreeListEntry * FirstSelected(const SvListView *) const
Definition: treelist.cxx:757
bool IsExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1331
sal_uLong m_nVisibleCount
Definition: treelist.cxx:38
const SvViewDataEntry * GetViewData(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1375
void RemoveViewData(SvTreeListEntry *pParent)
Definition: treelist.cxx:1227
bool HasChildren() const
SvSortMode GetSortMode() const
Definition: treelist.hxx:201
sal_uLong m_nSelectionCount
Definition: treelist.cxx:39
bool IsAllExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1341
VCL_DLLPRIVATE void ResortChildren(SvTreeListEntry *pParent)
Definition: treelist.cxx:1437
void ActionRemoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1239
virtual void ModelIsRemoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1155
void ExpandListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:858
sal_uLong Insert(SvTreeListEntry *pEntry, SvTreeListEntry *pPar, sal_uLong nPos=TREELIST_APPEND)
Definition: treelist.cxx:799
void CollapseListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:877
void Resort()
Definition: treelist.cxx:1403
SvTreeListEntry * GetEntryAtVisPos(const SvListView *, sal_uLong nVisPos) const
Definition: treelist.cxx:989
sal_uLong nListPos
SvTreeListEntry * First() const
Definition: treelist.cxx:459
void * p
void SetExpanded(bool bExpanded)
SvListView & mrOwnerListView
Definition: treelist.hxx:66
SvDataTable m_DataTable
Definition: treelist.cxx:36
void Move(SvTreeListEntry *pSource, SvTreeListEntry *pTarget)
Definition: treelist.cxx:303
SvTreeListEntry * NextVisible(const SvListView *, SvTreeListEntry *pEntry, sal_uInt16 *pDepth=nullptr) const
Definition: treelist.cxx:611
virtual void ModelIsMoving(SvTreeListEntry *pSource)
Definition: treelist.cxx:1146
SvTreeListEntry * GetEntryAtAbsPos(sal_uLong nAbsPos) const
Definition: treelist.cxx:978
SvTreeListEntry * LastSelected(const SvListView *) const
Definition: treelist.cxx:790
virtual void ModelHasCleared()
Definition: treelist.cxx:1134
void InsertTree(SvTreeListEntry *pTree, SvTreeListEntry *pTargetParent, sal_uLong nListPos)
Definition: treelist.cxx:322
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
#define TREELIST_ENTRY_NOTFOUND
Link< SvTreeListEntry *, SvTreeListEntry * > aCloneLink
Definition: treelist.hxx:69
sal_uLong GetSelectionCount() const
Definition: treelist.cxx:1078
virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry *pEntry1, SvTreeListEntry *pEntry2, sal_uLong nPos)
Definition: treelist.cxx:1279
bool IsSelected() const
virtual void ModelHasMoved(SvTreeListEntry *pSource)
Definition: treelist.cxx:1151
virtual void ModelHasInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1138
SvTreeListEntry * FirstChild(SvTreeListEntry *pParent) const
Definition: treelist.cxx:769
sal_uLong nEntryCount
Definition: treelist.hxx:67
SvTreeListEntry * pParent
sal_uInt16 nPos
std::vector< std::unique_ptr< SvTreeListEntry > > SvTreeListEntries
#define TREELIST_APPEND
const SvTreeListEntry * pLeft
Definition: treelist.hxx:58