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{
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
1028 : m_pImpl(new Impl(*this))
1029{
1030 pModel.reset(new SvTreeList(*this));
1031 m_pImpl->InitTable();
1032}
1033
1035{
1036 pModel.reset();
1037}
1038
1040{
1041 m_pImpl->m_DataTable.clear();
1042}
1043
1045{ return m_pImpl->m_nSelectionCount; }
1046
1048{ return m_pImpl->m_DataTable.size() > 1; } // There's always a ROOT
1049
1050
1052{
1053 DBG_ASSERT(m_rThis.pModel,"InitTable:No Model");
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
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
1101{
1102}
1103
1105{
1106}
1107
1109{
1110}
1111
1113{
1114}
1115
1116
1118{
1119}
1120
1122{
1123}
1124
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
1133{
1134}
1135
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
1151{
1152 m_nVisibleCount = 0;
1153 m_bVisPositionsValid = false;
1154}
1155
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
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
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
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
1241{
1242 m_rThis.Clear();
1243}
1244
1246 SvTreeListEntry* /*pEntry2*/, sal_uInt32 /*nPos*/ )
1247{
1248
1249 switch( nActionId )
1250 {
1252 m_pImpl->ActionInserted( pEntry1 );
1253 ModelHasInserted( pEntry1 );
1254 break;
1256 m_pImpl->ActionInsertedTree( pEntry1 );
1257 ModelHasInsertedTree( pEntry1 );
1258 break;
1260 ModelIsRemoving( pEntry1 );
1261 m_pImpl->ActionRemoving( pEntry1 );
1262 break;
1264 ModelHasRemoved( pEntry1 );
1265 break;
1267 ModelIsMoving( pEntry1 );
1268 m_pImpl->ActionMoving( pEntry1 );
1269 break;
1271 m_pImpl->ActionMoved();
1272 ModelHasMoved( pEntry1 );
1273 break;
1275 m_pImpl->ActionClear();
1276 ModelHasCleared(); // sic! for compatibility reasons!
1277 break;
1279 break;
1281 // no action for the base class
1282 ModelHasEntryInvalidated( pEntry1 );
1283 break;
1285 m_pImpl->m_bVisPositionsValid = false;
1286 break;
1288 break;
1289 default:
1290 OSL_FAIL("unknown ActionId");
1291 }
1292}
1293
1295{
1296}
1297
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
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
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
1334void 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
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
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
1358sal_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
1371{
1372 Broadcast( SvListAction::RESORTING );
1373 bAbsPositionsValid = false;
1374 ResortChildren( pRootItem.get() );
1375 Broadcast( SvListAction::RESORTED );
1376}
1377
1378namespace {
1379
1380class SortComparator
1381{
1382 SvTreeList& mrList;
1383public:
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
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
1425 sal_uInt32& rPos )
1426{
1427 DBG_ASSERT(pEntry,"No Entry");
1428
1429 if( eSortMode == SvSortMode::None )
1430 return;
1431
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
1465 else
1466 rPos = i; // not found, middle of list
1467 }
1468 else
1469 rPos = k;
1470}
1471
1472SvTreeListEntry* 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
1481SvTreeListEntry* 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
1490{
1491 if ( !pParent )
1492 pParent = pRootItem.get();
1493 return pParent->m_Children;
1494}
1495
1497{
1498 if ( !pParent )
1499 pParent = pRootItem.get();
1500 return pParent->m_Children;
1501}
1502
1504{
1505 const SvTreeListEntry* pParent = pEntry->pParent;
1506 if (pParent == pRootItem.get())
1507 pParent = nullptr;
1508 return pParent;
1509}
1510
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: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
bool SelectListEntry(SvTreeListEntry *pEntry, bool bSelect)
Definition: treelist.cxx:884
friend class SvTreeList
Definition: treelist.hxx:205
bool IsSelected(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1325
virtual void ModelHasInsertedTree(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1108
virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry *pEntry1, SvTreeListEntry *pEntry2, sal_uInt32 nPos)
Definition: treelist.cxx:1245
virtual void ModelHasRemoved(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1125
virtual void ModelHasCleared()
Definition: treelist.cxx:1100
void Clear()
Definition: treelist.cxx:1084
bool HasViewData() const
Definition: treelist.cxx:1047
virtual ~SvListView()
Definition: treelist.cxx:1039
void ExpandListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:846
std::unique_ptr< SvTreeList > pModel
Definition: treelist.hxx:211
void CollapseListEntry(SvTreeListEntry *pParent)
Definition: treelist.cxx:865
virtual void ModelIsRemoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1121
sal_uInt32 GetSelectionCount() const
Definition: treelist.cxx:1044
bool IsAllExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1308
virtual void ModelIsMoving(SvTreeListEntry *pSource)
Definition: treelist.cxx:1112
std::unique_ptr< Impl > m_pImpl
Definition: treelist.hxx:208
virtual void InitViewData(SvViewDataEntry *, SvTreeListEntry *pEntry)
Definition: treelist.cxx:1294
void dispose()
Definition: treelist.cxx:1034
virtual void ModelHasEntryInvalidated(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1132
virtual void ModelHasMoved(SvTreeListEntry *pSource)
Definition: treelist.cxx:1117
virtual void ModelHasInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1104
const SvViewDataEntry * GetViewData(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1342
bool IsExpanded(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1298
void SetEntryFocus(SvTreeListEntry *pEntry, bool bFocus)
Definition: treelist.cxx:1334
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:1404
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:1472
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:1370
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:197
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:1489
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:1503
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:1424
sal_uInt16 GetDepth(const SvTreeListEntry *pEntry) const
Definition: treelist.cxx:103
SvTreeListEntry * GetRootLevelParent(SvTreeListEntry *pEntry) const
Definition: treelist.cxx:1012
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:1358
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:1205
void RemoveViewData(SvTreeListEntry *pParent)
Definition: treelist.cxx:1193
SvListView & m_rThis
Definition: treelist.cxx:35
Impl(SvListView &rThis)
Definition: treelist.cxx:43
void ActionInserted(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1156
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:1171
void ActionMoving(SvTreeListEntry *pEntry)
Definition: treelist.cxx:1136
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