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  sal_uInt16 nDepth = 0;
530 
531  SvTreeListEntries* pActualList = &pActEntry->pParent->m_Children;
532  sal_uLong nActualPos = pActEntry->GetChildListPos();
533 
534  if ( nActualPos > 0 )
535  {
536  pActEntry = (*pActualList)[nActualPos-1].get();
537  while (!pActEntry->m_Children.empty())
538  {
539  pActualList = &pActEntry->m_Children;
540  nDepth++;
541  pActEntry = pActualList->back().get();
542  }
543  return pActEntry;
544  }
545  if ( pActEntry->pParent == pRootItem.get() )
546  return nullptr;
547 
548  pActEntry = pActEntry->pParent;
549 
550  if ( pActEntry )
551  {
552  nDepth--;
553  return pActEntry;
554  }
555  return nullptr;
556 }
557 
559 {
560  SvTreeListEntries* pActList = &pRootItem->m_Children;
561  SvTreeListEntry* pEntry = nullptr;
562  while (!pActList->empty())
563  {
564  pEntry = pActList->back().get();
565  pActList = &pEntry->m_Children;
566  }
567  return pEntry;
568 }
569 
570 sal_uLong SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry const * pEntry ) const
571 {
572  DBG_ASSERT(pView&&pEntry,"View/Entry?");
573 
574  if (!pView->m_pImpl->m_bVisPositionsValid)
575  {
576  // to make GetVisibleCount refresh the positions
577  const_cast<SvListView*>(pView)->m_pImpl->m_nVisibleCount = 0;
578  GetVisibleCount( const_cast<SvListView*>(pView) );
579  }
580  const SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
581  return pViewData->nVisPos;
582 }
583 
585 {
586  assert(pView && "GetVisCount:No View");
587  if( !pView->HasViewData() )
588  return 0;
589  if (pView->m_pImpl->m_nVisibleCount)
590  return pView->m_pImpl->m_nVisibleCount;
591 
592  sal_uLong nPos = 0;
593  SvTreeListEntry* pEntry = First(); // first entry is always visible
594  while ( pEntry )
595  {
596  SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
597  pViewData->nVisPos = nPos;
598  nPos++;
599  pEntry = NextVisible( pView, pEntry );
600  }
601 #ifdef DBG_UTIL
602  if( nPos > 10000000 )
603  {
604  OSL_FAIL("nVisibleCount bad");
605  }
606 #endif
607  pView->m_pImpl->m_nVisibleCount = nPos;
608  pView->m_pImpl->m_bVisPositionsValid = true;
609  return nPos;
610 }
611 
612 
613 // For performance reasons, this function assumes that the passed entry is
614 // already visible.
615 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pActEntry,sal_uInt16* pActDepth) const
616 {
617  DBG_ASSERT(pView,"NextVisible:No View");
618  if ( !pActEntry )
619  return nullptr;
620 
621  sal_uInt16 nDepth = 0;
622  bool bWithDepth = false;
623  if ( pActDepth )
624  {
625  nDepth = *pActDepth;
626  bWithDepth = true;
627  }
628 
629  SvTreeListEntries* pActualList = &pActEntry->pParent->m_Children;
630  sal_uLong nActualPos = pActEntry->GetChildListPos();
631 
632  if ( pView->IsExpanded(pActEntry) )
633  {
634  OSL_ENSURE(!pActEntry->m_Children.empty(), "Pass entry is supposed to have child entries.");
635 
636  nDepth++;
637  pActEntry = pActEntry->m_Children[0].get();
638  if ( bWithDepth )
639  *pActDepth = nDepth;
640  return pActEntry;
641  }
642 
643  nActualPos++;
644  if ( pActualList->size() > nActualPos )
645  {
646  pActEntry = (*pActualList)[nActualPos].get();
647  if ( bWithDepth )
648  *pActDepth = nDepth;
649  return pActEntry;
650  }
651 
652  SvTreeListEntry* pParent = pActEntry->pParent;
653  nDepth--;
654  while( pParent != pRootItem.get() )
655  {
656  pActualList = &pParent->pParent->m_Children;
657  nActualPos = pParent->GetChildListPos();
658  nActualPos++;
659  if ( pActualList->size() > nActualPos )
660  {
661  pActEntry = (*pActualList)[nActualPos].get();
662  if ( bWithDepth )
663  *pActDepth = nDepth;
664  return pActEntry;
665  }
666  pParent = pParent->pParent;
667  nDepth--;
668  }
669  return nullptr;
670 }
671 
672 
673 // For performance reasons, this function assumes that the passed entry is
674 // already visible.
675 
677 {
678  DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
679 
680  sal_uInt16 nDepth = 0;
681 
682  SvTreeListEntries* pActualList = &pActEntry->pParent->m_Children;
683  sal_uLong nActualPos = pActEntry->GetChildListPos();
684 
685  if ( nActualPos > 0 )
686  {
687  pActEntry = (*pActualList)[nActualPos-1].get();
688  while( pView->IsExpanded(pActEntry) )
689  {
690  pActualList = &pActEntry->m_Children;
691  nDepth++;
692  pActEntry = pActualList->back().get();
693  }
694  return pActEntry;
695  }
696 
697  if ( pActEntry->pParent == pRootItem.get() )
698  return nullptr;
699 
700  pActEntry = pActEntry->pParent;
701  if ( pActEntry )
702  {
703  nDepth--;
704  return pActEntry;
705  }
706  return nullptr;
707 }
708 
710 {
711  DBG_ASSERT(pView,"LastVis:No View");
712  SvTreeListEntry* pEntry = Last();
713  while( pEntry && !IsEntryVisible( pView, pEntry ) )
714  pEntry = PrevVisible( pView, pEntry );
715  return pEntry;
716 }
717 
718 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pEntry,sal_uInt16& nDelta) const
719 {
720  DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
721 
722  sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
723  // nDelta entries existent?
724  // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
725  // nNewDelta = 10-nVisPos-1 == 4
726  if (nVisPos+nDelta >= pView->m_pImpl->m_nVisibleCount)
727  {
728  nDelta = static_cast<sal_uInt16>(pView->m_pImpl->m_nVisibleCount-nVisPos);
729  nDelta--;
730  }
731  sal_uInt16 nDeltaTmp = nDelta;
732  while( nDeltaTmp )
733  {
734  pEntry = NextVisible( pView, pEntry );
735  nDeltaTmp--;
736  DBG_ASSERT(pEntry,"Entry?");
737  }
738  return pEntry;
739 }
740 
741 SvTreeListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvTreeListEntry* pEntry, sal_uInt16& nDelta ) const
742 {
743  DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
744 
745  sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
746  // nDelta entries existent?
747  // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
748  // nNewDelta = nNewVisPos
749  if ( nDelta > nVisPos )
750  nDelta = static_cast<sal_uInt16>(nVisPos);
751  sal_uInt16 nDeltaTmp = nDelta;
752  while( nDeltaTmp )
753  {
754  pEntry = PrevVisible( pView, pEntry );
755  nDeltaTmp--;
756  DBG_ASSERT(pEntry,"Entry?");
757  }
758  return pEntry;
759 }
760 
762 {
763  DBG_ASSERT(pView,"FirstSel:No View");
764  if( !pView )
765  return nullptr;
766  SvTreeListEntry* pActSelEntry = First();
767  while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
768  pActSelEntry = NextVisible( pView, pActSelEntry );
769  return pActSelEntry;
770 }
771 
772 
774 {
775  if ( !pParent )
776  pParent = pRootItem.get();
777  SvTreeListEntry* pResult;
778  if (!pParent->m_Children.empty())
779  pResult = pParent->m_Children[0].get();
780  else
781  pResult = nullptr;
782  return pResult;
783 }
784 
786 {
787  DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
788  pEntry = Next( pEntry );
789  while( pEntry && !pView->IsSelected(pEntry) )
790  pEntry = Next( pEntry );
791  return pEntry;
792 }
793 
795 {
796  DBG_ASSERT(pView&&pEntry,"PrevSel:View/Entry?");
797  pEntry = Prev( pEntry );
798  while( pEntry && !pView->IsSelected(pEntry) )
799  pEntry = Prev( pEntry );
800 
801  return pEntry;
802 }
803 
805 {
806  DBG_ASSERT(pView,"LastSel:No View");
807  SvTreeListEntry* pEntry = Last();
808  while( pEntry && !pView->IsSelected(pEntry) )
809  pEntry = Prev( pEntry );
810  return pEntry;
811 }
812 
814 {
815  DBG_ASSERT( pEntry,"Entry?");
816 
817  if ( !pParent )
818  pParent = pRootItem.get();
819 
820  SvTreeListEntries& rList = pParent->m_Children;
821 
822  // take sorting into account
823  GetInsertionPos( pEntry, pParent, nPos );
824 
825  bAbsPositionsValid = false;
826  pEntry->pParent = pParent;
827 
828  if (nPos < rList.size())
829  {
830  SvTreeListEntries::iterator itPos = rList.begin();
831  std::advance(itPos, nPos);
832  rList.insert(itPos, std::unique_ptr<SvTreeListEntry>(pEntry));
833  }
834  else
835  rList.push_back(std::unique_ptr<SvTreeListEntry>(pEntry));
836 
837  nEntryCount++;
838  if (nPos != TREELIST_APPEND && (nPos != (rList.size()-1)))
839  SetListPositions(rList);
840  else
841  pEntry->nListPos = rList.size()-1;
842 
844  return nPos; // pEntry->nListPos;
845 }
846 
848 {
849  if ( !bAbsPositionsValid )
850  const_cast<SvTreeList*>(this)->SetAbsolutePositions();
851  return pEntry->nAbsPos;
852 }
853 
855 {
856  return pChild->GetChildListPos();
857 }
858 
860 {
861  sal_uLong nPos = 0;
862  SvTreeListEntry* pEntry = First();
863  while ( pEntry )
864  {
865  pEntry->nAbsPos = nPos;
866  nPos++;
867  pEntry = Next( pEntry );
868  }
869  bAbsPositionsValid = true;
870 }
871 
873 {
874  DBG_ASSERT(pEntry,"Expand:View/Entry?");
875  if ( IsExpanded(pEntry) )
876  return;
877 
878  DBG_ASSERT(!pEntry->m_Children.empty(), "SvTreeList::Expand: We expected to have child entries.");
879 
880  SvViewDataEntry* pViewData = GetViewData(pEntry);
881  pViewData->SetExpanded(true);
882  SvTreeListEntry* pParent = pEntry->pParent;
883  // if parent is visible, invalidate status data
884  if ( IsExpanded( pParent ) )
885  {
886  m_pImpl->m_bVisPositionsValid = false;
887  m_pImpl->m_nVisibleCount = 0;
888  }
889 }
890 
892 {
893  DBG_ASSERT(pEntry,"Collapse:View/Entry?");
894  if ( !IsExpanded(pEntry) )
895  return;
896 
897  DBG_ASSERT(!pEntry->m_Children.empty(), "SvTreeList::Collapse: We expected to have child entries.");
898 
899  SvViewDataEntry* pViewData = GetViewData( pEntry );
900  pViewData->SetExpanded(false);
901 
902  SvTreeListEntry* pParent = pEntry->pParent;
903  if ( IsExpanded(pParent) )
904  {
905  m_pImpl->m_nVisibleCount = 0;
906  m_pImpl->m_bVisPositionsValid = false;
907  }
908 }
909 
910 bool SvListView::SelectListEntry( SvTreeListEntry* pEntry, bool bSelect )
911 {
912  DBG_ASSERT(pEntry,"Select:View/Entry?");
913  SvViewDataEntry* pViewData = GetViewData( pEntry );
914  if ( bSelect )
915  {
916  if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
917  return false;
918  else
919  {
920  pViewData->SetSelected(true);
921  m_pImpl->m_nSelectionCount++;
922  }
923  }
924  else
925  {
926  if ( !pViewData->IsSelected() )
927  return false;
928  else
929  {
930  pViewData->SetSelected(false);
931  m_pImpl->m_nSelectionCount--;
932  }
933  }
934  return true;
935 }
936 
937 bool SvTreeList::Remove( const SvTreeListEntry* pEntry )
938 {
939  DBG_ASSERT(pEntry,"Cannot remove root, use clear");
940 
941  if( !pEntry->pParent )
942  {
943  OSL_FAIL("Removing entry not in model!");
944  // Under certain circumstances (which?), the explorer deletes entries
945  // from the view that it hasn't inserted into the view. We don't want
946  // to crash, so we catch this case here.
947  return false;
948  }
949 
950  Broadcast(SvListAction::REMOVING, const_cast<SvTreeListEntry*>(pEntry));
951  sal_uLong nRemoved = 1 + GetChildCount(pEntry);
952  bAbsPositionsValid = false;
953 
954  SvTreeListEntry* pParent = pEntry->pParent;
955  SvTreeListEntries& rList = pParent->m_Children;
956  bool bLastEntry = false;
957 
958  // Since we need the live instance of SvTreeListEntry for broadcasting,
959  // we first need to pop it from the container, broadcast it, then delete
960  // the instance manually at the end.
961 
962  std::unique_ptr<SvTreeListEntry> pEntryDeleter;
963  if ( pEntry->HasChildListPos() )
964  {
965  size_t nListPos = pEntry->GetChildListPos();
966  bLastEntry = (nListPos == (rList.size()-1));
967  SvTreeListEntries::iterator it = rList.begin();
968  std::advance(it, nListPos);
969  pEntryDeleter = std::move(*it);
970  rList.erase(it);
971  }
972  else
973  {
974  SvTreeListEntries::iterator it =
975  std::find_if(rList.begin(), rList.end(), FindByPointer(pEntry));
976  if (it != rList.end())
977  {
978  pEntryDeleter = std::move(*it);
979  rList.erase(it);
980  }
981  }
982 
983  if (!rList.empty() && !bLastEntry)
984  SetListPositions(rList);
985 
986  nEntryCount -= nRemoved;
987  Broadcast(SvListAction::REMOVED, const_cast<SvTreeListEntry*>(pEntry));
988 
989  return true;
990 }
991 
993 {
994  SvTreeListEntry* pEntry = First();
995  while ( nAbsPos && pEntry )
996  {
997  pEntry = Next( pEntry );
998  nAbsPos--;
999  }
1000  return pEntry;
1001 }
1002 
1004 {
1005  DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
1006  SvTreeListEntry* pEntry = First();
1007  while ( nVisPos && pEntry )
1008  {
1009  pEntry = NextVisible( pView, pEntry );
1010  nVisPos--;
1011  }
1012  return pEntry;
1013 }
1014 
1016 {
1017  if (rEntries.empty())
1018  return;
1019 
1020  SvTreeListEntry& rFirst = *rEntries.front();
1021  if (rFirst.pParent)
1023 }
1024 
1025 void SvTreeList::EnableInvalidate( bool bEnable )
1026 {
1027  mbEnableInvalidate = bEnable;
1028 }
1029 
1031 {
1032  if (!mbEnableInvalidate)
1033  return;
1034 
1036 }
1037 
1039 {
1040  DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
1041  SvTreeListEntry* pCurParent = nullptr;
1042  if ( pEntry )
1043  {
1044  pCurParent = pEntry->pParent;
1045  if ( pCurParent == pRootItem.get() )
1046  return pEntry; // is its own parent
1047  while( pCurParent && pCurParent->pParent != pRootItem.get() )
1048  pCurParent = pCurParent->pParent;
1049  }
1050  return pCurParent;
1051 }
1052 
1053 std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator>
1055 {
1056  typedef std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator> IteratorPair;
1057 
1058  static SvTreeListEntries dummy; // prevent singular iterator asserts
1059  IteratorPair aRet(dummy.begin(), dummy.end());
1060 
1061  if (!pParent)
1062  pParent = pRootItem.get();
1063 
1064  if (pParent->m_Children.empty())
1065  // This entry has no children.
1066  return aRet;
1067 
1068  aRet.first = pParent->m_Children.begin();
1069  aRet.second = pParent->m_Children.end();
1070 
1071  return aRet;
1072 }
1073 
1074 
1076  : m_pImpl(new Impl(*this))
1077 {
1078  pModel.reset(new SvTreeList(*this));
1079  m_pImpl->InitTable();
1080 }
1081 
1083 {
1084  pModel.reset();
1085 }
1086 
1088 {
1089  m_pImpl->m_DataTable.clear();
1090 }
1091 
1093 { return m_pImpl->m_nSelectionCount; }
1094 
1096 { return m_pImpl->m_DataTable.size() > 1; } // There's always a ROOT
1097 
1098 
1100 {
1101  DBG_ASSERT(m_rThis.pModel,"InitTable:No Model");
1103  "InitTable: Not cleared!");
1104 
1105  if (!m_DataTable.empty())
1106  {
1107  DBG_ASSERT(m_DataTable.size() == 1, "InitTable: TableCount != 1");
1108  // Delete the view data allocated to the Clear in the root.
1109  // Attention: The model belonging to the root entry (and thus the entry
1110  // itself) might already be deleted.
1111  m_DataTable.clear();
1112  }
1113 
1114  SvTreeListEntry* pEntry;
1115 
1116  // insert root entry
1117  pEntry = m_rThis.pModel->pRootItem.get();
1118  std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry);
1119  pViewData->SetExpanded(true);
1120  m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1121  // now all the other entries
1122  pEntry = m_rThis.pModel->First();
1123  while( pEntry )
1124  {
1125  pViewData = std::make_unique<SvViewDataEntry>();
1126  m_rThis.InitViewData( pViewData.get(), pEntry );
1127  m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1128  pEntry = m_rThis.pModel->Next( pEntry );
1129  }
1130 }
1131 
1133 {
1134  m_pImpl->m_DataTable.clear();
1135  m_pImpl->m_nSelectionCount = 0;
1136  m_pImpl->m_nVisibleCount = 0;
1137  m_pImpl->m_bVisPositionsValid = false;
1138  if( pModel )
1139  {
1140  // insert root entry
1141  SvTreeListEntry* pEntry = pModel->pRootItem.get();
1142  std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry);
1143  pViewData->SetExpanded(true);
1144  m_pImpl->m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1145  }
1146 }
1147 
1149 {
1150 }
1151 
1153 {
1154 }
1155 
1157 {
1158 }
1159 
1161 {
1162 }
1163 
1164 
1166 {
1167 }
1168 
1170 {
1171 }
1172 
1174 {
1175  //WARNING WARNING WARNING
1176  //The supplied pointer should have been deleted
1177  //before this call. Be careful not to use it!!!
1178 }
1179 
1181 {
1182 }
1183 
1185 {
1186  SvTreeListEntry* pParent = pEntry->pParent;
1187  DBG_ASSERT(pParent,"Model not consistent");
1188  if (pParent != m_rThis.pModel->pRootItem.get() && pParent->m_Children.size() == 1)
1189  {
1190  SvViewDataEntry* pViewData = m_DataTable.find( pParent )->second.get();
1191  pViewData->SetExpanded(false);
1192  }
1193  // preliminary
1194  m_nVisibleCount = 0;
1195  m_bVisPositionsValid = false;
1196 }
1197 
1199 {
1200  m_nVisibleCount = 0;
1201  m_bVisPositionsValid = false;
1202 }
1203 
1205 {
1206  DBG_ASSERT(pEntry,"Insert:No Entry");
1207  std::unique_ptr<SvViewDataEntry> pData(new SvViewDataEntry());
1208  m_rThis.InitViewData( pData.get(), pEntry );
1209  std::pair<SvDataTable::iterator, bool> aSuccess =
1210  m_DataTable.insert(std::make_pair(pEntry, std::move(pData)));
1211  DBG_ASSERT(aSuccess.second,"Entry already in View");
1212  if (m_nVisibleCount && m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1213  {
1214  m_nVisibleCount = 0;
1215  m_bVisPositionsValid = false;
1216  }
1217 }
1218 
1220 {
1221  if (m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1222  {
1223  m_nVisibleCount = 0;
1224  m_bVisPositionsValid = false;
1225  }
1226  // iterate over entry and its children
1227  SvTreeListEntry* pCurEntry = pEntry;
1228  sal_uInt16 nRefDepth = m_rThis.pModel->GetDepth( pCurEntry );
1229  while( pCurEntry )
1230  {
1231  DBG_ASSERT(m_DataTable.find(pCurEntry) != m_DataTable.end(),"Entry already in Table");
1232  std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry());
1233  m_rThis.InitViewData( pViewData.get(), pEntry );
1234  m_DataTable.insert(std::make_pair(pCurEntry, std::move(pViewData)));
1235  pCurEntry = m_rThis.pModel->Next( pCurEntry );
1236  if ( pCurEntry && m_rThis.pModel->GetDepth(pCurEntry) <= nRefDepth)
1237  pCurEntry = nullptr;
1238  }
1239 }
1240 
1242 {
1243  for (auto const& it : pParent->m_Children)
1244  {
1245  SvTreeListEntry& rEntry = *it;
1246  m_DataTable.erase(&rEntry);
1247  if (rEntry.HasChildren())
1248  RemoveViewData(&rEntry);
1249  }
1250 }
1251 
1252 
1254 {
1255  DBG_ASSERT(pEntry,"Remove:No Entry");
1256 
1257  SvViewDataEntry* pViewData = m_DataTable.find( pEntry )->second.get();
1258  sal_uLong nSelRemoved = 0;
1259  if ( pViewData->IsSelected() )
1260  nSelRemoved = 1 + m_rThis.pModel->GetChildSelectionCount(&m_rThis, pEntry);
1261  m_nSelectionCount -= nSelRemoved;
1262  sal_uLong nVisibleRemoved = 0;
1263  if (m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1264  nVisibleRemoved = 1 + m_rThis.pModel->GetVisibleChildCount(&m_rThis, pEntry);
1265  if( m_nVisibleCount )
1266  {
1267 #ifdef DBG_UTIL
1268  if (m_nVisibleCount < nVisibleRemoved)
1269  {
1270  OSL_FAIL("nVisibleRemoved bad");
1271  }
1272 #endif
1273  m_nVisibleCount -= nVisibleRemoved;
1274  }
1275  m_bVisPositionsValid = false;
1276 
1277  m_DataTable.erase(pEntry);
1278  RemoveViewData( pEntry );
1279 
1280  SvTreeListEntry* pCurEntry = pEntry->pParent;
1281  if (pCurEntry && pCurEntry != m_rThis.pModel->pRootItem.get() && pCurEntry->m_Children.size() == 1)
1282  {
1283  pViewData = m_DataTable.find(pCurEntry)->second.get();
1284  pViewData->SetExpanded(false);
1285  }
1286 }
1287 
1289 {
1290  m_rThis.Clear();
1291 }
1292 
1294  SvTreeListEntry* /*pEntry2*/, sal_uLong /*nPos*/ )
1295 {
1296  switch( nActionId )
1297  {
1299  m_pImpl->ActionInserted( pEntry1 );
1300  ModelHasInserted( pEntry1 );
1301  break;
1303  m_pImpl->ActionInsertedTree( pEntry1 );
1304  ModelHasInsertedTree( pEntry1 );
1305  break;
1307  ModelIsRemoving( pEntry1 );
1308  m_pImpl->ActionRemoving( pEntry1 );
1309  break;
1310  case SvListAction::REMOVED:
1311  ModelHasRemoved( pEntry1 );
1312  break;
1313  case SvListAction::MOVING:
1314  ModelIsMoving( pEntry1 );
1315  m_pImpl->ActionMoving( pEntry1 );
1316  break;
1317  case SvListAction::MOVED:
1318  m_pImpl->ActionMoved();
1319  ModelHasMoved( pEntry1 );
1320  break;
1322  m_pImpl->ActionClear();
1323  ModelHasCleared(); // sic! for compatibility reasons!
1324  break;
1325  case SvListAction::CLEARED:
1326  break;
1328  // no action for the base class
1329  ModelHasEntryInvalidated( pEntry1 );
1330  break;
1332  m_pImpl->m_bVisPositionsValid = false;
1333  break;
1335  break;
1336  default:
1337  OSL_FAIL("unknown ActionId");
1338  }
1339 }
1340 
1342 {
1343 }
1344 
1346 {
1347  DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1348  SvDataTable::const_iterator itr = m_pImpl->m_DataTable.find(pEntry);
1349  DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in Table");
1350  if (itr == m_pImpl->m_DataTable.end())
1351  return false;
1352  return itr->second->IsExpanded();
1353 }
1354 
1356 {
1357  DBG_ASSERT(pEntry,"IsAllExpanded:No Entry");
1358  if (!IsExpanded(pEntry))
1359  return false;
1360  const SvTreeListEntries& rChildren = pEntry->GetChildEntries();
1361  for (auto& rChild : rChildren)
1362  {
1363  if (rChild->HasChildren() || rChild->HasChildrenOnDemand())
1364  {
1365  if (!IsAllExpanded(rChild.get()))
1366  return false;
1367  }
1368  }
1369  return true;
1370 }
1371 
1373 {
1374  DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1375  SvDataTable::const_iterator itr = m_pImpl->m_DataTable.find(pEntry);
1376  if (itr == m_pImpl->m_DataTable.end())
1377  return false;
1378  return itr->second->IsSelected();
1379 }
1380 
1381 void SvListView::SetEntryFocus( SvTreeListEntry* pEntry, bool bFocus )
1382 {
1383  DBG_ASSERT(pEntry,"SetEntryFocus:No Entry");
1384  SvDataTable::iterator itr = m_pImpl->m_DataTable.find(pEntry);
1385  DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in Table");
1386  itr->second->SetFocus(bFocus);
1387 }
1388 
1390 {
1391  SvDataTable::const_iterator itr =
1392  m_pImpl->m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry));
1393  if (itr == m_pImpl->m_DataTable.end())
1394  return nullptr;
1395  return itr->second.get();
1396 }
1397 
1399 {
1400  SvDataTable::iterator itr = m_pImpl->m_DataTable.find( pEntry );
1401  DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in model or wrong view");
1402  return itr->second.get();
1403 }
1404 
1405 sal_Int32 SvTreeList::Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const
1406 {
1407  if( aCompareLink.IsSet())
1408  {
1409  SvSortData aSortData;
1410  aSortData.pLeft = pLeft;
1411  aSortData.pRight = pRight;
1412  return aCompareLink.Call( aSortData );
1413  }
1414  return 0;
1415 }
1416 
1418 {
1419  Broadcast( SvListAction::RESORTING );
1420  bAbsPositionsValid = false;
1421  ResortChildren( pRootItem.get() );
1422  Broadcast( SvListAction::RESORTED );
1423 }
1424 
1425 namespace {
1426 
1427 class SortComparator
1428 {
1429  SvTreeList& mrList;
1430 public:
1431 
1432  explicit SortComparator( SvTreeList& rList ) : mrList(rList) {}
1433 
1434  bool operator() (std::unique_ptr<SvTreeListEntry> const& rpLeft,
1435  std::unique_ptr<SvTreeListEntry> const& rpRight) const
1436  {
1437  int nCompare = mrList.Compare(rpLeft.get(), rpRight.get());
1438  if (nCompare != 0 && mrList.GetSortMode() == SortDescending)
1439  {
1440  if( nCompare < 0 )
1441  nCompare = 1;
1442  else
1443  nCompare = -1;
1444  }
1445  return nCompare < 0;
1446  }
1447 };
1448 
1449 }
1450 
1452 {
1453  DBG_ASSERT(pParent,"Parent not set");
1454 
1455  if (pParent->m_Children.empty())
1456  return;
1457 
1458  SortComparator aComp(*this);
1459  std::sort(pParent->m_Children.begin(), pParent->m_Children.end(), aComp);
1460 
1461  // Recursively sort child entries.
1462  for (auto const& it : pParent->m_Children)
1463  {
1464  SvTreeListEntry& r = *it;
1465  ResortChildren(&r);
1466  }
1467 
1468  SetListPositions(pParent->m_Children); // correct list position in target list
1469 }
1470 
1472  sal_uLong& rPos )
1473 {
1474  DBG_ASSERT(pEntry,"No Entry");
1475 
1476  if( eSortMode == SortNone )
1477  return;
1478 
1479  rPos = TREELIST_ENTRY_NOTFOUND;
1480  const SvTreeListEntries& rChildList = GetChildList(pParent);
1481 
1482  if (rChildList.empty())
1483  return;
1484 
1485  long i = 0;
1486  long j = rChildList.size()-1;
1487  long k;
1488  sal_Int32 nCompare = 1;
1489 
1490  do
1491  {
1492  k = (i+j)/2;
1493  const SvTreeListEntry* pTempEntry = rChildList[k].get();
1494  nCompare = Compare( pEntry, pTempEntry );
1495  if (nCompare != 0 && eSortMode == SortDescending)
1496  {
1497  if( nCompare < 0 )
1498  nCompare = 1;
1499  else
1500  nCompare = -1;
1501  }
1502  if( nCompare > 0 )
1503  i = k + 1;
1504  else
1505  j = k - 1;
1506  } while( (nCompare != 0) && (i <= j) );
1507 
1508  if( nCompare != 0 )
1509  {
1510  if (i > static_cast<long>(rChildList.size()-1)) // not found, end of list
1511  rPos = TREELIST_ENTRY_NOTFOUND;
1512  else
1513  rPos = i; // not found, middle of list
1514  }
1515  else
1516  rPos = k;
1517 }
1518 
1519 bool SvTreeList::HasChildren( const SvTreeListEntry* pEntry ) const
1520 {
1521  if ( !pEntry )
1522  pEntry = pRootItem.get();
1523 
1524  return !pEntry->m_Children.empty();
1525 }
1526 
1527 bool SvTreeList::HasParent( const SvTreeListEntry* pEntry ) const
1528 {
1529  return pEntry->pParent != pRootItem.get();
1530 }
1531 
1533 { if ( !pParent )
1534  pParent = pRootItem.get();
1535  SvTreeListEntry* pRet = nullptr;
1536  if (nPos < pParent->m_Children.size())
1537  pRet = pParent->m_Children[nPos].get();
1538  return pRet;
1539 }
1540 
1542 {
1543  SvTreeListEntry* pRet = nullptr;
1544  if (nEntryCount && nRootPos < pRootItem->m_Children.size())
1545  pRet = pRootItem->m_Children[nRootPos].get();
1546  return pRet;
1547 }
1548 
1550 {
1551  if ( !pParent )
1552  pParent = pRootItem.get();
1553  return pParent->m_Children;
1554 }
1555 
1557 {
1558  if ( !pParent )
1559  pParent = pRootItem.get();
1560  return pParent->m_Children;
1561 }
1562 
1564 {
1565  const SvTreeListEntry* pParent = pEntry->pParent;
1566  if (pParent == pRootItem.get())
1567  pParent = nullptr;
1568  return pParent;
1569 }
1570 
1572 {
1573  SvTreeListEntry* pParent = pEntry->pParent;
1574  if (pParent == pRootItem.get())
1575  pParent = nullptr;
1576  return pParent;
1577 }
1578 
1579 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvListView & m_rThis
Definition: treelist.cxx:34
void dispose()
Definition: treelist.cxx:1082
virtual void ModelHasEntryInvalidated(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1180
SvSortMode eSortMode
Definition: treelist.hxx:71
bool IsSelectable() const
bool HasChildren(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1519
void InvalidateEntry(SvTreeListEntry *)
Definition: treelist.cxx:1030
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:1471
std::unique_ptr< Impl > m_pImpl
Definition: treelist.hxx:212
virtual ~SvListView()
Definition: treelist.cxx:1087
const SvTreeListEntries & GetChildList(SvTreeListEntry *pParent) const
Definition: treelist.cxx:1549
Impl(SvListView &rThis)
Definition: treelist.cxx:42
sal_uIntPtr sal_uLong
sal_Int32 Compare(const SvTreeListEntry *pLeft, const SvTreeListEntry *pRight) const
Definition: treelist.cxx:1405
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:1025
std::pair< SvTreeListEntries::iterator, SvTreeListEntries::iterator > GetChildIterators(SvTreeListEntry *pParent)
Definition: treelist.cxx:1054
static VCL_DLLPRIVATE void SetListPositions(SvTreeListEntries &rEntries)
Invalidate the cached position data to have them re-generated before the next access.
Definition: treelist.cxx:1015
SvTreeListEntry * LastVisible(const SvListView *) const
Definition: treelist.cxx:709
View-dependent data for a tree list entry created in the virtual function SvTreeListBox::CreateViewDa...
std::unique_ptr< SvTreeListEntry > pRootItem
Definition: treelist.hxx:120
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:1381
void ActionInsertedTree(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1219
SvTreeListEntry * Next(SvTreeListEntry *pEntry, sal_uInt16 *pDepth=nullptr) const
Definition: treelist.cxx:467
friend class SvTreeList
Definition: treelist.hxx:210
const SvTreeListEntry * GetParent(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1563
SvTreeListEntries m_Children
virtual void ModelHasInsertedTree(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1156
SvTreeListEntry * PrevVisible(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:676
SvTreeListEntry * CloneEntry(SvTreeListEntry *pSource) const
Definition: treelist.cxx:356
SvTreeListEntry * GetRootLevelParent(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1038
sal_uLong GetVisibleCount(SvListView *) const
Definition: treelist.cxx:584
void ActionMoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1184
void Broadcast(SvListAction nActionId, SvTreeListEntry *pEntry1=nullptr, SvTreeListEntry *pEntry2=nullptr, sal_uLong nPos=0)
Definition: treelist.cxx:75
SvTreeListEntry * PrevSelected(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:794
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:1532
bool HasViewData() const
Definition: treelist.cxx:1095
void InvalidateChildrensListPositions()
VCL_DLLPRIVATE void SetAbsolutePositions()
Definition: treelist.cxx:859
virtual void InitViewData(SvViewDataEntry *, SvTreeListEntry *pEntry)
Definition: treelist.cxx:1341
SvTreeListEntry * NextSelected(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:785
sal_uLong GetAbsPos(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:847
#define DBG_ASSERT(sCon, aError)
SvTreeListEntry * Clone(SvTreeListEntry *pEntry, sal_uLong &nCloneCount) const
Definition: treelist.cxx:365
bool Remove(const SvTreeListEntry *pEntry)
Definition: treelist.cxx:937
void Clear()
Definition: treelist.cxx:1132
void Clone(SvTreeListEntry *pSource)
void Clear()
Definition: treelist.cxx:119
int i
std::unique_ptr< SvTreeList > pModel
Definition: treelist.hxx:216
bool IsSelected(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1372
sal_uLong GetEntryCount() const
Definition: treelist.hxx:140
void ActionInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1204
sal_uLong Copy(SvTreeListEntry *pSource, SvTreeListEntry *pTargetParent, sal_uLong nListPos)
Definition: treelist.cxx:270
virtual void ModelHasRemoved(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1173
SvTreeListEntry * Last() const
Definition: treelist.cxx:558
static sal_uLong GetRelPos(const SvTreeListEntry *pChild)
Definition: treelist.cxx:854
sal_uLong GetVisiblePos(const SvListView *, SvTreeListEntry const *pEntry) const
Definition: treelist.cxx:570
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:910
bool mbEnableInvalidate
Definition: treelist.hxx:75
const SvTreeListEntry * pRight
Definition: treelist.hxx:59
bool HasParent(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1527
SvTreeListEntry * FirstSelected(const SvListView *) const
Definition: treelist.cxx:761
bool IsExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1345
sal_uLong m_nVisibleCount
Definition: treelist.cxx:38
const SvViewDataEntry * GetViewData(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1389
void RemoveViewData(SvTreeListEntry *pParent)
Definition: treelist.cxx:1241
bool HasChildren() const
SvSortMode GetSortMode() const
Definition: treelist.hxx:202
sal_uLong m_nSelectionCount
Definition: treelist.cxx:39
bool IsAllExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1355
VCL_DLLPRIVATE void ResortChildren(SvTreeListEntry *pParent)
Definition: treelist.cxx:1451
void ActionRemoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1253
virtual void ModelIsRemoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1169
void ExpandListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:872
sal_uLong Insert(SvTreeListEntry *pEntry, SvTreeListEntry *pPar, sal_uLong nPos=TREELIST_APPEND)
Definition: treelist.cxx:813
void CollapseListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:891
void Resort()
Definition: treelist.cxx:1417
SvTreeListEntry * GetEntryAtVisPos(const SvListView *, sal_uLong nVisPos) const
Definition: treelist.cxx:1003
sal_uLong nListPos
SvTreeListEntry * First() const
Definition: treelist.cxx:459
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:615
virtual void ModelIsMoving(SvTreeListEntry *pSource)
Definition: treelist.cxx:1160
SvTreeListEntry * GetEntryAtAbsPos(sal_uLong nAbsPos) const
Definition: treelist.cxx:992
SvTreeListEntry * LastSelected(const SvListView *) const
Definition: treelist.cxx:804
virtual void ModelHasCleared()
Definition: treelist.cxx:1148
void InsertTree(SvTreeListEntry *pTree, SvTreeListEntry *pTargetParent, sal_uLong nListPos)
Definition: treelist.cxx:322
#define TREELIST_ENTRY_NOTFOUND
Link< SvTreeListEntry *, SvTreeListEntry * > aCloneLink
Definition: treelist.hxx:69
sal_uLong GetSelectionCount() const
Definition: treelist.cxx:1092
virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry *pEntry1, SvTreeListEntry *pEntry2, sal_uLong nPos)
Definition: treelist.cxx:1293
bool IsSelected() const
sal_Int32 nPos
virtual void ModelHasMoved(SvTreeListEntry *pSource)
Definition: treelist.cxx:1165
virtual void ModelHasInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1152
SvTreeListEntry * FirstChild(SvTreeListEntry *pParent) const
Definition: treelist.cxx:773
sal_uLong nEntryCount
Definition: treelist.hxx:67
SvTreeListEntry * pParent
std::vector< std::unique_ptr< SvTreeListEntry > > SvTreeListEntries
#define TREELIST_APPEND
const SvTreeListEntry * pLeft
Definition: treelist.hxx:58