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
23#include <tools/debug.hxx>
24#include <osl/diagnose.h>
25
26#include <cassert>
27#include <memory>
28#include <unordered_map>
29
30
31typedef std::unordered_map<SvTreeListEntry*, std::unique_ptr<SvViewDataEntry>> SvDataTable;
32
34{
36
37 SvDataTable m_DataTable; // Mapping SvTreeListEntry -> ViewData
38
39 sal_uInt32 m_nVisibleCount;
42
43 explicit Impl(SvListView & rThis)
44 : m_rThis(rThis)
48 {}
49
50 void InitTable();
51 void RemoveViewData( SvTreeListEntry* pParent );
52
53 void ActionMoving(SvTreeListEntry* pEntry);
54 void ActionMoved();
55 void ActionInserted(SvTreeListEntry* pEntry);
57 void ActionRemoving(SvTreeListEntry* pEntry);
58 void ActionClear();
59};
60
61
63 mrOwnerListView(listView),
64 mbEnableInvalidate(true)
65{
66 nEntryCount = 0;
67 bAbsPositionsValid = false;
68 pRootItem.reset(new SvTreeListEntry);
70}
71
73{
74}
75
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
87bool 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
103sal_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
116{
117 return pEntry->pParent == pRootItem.get();
118}
119
121{
123 pRootItem->ClearChildren();
124 nEntryCount = 0;
126}
127
128bool 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
151namespace {
152
153class FindByPointer
154{
155 const SvTreeListEntry* mpEntry;
156public:
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
165sal_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
176sal_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
271sal_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
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
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
355}
356
358{
359 if( aCloneLink.IsSet() )
360 return aCloneLink.Call( pSource );
361 SvTreeListEntry* pEntry = new SvTreeListEntry;
362 pEntry->Clone(pSource);
363 return pEntry;
364}
365
366SvTreeListEntry* 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
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
397sal_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
417sal_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
438sal_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
461{
462 if ( nEntryCount )
463 return pRootItem->m_Children[0].get();
464 else
465 return nullptr;
466}
467
468SvTreeListEntry* 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
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
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
567sal_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
581sal_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.
612SvTreeListEntry* 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
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
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
711SvTreeListEntry* 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
734SvTreeListEntry* 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
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
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
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
787sal_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
818 return nPos; // pEntry->nListPos;
819}
820
821sal_uInt32 SvTreeList::GetAbsPos( const SvTreeListEntry* pEntry) const
822{
823 if ( !bAbsPositionsValid )
824 const_cast<SvTreeList*>(this)->SetAbsolutePositions();
825 return pEntry->nAbsPos;
826}
827
828sal_uInt32 SvTreeList::GetRelPos( const SvTreeListEntry* pChild )
829{
830 return pChild->GetChildListPos();
831}
832
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
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
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
884bool 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
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
967{
968 SvTreeListEntry* pEntry = First();
969 while ( nAbsPos && pEntry )
970 {
971 pEntry = Next( pEntry );
972 nAbsPos--;
973 }
974 return pEntry;
975}
976
977SvTreeListEntry* 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
990{
991 if (rEntries.empty())
992 return;
993
994 SvTreeListEntry& rFirst = *rEntries.front();
995 if (rFirst.pParent)
997}
998
1000{
1001 mbEnableInvalidate = bEnable;
1002}
1003
1005{
1006 if (!mbEnableInvalidate)
1007 return;
1008
1010}
1011
1013 : m_pImpl(new Impl(*this))
1014{
1015 pModel.reset(new SvTreeList(*this));
1016 m_pImpl->InitTable();
1017}
1018
1020{
1021 pModel.reset();
1022}
1023
1025{
1026 m_pImpl->m_DataTable.clear();
1027}
1028
1030{ return m_pImpl->m_nSelectionCount; }
1031
1033{ return m_pImpl->m_DataTable.size() > 1; } // There's always a ROOT
1034
1035
1037{
1038 DBG_ASSERT(m_rThis.pModel,"InitTable:No Model");
1040 "InitTable: Not cleared!");
1041
1042 if (!m_DataTable.empty())
1043 {
1044 DBG_ASSERT(m_DataTable.size() == 1, "InitTable: TableCount != 1");
1045 // Delete the view data allocated to the Clear in the root.
1046 // Attention: The model belonging to the root entry (and thus the entry
1047 // itself) might already be deleted.
1048 m_DataTable.clear();
1049 }
1050
1051 SvTreeListEntry* pEntry;
1052
1053 // insert root entry
1054 pEntry = m_rThis.pModel->pRootItem.get();
1055 std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry);
1056 pViewData->SetExpanded(true);
1057 m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1058 // now all the other entries
1059 pEntry = m_rThis.pModel->First();
1060 while( pEntry )
1061 {
1062 pViewData = std::make_unique<SvViewDataEntry>();
1063 m_rThis.InitViewData( pViewData.get(), pEntry );
1064 m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1065 pEntry = m_rThis.pModel->Next( pEntry );
1066 }
1067}
1068
1070{
1071 m_pImpl->m_DataTable.clear();
1072 m_pImpl->m_nSelectionCount = 0;
1073 m_pImpl->m_nVisibleCount = 0;
1074 m_pImpl->m_bVisPositionsValid = false;
1075 if( pModel )
1076 {
1077 // insert root entry
1078 SvTreeListEntry* pEntry = pModel->pRootItem.get();
1079 std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry);
1080 pViewData->SetExpanded(true);
1081 m_pImpl->m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData)));
1082 }
1083}
1084
1086{
1087}
1088
1090{
1091}
1092
1094{
1095}
1096
1098{
1099}
1100
1101
1103{
1104}
1105
1107{
1108}
1109
1111{
1112 //WARNING WARNING WARNING
1113 //The supplied pointer should have been deleted
1114 //before this call. Be careful not to use it!!!
1115}
1116
1118{
1119}
1120
1122{
1123 SvTreeListEntry* pParent = pEntry->pParent;
1124 DBG_ASSERT(pParent,"Model not consistent");
1125 if (pParent != m_rThis.pModel->pRootItem.get() && pParent->m_Children.size() == 1)
1126 {
1127 SvViewDataEntry* pViewData = m_DataTable.find( pParent )->second.get();
1128 pViewData->SetExpanded(false);
1129 }
1130 // preliminary
1131 m_nVisibleCount = 0;
1132 m_bVisPositionsValid = false;
1133}
1134
1136{
1137 m_nVisibleCount = 0;
1138 m_bVisPositionsValid = false;
1139}
1140
1142{
1143 DBG_ASSERT(pEntry,"Insert:No Entry");
1144 std::unique_ptr<SvViewDataEntry> pData(new SvViewDataEntry());
1145 m_rThis.InitViewData( pData.get(), pEntry );
1146 std::pair<SvDataTable::iterator, bool> aSuccess =
1147 m_DataTable.insert(std::make_pair(pEntry, std::move(pData)));
1148 DBG_ASSERT(aSuccess.second,"Entry already in View");
1149 if (m_nVisibleCount && m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1150 {
1151 m_nVisibleCount = 0;
1152 m_bVisPositionsValid = false;
1153 }
1154}
1155
1157{
1158 if (m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1159 {
1160 m_nVisibleCount = 0;
1161 m_bVisPositionsValid = false;
1162 }
1163 // iterate over entry and its children
1164 SvTreeListEntry* pCurEntry = pEntry;
1165 sal_uInt16 nRefDepth = m_rThis.pModel->GetDepth( pCurEntry );
1166 while( pCurEntry )
1167 {
1168 DBG_ASSERT(m_DataTable.find(pCurEntry) != m_DataTable.end(),"Entry already in Table");
1169 std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry());
1170 m_rThis.InitViewData( pViewData.get(), pEntry );
1171 m_DataTable.insert(std::make_pair(pCurEntry, std::move(pViewData)));
1172 pCurEntry = m_rThis.pModel->Next( pCurEntry );
1173 if ( pCurEntry && m_rThis.pModel->GetDepth(pCurEntry) <= nRefDepth)
1174 pCurEntry = nullptr;
1175 }
1176}
1177
1179{
1180 for (auto const& it : pParent->m_Children)
1181 {
1182 SvTreeListEntry& rEntry = *it;
1183 m_DataTable.erase(&rEntry);
1184 if (rEntry.HasChildren())
1185 RemoveViewData(&rEntry);
1186 }
1187}
1188
1189
1191{
1192 DBG_ASSERT(pEntry,"Remove:No Entry");
1193
1194 SvViewDataEntry* pViewData = m_DataTable.find( pEntry )->second.get();
1195 sal_uInt32 nSelRemoved = 0;
1196 if ( pViewData->IsSelected() )
1197 nSelRemoved = 1 + m_rThis.pModel->GetChildSelectionCount(&m_rThis, pEntry);
1198 m_nSelectionCount -= nSelRemoved;
1199 sal_uInt32 nVisibleRemoved = 0;
1200 if (m_rThis.pModel->IsEntryVisible(&m_rThis, pEntry))
1201 nVisibleRemoved = 1 + m_rThis.pModel->GetVisibleChildCount(&m_rThis, pEntry);
1202 if( m_nVisibleCount )
1203 {
1204#ifdef DBG_UTIL
1205 if (m_nVisibleCount < nVisibleRemoved)
1206 {
1207 OSL_FAIL("nVisibleRemoved bad");
1208 }
1209#endif
1210 m_nVisibleCount -= nVisibleRemoved;
1211 }
1212 m_bVisPositionsValid = false;
1213
1214 m_DataTable.erase(pEntry);
1215 RemoveViewData( pEntry );
1216
1217 SvTreeListEntry* pCurEntry = pEntry->pParent;
1218 if (pCurEntry && pCurEntry != m_rThis.pModel->pRootItem.get() && pCurEntry->m_Children.size() == 1)
1219 {
1220 pViewData = m_DataTable.find(pCurEntry)->second.get();
1221 pViewData->SetExpanded(false);
1222 }
1223}
1224
1226{
1227 m_rThis.Clear();
1228}
1229
1231 SvTreeListEntry* /*pEntry2*/, sal_uInt32 /*nPos*/ )
1232{
1233
1234 switch( nActionId )
1235 {
1237 m_pImpl->ActionInserted( pEntry1 );
1238 ModelHasInserted( pEntry1 );
1239 break;
1241 m_pImpl->ActionInsertedTree( pEntry1 );
1242 ModelHasInsertedTree( pEntry1 );
1243 break;
1245 ModelIsRemoving( pEntry1 );
1246 m_pImpl->ActionRemoving( pEntry1 );
1247 break;
1249 ModelHasRemoved( pEntry1 );
1250 break;
1252 ModelIsMoving( pEntry1 );
1253 m_pImpl->ActionMoving( pEntry1 );
1254 break;
1256 m_pImpl->ActionMoved();
1257 ModelHasMoved( pEntry1 );
1258 break;
1260 m_pImpl->ActionClear();
1261 ModelHasCleared(); // sic! for compatibility reasons!
1262 break;
1264 break;
1266 // no action for the base class
1267 ModelHasEntryInvalidated( pEntry1 );
1268 break;
1270 m_pImpl->m_bVisPositionsValid = false;
1271 break;
1273 break;
1274 default:
1275 OSL_FAIL("unknown ActionId");
1276 }
1277}
1278
1280{
1281}
1282
1284{
1285 DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1286 SvDataTable::const_iterator itr = m_pImpl->m_DataTable.find(pEntry);
1287 DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in Table");
1288 if (itr == m_pImpl->m_DataTable.end())
1289 return false;
1290 return itr->second->IsExpanded();
1291}
1292
1294{
1295 DBG_ASSERT(pEntry,"IsAllExpanded:No Entry");
1296 if (!IsExpanded(pEntry))
1297 return false;
1298 const SvTreeListEntries& rChildren = pEntry->GetChildEntries();
1299 for (auto& rChild : rChildren)
1300 {
1301 if (rChild->HasChildren() || rChild->HasChildrenOnDemand())
1302 {
1303 if (!IsAllExpanded(rChild.get()))
1304 return false;
1305 }
1306 }
1307 return true;
1308}
1309
1311{
1312 DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1313 SvDataTable::const_iterator itr = m_pImpl->m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry));
1314 if (itr == m_pImpl->m_DataTable.end())
1315 return false;
1316 return itr->second->IsSelected();
1317}
1318
1319void SvListView::SetEntryFocus( SvTreeListEntry* pEntry, bool bFocus )
1320{
1321 DBG_ASSERT(pEntry,"SetEntryFocus:No Entry");
1322 SvDataTable::iterator itr = m_pImpl->m_DataTable.find(pEntry);
1323 DBG_ASSERT(itr != m_pImpl->m_DataTable.end(),"Entry not in Table");
1324 itr->second->SetFocus(bFocus);
1325}
1326
1328{
1329 SvDataTable::const_iterator itr =
1330 m_pImpl->m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry));
1331 if (itr == m_pImpl->m_DataTable.end())
1332 return nullptr;
1333 return itr->second.get();
1334}
1335
1337{
1338 SvDataTable::iterator itr = m_pImpl->m_DataTable.find( pEntry );
1339 assert(itr != m_pImpl->m_DataTable.end() && "Entry not in model or wrong view");
1340 return itr->second.get();
1341}
1342
1343sal_Int32 SvTreeList::Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const
1344{
1345 if( aCompareLink.IsSet())
1346 {
1347 SvSortData aSortData;
1348 aSortData.pLeft = pLeft;
1349 aSortData.pRight = pRight;
1350 return aCompareLink.Call( aSortData );
1351 }
1352 return 0;
1353}
1354
1356{
1357 Broadcast( SvListAction::RESORTING );
1358 bAbsPositionsValid = false;
1359 ResortChildren( pRootItem.get() );
1360 Broadcast( SvListAction::RESORTED );
1361}
1362
1363namespace {
1364
1365class SortComparator
1366{
1367 SvTreeList& mrList;
1368public:
1369
1370 explicit SortComparator( SvTreeList& rList ) : mrList(rList) {}
1371
1372 bool operator() (std::unique_ptr<SvTreeListEntry> const& rpLeft,
1373 std::unique_ptr<SvTreeListEntry> const& rpRight) const
1374 {
1375 int nCompare = mrList.Compare(rpLeft.get(), rpRight.get());
1376 if (nCompare != 0 && mrList.GetSortMode() == SvSortMode::Descending)
1377 {
1378 if( nCompare < 0 )
1379 nCompare = 1;
1380 else
1381 nCompare = -1;
1382 }
1383 return nCompare < 0;
1384 }
1385};
1386
1387}
1388
1390{
1391 DBG_ASSERT(pParent,"Parent not set");
1392
1393 if (pParent->m_Children.empty())
1394 return;
1395
1396 SortComparator aComp(*this);
1397 std::sort(pParent->m_Children.begin(), pParent->m_Children.end(), aComp);
1398
1399 // Recursively sort child entries.
1400 for (auto const& it : pParent->m_Children)
1401 {
1402 SvTreeListEntry& r = *it;
1403 ResortChildren(&r);
1404 }
1405
1406 SetListPositions(pParent->m_Children); // correct list position in target list
1407}
1408
1410 sal_uInt32& rPos )
1411{
1412 DBG_ASSERT(pEntry,"No Entry");
1413
1414 if( eSortMode == SvSortMode::None )
1415 return;
1416
1418 const SvTreeListEntries& rChildList = GetChildList(pParent);
1419
1420 if (rChildList.empty())
1421 return;
1422
1423 tools::Long i = 0;
1424 tools::Long j = rChildList.size()-1;
1425 tools::Long k;
1426 sal_Int32 nCompare = 1;
1427
1428 do
1429 {
1430 k = (i+j)/2;
1431 const SvTreeListEntry* pTempEntry = rChildList[k].get();
1432 nCompare = Compare( pEntry, pTempEntry );
1433 if (nCompare != 0 && eSortMode == SvSortMode::Descending)
1434 {
1435 if( nCompare < 0 )
1436 nCompare = 1;
1437 else
1438 nCompare = -1;
1439 }
1440 if( nCompare > 0 )
1441 i = k + 1;
1442 else
1443 j = k - 1;
1444 } while( (nCompare != 0) && (i <= j) );
1445
1446 if( nCompare != 0 )
1447 {
1448 if (i > static_cast<tools::Long>(rChildList.size()-1)) // not found, end of list
1450 else
1451 rPos = i; // not found, middle of list
1452 }
1453 else
1454 rPos = k;
1455}
1456
1457SvTreeListEntry* SvTreeList::GetEntry( SvTreeListEntry* pParent, sal_uInt32 nPos ) const
1458{ if ( !pParent )
1459 pParent = pRootItem.get();
1460 SvTreeListEntry* pRet = nullptr;
1461 if (nPos < pParent->m_Children.size())
1462 pRet = pParent->m_Children[nPos].get();
1463 return pRet;
1464}
1465
1466SvTreeListEntry* SvTreeList::GetEntry( sal_uInt32 nRootPos ) const
1467{
1468 SvTreeListEntry* pRet = nullptr;
1469 if (nEntryCount && nRootPos < pRootItem->m_Children.size())
1470 pRet = pRootItem->m_Children[nRootPos].get();
1471 return pRet;
1472}
1473
1475{
1476 if ( !pParent )
1477 pParent = pRootItem.get();
1478 return pParent->m_Children;
1479}
1480
1482{
1483 if ( !pParent )
1484 pParent = pRootItem.get();
1485 return pParent->m_Children;
1486}
1487
1489{
1490 const SvTreeListEntry* pParent = pEntry->pParent;
1491 if (pParent == pRootItem.get())
1492 pParent = nullptr;
1493 return pParent;
1494}
1495
1497{
1498 SvTreeListEntry* pParent = pEntry->pParent;
1499 if (pParent == pRootItem.get())
1500 pParent = nullptr;
1501 return pParent;
1502}
1503
1504/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
bool SelectListEntry(SvTreeListEntry *pEntry, bool bSelect)
Definition: treelist.cxx:884
friend class SvTreeList
Definition: treelist.hxx:204
bool IsSelected(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1310
virtual void ModelHasInsertedTree(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1093
virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry *pEntry1, SvTreeListEntry *pEntry2, sal_uInt32 nPos)
Definition: treelist.cxx:1230
virtual void ModelHasRemoved(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1110
virtual void ModelHasCleared()
Definition: treelist.cxx:1085
void Clear()
Definition: treelist.cxx:1069
bool HasViewData() const
Definition: treelist.cxx:1032
virtual ~SvListView()
Definition: treelist.cxx:1024
void ExpandListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:846
std::unique_ptr< SvTreeList > pModel
Definition: treelist.hxx:210
void CollapseListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:865
virtual void ModelIsRemoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1106
sal_uInt32 GetSelectionCount() const
Definition: treelist.cxx:1029
bool IsAllExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1293
virtual void ModelIsMoving(SvTreeListEntry *pSource)
Definition: treelist.cxx:1097
std::unique_ptr< Impl > m_pImpl
Definition: treelist.hxx:207
virtual void InitViewData(SvViewDataEntry *, SvTreeListEntry *pEntry)
Definition: treelist.cxx:1279
void dispose()
Definition: treelist.cxx:1019
virtual void ModelHasEntryInvalidated(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1117
virtual void ModelHasMoved(SvTreeListEntry *pSource)
Definition: treelist.cxx:1102
virtual void ModelHasInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1089
const SvViewDataEntry * GetViewData(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1327
bool IsExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1283
void SetEntryFocus(SvTreeListEntry *pEntry, bool bFocus)
Definition: treelist.cxx:1319
void InvalidateChildrensListPositions()
SvTreeListEntries m_Children
void Clone(SvTreeListEntry *pSource)
bool HasChildren() const
SvTreeListEntries & GetChildEntries()
bool HasChildListPos() const
sal_uInt32 nAbsPos
SvTreeListEntry * pParent
sal_uInt32 nListPos
sal_uInt32 GetChildListPos() const
SvTreeListEntry * NextSelected(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:778
sal_uInt32 GetVisibleChildCount(const SvListView *, SvTreeListEntry *pParent) const
Definition: treelist.cxx:417
sal_uInt32 Copy(SvTreeListEntry *pSource, SvTreeListEntry *pTargetParent, sal_uInt32 nListPos)
Definition: treelist.cxx:271
SvTreeListEntry * Prev(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:526
VCL_DLLPRIVATE void ResortChildren(SvTreeListEntry *pParent)
Definition: treelist.cxx:1389
SvTreeList()=delete
sal_uInt32 GetVisiblePos(const SvListView *, SvTreeListEntry const *pEntry) const
Definition: treelist.cxx:567
sal_uInt32 GetVisibleCount(SvListView *) const
Definition: treelist.cxx:581
void Move(SvTreeListEntry *pSource, SvTreeListEntry *pTarget)
Definition: treelist.cxx:304
Link< SvTreeListEntry *, SvTreeListEntry * > aCloneLink
Definition: treelist.hxx:71
SvTreeListEntry * Last() const
Definition: treelist.cxx:555
VCL_DLLPRIVATE void CloneChildren(SvTreeListEntries &rDst, sal_uInt32 &rCloneCount, SvTreeListEntries &rSrc, SvTreeListEntry &rNewParent) const
Definition: treelist.cxx:377
sal_uInt32 GetAbsPos(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:821
VCL_DLLPRIVATE void SetAbsolutePositions()
Definition: treelist.cxx:833
SvTreeListEntry * CloneEntry(SvTreeListEntry *pSource) const
Definition: treelist.cxx:357
sal_uInt32 GetEntryCount() const
Definition: treelist.hxx:141
SvTreeListEntry * LastVisible(const SvListView *) const
Definition: treelist.cxx:702
SvTreeListEntry * GetEntry(SvTreeListEntry *pParent, sal_uInt32 nPos) const
Definition: treelist.cxx:1457
SvListView & mrOwnerListView
Definition: treelist.hxx:68
std::unique_ptr< SvTreeListEntry > pRootItem
Definition: treelist.hxx:120
SvTreeListEntry * GetEntryAtAbsPos(sal_uInt32 nAbsPos) const
Definition: treelist.cxx:966
SvTreeListEntry * Next(SvTreeListEntry *pEntry, sal_uInt16 *pDepth=nullptr) const
Definition: treelist.cxx:468
void Resort()
Definition: treelist.cxx:1355
bool IsChild(const SvTreeListEntry *pParent, const SvTreeListEntry *pChild) const
Definition: treelist.cxx:128
SvTreeListEntry * Clone(SvTreeListEntry *pEntry, sal_uInt32 &nCloneCount) const
Definition: treelist.cxx:366
static sal_uInt32 GetRelPos(const SvTreeListEntry *pChild)
Definition: treelist.cxx:828
SvTreeListEntry * NextVisible(const SvListView *, SvTreeListEntry *pEntry, sal_uInt16 *pDepth=nullptr) const
Definition: treelist.cxx:612
sal_uInt32 Insert(SvTreeListEntry *pEntry, SvTreeListEntry *pPar, sal_uInt32 nPos=TREELIST_APPEND)
Definition: treelist.cxx:787
bool bAbsPositionsValid
Definition: treelist.hxx:75
void Clear()
Definition: treelist.cxx:120
SvTreeListEntry * First() const
Definition: treelist.cxx:460
SvSortMode GetSortMode() const
Definition: treelist.hxx:196
SvTreeListEntry * GetEntryAtVisPos(const SvListView *, sal_uInt32 nVisPos) const
Definition: treelist.cxx:977
sal_uInt32 GetChildSelectionCount(const SvListView *, SvTreeListEntry *pParent) const
Definition: treelist.cxx:438
SvTreeListEntry * FirstSelected(const SvListView *) const
Definition: treelist.cxx:754
bool IsAtRootDepth(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:115
sal_uInt32 nEntryCount
Definition: treelist.hxx:69
const SvTreeListEntries & GetChildList(SvTreeListEntry *pParent) const
Definition: treelist.cxx:1474
bool IsEntryVisible(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:87
SvSortMode eSortMode
Definition: treelist.hxx:73
bool Remove(const SvTreeListEntry *pEntry)
Definition: treelist.cxx:911
const SvTreeListEntry * GetParent(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1488
sal_uInt32 GetChildCount(const SvTreeListEntry *pParent) const
Definition: treelist.cxx:397
void InsertTree(SvTreeListEntry *pTree, SvTreeListEntry *pTargetParent, sal_uInt32 nListPos)
Definition: treelist.cxx:323
SvTreeListEntry * FirstChild(SvTreeListEntry *pParent) const
Definition: treelist.cxx:766
void EnableInvalidate(bool bEnable)
Definition: treelist.cxx:999
void Broadcast(SvListAction nActionId, SvTreeListEntry *pEntry1=nullptr, SvTreeListEntry *pEntry2=nullptr, sal_uInt32 nPos=0)
Definition: treelist.cxx:76
VCL_DLLPRIVATE void GetInsertionPos(SvTreeListEntry const *pEntry, SvTreeListEntry *pParent, sal_uInt32 &rPos)
Definition: treelist.cxx:1409
sal_uInt16 GetDepth(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:103
void InvalidateEntry(SvTreeListEntry *)
Definition: treelist.cxx:1004
bool mbEnableInvalidate
Definition: treelist.hxx:77
static VCL_DLLPRIVATE void SetListPositions(SvTreeListEntries &rEntries)
Invalidate the cached position data to have them re-generated before the next access.
Definition: treelist.cxx:989
SvTreeListEntry * PrevVisible(const SvListView *, SvTreeListEntry *pEntry) const
Definition: treelist.cxx:673
sal_Int32 Compare(const SvTreeListEntry *pLeft, const SvTreeListEntry *pRight) const
Definition: treelist.cxx:1343
View-dependent data for a tree list entry created in the virtual function SvTreeListBox::CreateViewDa...
void SetSelected(bool bSelected)
void SetExpanded(bool bExpanded)
bool IsSelectable() const
sal_uInt32 nVisPos
bool IsSelected() const
#define TREELIST_ENTRY_NOTFOUND
#define TREELIST_APPEND
int nCount
#define DBG_ASSERT(sCon, aError)
void * p
sal_uInt16 nPos
std::unique_ptr< sal_Int32[]> pData
int i
long Long
SvDataTable m_DataTable
Definition: treelist.cxx:37
void ActionRemoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1190
void RemoveViewData(SvTreeListEntry *pParent)
Definition: treelist.cxx:1178
SvListView & m_rThis
Definition: treelist.cxx:35
Impl(SvListView &rThis)
Definition: treelist.cxx:43
void ActionInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1141
sal_uInt32 m_nVisibleCount
Definition: treelist.cxx:39
bool m_bVisPositionsValid
Definition: treelist.cxx:41
sal_uInt32 m_nSelectionCount
Definition: treelist.cxx:40
void ActionInsertedTree(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1156
void ActionMoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1121
const SvTreeListEntry * pLeft
Definition: treelist.hxx:60
const SvTreeListEntry * pRight
Definition: treelist.hxx:61
std::unordered_map< SvTreeListEntry *, std::unique_ptr< SvViewDataEntry > > SvDataTable
Definition: treelist.cxx:31
SvListAction
Definition: treelist.hxx:35
std::vector< std::unique_ptr< SvTreeListEntry > > SvTreeListEntries