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