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