GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / contnr / treelist.cxx
blob3ef468d3f39be30aca3ebf0eacc45735eda99753
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "svtools/treelist.hxx"
21 #include "svtools/treelistentry.hxx"
22 #include "svtools/viewdataentry.hxx"
23 #include "osl/diagnose.h"
25 #include <stdio.h>
27 SvTreeList::SvTreeList()
29 nEntryCount = 0;
30 bAbsPositionsValid = sal_False;
31 nRefCount = 1;
32 pRootItem = new SvTreeListEntry;
33 eSortMode = SortNone;
36 SvTreeList::~SvTreeList()
38 Clear();
39 delete pRootItem;
40 #ifdef DBG_UTIL
41 pRootItem = 0;
42 #endif
45 void SvTreeList::Broadcast(
46 sal_uInt16 nActionId,
47 SvTreeListEntry* pEntry1,
48 SvTreeListEntry* pEntry2,
49 sal_uLong nPos
50 ) {
51 sal_uLong nViewCount = aViewList.size();
52 for( sal_uLong nCurView = 0; nCurView < nViewCount; nCurView++ )
54 SvListView* pView = aViewList[ nCurView ];
55 if( pView )
56 pView->ModelNotification( nActionId, pEntry1, pEntry2, nPos );
60 void SvTreeList::InsertView( SvListView* pView )
62 for ( sal_uLong i = 0, n = aViewList.size(); i < n; ++i ) {
63 if ( aViewList[ i ] == pView ) {
64 return;
67 aViewList.push_back( pView );
68 nRefCount++;
71 void SvTreeList::RemoveView( SvListView* pView )
73 for ( ListViewsType::iterator it = aViewList.begin(); it != aViewList.end(); ++it )
75 if ( *it == pView )
77 aViewList.erase( it );
78 --nRefCount;
79 break;
85 // an entry is visible if all parents are expanded
86 sal_Bool SvTreeList::IsEntryVisible( const SvListView* pView, SvTreeListEntry* pEntry ) const
88 DBG_ASSERT(pView&&pEntry,"IsVisible:Invalid Params");
89 sal_Bool bRetVal=sal_False;
92 if ( pEntry == pRootItem )
94 bRetVal=sal_True;
95 break;
97 pEntry = pEntry->pParent;
98 } while( pView->IsExpanded( pEntry ) );
99 return bRetVal;
102 sal_uInt16 SvTreeList::GetDepth( const SvTreeListEntry* pEntry ) const
104 DBG_ASSERT(pEntry&&pEntry!=pRootItem,"GetDepth:Bad Entry");
105 sal_uInt16 nDepth = 0;
106 while( pEntry->pParent != pRootItem )
108 nDepth++;
109 pEntry = pEntry->pParent;
111 return nDepth;
114 bool SvTreeList::IsAtRootDepth( const SvTreeListEntry* pEntry ) const
116 return pEntry->pParent == pRootItem;
119 void SvTreeList::Clear()
121 Broadcast( LISTACTION_CLEARING );
122 pRootItem->ClearChildren();
123 nEntryCount = 0;
124 Broadcast( LISTACTION_CLEARED );
127 bool SvTreeList::IsChild(const SvTreeListEntry* pParent, const SvTreeListEntry* pChild) const
129 if ( !pParent )
130 pParent = pRootItem;
132 if (pParent->maChildren.empty())
133 return false;
135 SvTreeListEntries::const_iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
136 for (; it != itEnd; ++it)
138 const SvTreeListEntry* pThis = &(*it);
139 if (pThis == pChild)
140 return true;
141 else
143 bool bIsChild = IsChild(pThis, pChild);
144 if (bIsChild)
145 return true;
148 return false;
151 namespace {
153 class FindByPointer : std::unary_function<SvTreeListEntry, bool>
155 const SvTreeListEntry* mpEntry;
156 public:
157 FindByPointer(const SvTreeListEntry* p) : mpEntry(p) {}
159 bool operator() (const SvTreeListEntry& rEntry) const
161 return mpEntry == &rEntry;
165 sal_uLong findEntryPosition(const SvTreeListEntries& rDst, const SvTreeListEntry* pEntry)
167 SvTreeListEntries::const_iterator itPos = std::find_if(rDst.begin(), rDst.end(), FindByPointer(pEntry));
168 if (itPos == rDst.end())
169 return static_cast<sal_uLong>(~0);
171 return static_cast<sal_uLong>(std::distance(rDst.begin(), itPos));
176 sal_uLong SvTreeList::Move(SvTreeListEntry* pSrcEntry,SvTreeListEntry* pTargetParent,sal_uLong nListPos)
178 // pDest may be 0!
179 DBG_ASSERT(pSrcEntry,"Entry?");
180 if ( !pTargetParent )
181 pTargetParent = pRootItem;
182 DBG_ASSERT(pSrcEntry!=pTargetParent,"Move:Source=Target");
184 Broadcast( LISTACTION_MOVING, pSrcEntry, pTargetParent, nListPos );
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();
191 bAbsPositionsValid = false;
193 SvTreeListEntries& rDst = pTargetParent->maChildren;
194 SvTreeListEntries& rSrc = pSrcEntry->pParent->maChildren;
196 bool bSameParent = pTargetParent == pSrcEntry->pParent;
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)
202 const SvTreeListEntry* p = &(*itSrcPos);
203 if (p == pSrcEntry)
204 // Found
205 break;
208 if (itSrcPos == itEnd)
210 OSL_FAIL("Source entry not found! This should never happen.");
211 return pSrcEntry->GetChildListPos();
214 if (bSameParent)
216 // Moving within the same parent.
218 size_t nSrcPos = std::distance(rSrc.begin(), itSrcPos);
219 if (nSrcPos == nListPos)
220 // Nothing to move here.
221 return pSrcEntry->GetChildListPos();
223 if (nSrcPos < nListPos)
224 // Destination position shifts left after removing the original.
225 --nListPos;
227 // Release the original.
228 SvTreeListEntries::auto_type p = rSrc.release(itSrcPos);
229 // Determine the insertion position.
230 SvTreeListEntries::iterator itDstPos = rSrc.end();
231 if (nListPos < rSrc.size())
233 itDstPos = rSrc.begin();
234 std::advance(itDstPos, nListPos);
236 rSrc.insert(itDstPos, p.release());
238 else
240 // Moving from one parent to another.
241 SvTreeListEntries::iterator itDstPos = rDst.end();
242 if (nListPos < rDst.size())
244 itDstPos = rDst.begin();
245 std::advance(itDstPos, nListPos);
247 SvTreeListEntries::auto_type p = rSrc.release(itSrcPos);
248 rDst.insert(itDstPos, p.release());
251 // move parent umsetzen (do this only now, because we need the parent for
252 // deleting the old child list!)
253 pSrcEntry->pParent = pTargetParent;
255 // correct list position in target list
256 SetListPositions(rDst);
257 if (!bSameParent)
258 SetListPositions(rSrc);
260 sal_uLong nRetVal = findEntryPosition(rDst, pSrcEntry);
261 OSL_ENSURE(nRetVal == pSrcEntry->GetChildListPos(), "ListPos not valid");
262 Broadcast( LISTACTION_MOVED,pSrcEntry,pTargetParent,nRetVal);
263 return nRetVal;
266 sal_uLong SvTreeList::Copy(SvTreeListEntry* pSrcEntry,SvTreeListEntry* pTargetParent,sal_uLong nListPos)
268 // pDest may be 0!
269 DBG_ASSERT(pSrcEntry,"Entry?");
270 if ( !pTargetParent )
271 pTargetParent = pRootItem;
273 bAbsPositionsValid = sal_False;
275 sal_uLong nCloneCount = 0;
276 SvTreeListEntry* pClonedEntry = Clone( pSrcEntry, nCloneCount );
277 nEntryCount += nCloneCount;
279 SvTreeListEntries& rDst = pTargetParent->maChildren;
281 pClonedEntry->pParent = pTargetParent; // move parent
283 if (nListPos < rDst.size())
285 SvTreeListEntries::iterator itPos = rDst.begin(); // insertion position.
286 std::advance(itPos, nListPos);
287 rDst.insert(itPos, pClonedEntry);
289 else
290 rDst.push_back(pClonedEntry);
292 SetListPositions(rDst); // correct list position in target list
294 Broadcast( LISTACTION_INSERTED_TREE, pClonedEntry );
295 sal_uLong nRetVal = findEntryPosition(rDst, pClonedEntry);
296 return nRetVal;
299 void SvTreeList::Move( SvTreeListEntry* pSrcEntry, SvTreeListEntry* pDstEntry )
301 SvTreeListEntry* pParent;
302 sal_uLong nPos;
304 if ( !pDstEntry )
306 pParent = pRootItem;
307 nPos = 0UL;
309 else
311 pParent = pDstEntry->pParent;
312 nPos = pDstEntry->GetChildListPos();
313 nPos++; // (On screen:) insert _below_ pDstEntry
315 Move( pSrcEntry, pParent, nPos );
318 void SvTreeList::InsertTree(SvTreeListEntry* pSrcEntry,
319 SvTreeListEntry* pTargetParent,sal_uLong nListPos)
321 DBG_ASSERT(pSrcEntry,"InsertTree:Entry?");
322 if ( !pSrcEntry )
323 return;
325 if ( !pTargetParent )
326 pTargetParent = pRootItem;
328 // take sorting into account
329 GetInsertionPos( pSrcEntry, pTargetParent, nListPos );
331 bAbsPositionsValid = false;
333 pSrcEntry->pParent = pTargetParent; // move parent
334 SvTreeListEntries& rDst = pTargetParent->maChildren;
336 if (nListPos < rDst.size())
338 SvTreeListEntries::iterator itPos = rDst.begin();
339 std::advance(itPos, nListPos);
340 rDst.insert(itPos, pSrcEntry);
342 else
343 rDst.push_back(pSrcEntry);
345 SetListPositions(rDst); // correct list position in target list
346 nEntryCount += GetChildCount( pSrcEntry );
347 nEntryCount++; // the parent is new, too
349 Broadcast(LISTACTION_INSERTED_TREE, pSrcEntry );
352 SvTreeListEntry* SvTreeList::CloneEntry( SvTreeListEntry* pSource ) const
354 if( aCloneLink.IsSet() )
355 return (SvTreeListEntry*)aCloneLink.Call( pSource );
356 SvTreeListEntry* pEntry = CreateEntry();
357 pSource->Clone( pEntry );
358 return pSource;
361 SvTreeListEntry* SvTreeList::CreateEntry() const
363 return new SvTreeListEntry;
366 SvTreeListEntry* SvTreeList::Clone( SvTreeListEntry* pEntry, sal_uLong& nCloneCount ) const
368 SvTreeListEntry* pClonedEntry = CloneEntry( pEntry );
369 nCloneCount = 1;
370 if (!pEntry->maChildren.empty())
371 // Clone the child entries.
372 CloneChildren(pClonedEntry->maChildren, nCloneCount, pEntry->maChildren, pClonedEntry);
374 return pClonedEntry;
377 void SvTreeList::CloneChildren(
378 SvTreeListEntries& rDst, sal_uLong& rCloneCount, SvTreeListEntries& rSrc, SvTreeListEntry* pNewParent) const
380 SvTreeListEntries aClone;
381 SvTreeListEntries::iterator it = rSrc.begin(), itEnd = rSrc.end();
382 for (; it != itEnd; ++it)
384 SvTreeListEntry& rEntry = *it;
385 SvTreeListEntry* pNewEntry = CloneEntry(&rEntry);
386 ++rCloneCount;
387 pNewEntry->pParent = pNewParent;
388 if (!rEntry.maChildren.empty())
389 // Clone entries recursively.
390 CloneChildren(pNewEntry->maChildren, rCloneCount, rEntry.maChildren, pNewEntry);
392 aClone.push_back(pNewEntry);
395 rDst.swap(aClone);
398 sal_uLong SvTreeList::GetChildCount( const SvTreeListEntry* pParent ) const
400 if ( !pParent )
401 return GetEntryCount();
403 if (!pParent || pParent->maChildren.empty())
404 return 0;
406 sal_uLong nCount = 0;
407 sal_uInt16 nRefDepth = GetDepth( pParent );
408 sal_uInt16 nActDepth = nRefDepth;
411 pParent = Next(const_cast<SvTreeListEntry*>(pParent), &nActDepth);
412 nCount++;
413 } while( pParent && nRefDepth < nActDepth );
414 nCount--;
415 return nCount;
418 sal_uLong SvTreeList::GetVisibleChildCount(const SvListView* pView, SvTreeListEntry* pParent) const
420 DBG_ASSERT(pView,"GetVisChildCount:No View");
421 if ( !pParent )
422 pParent = pRootItem;
424 if (!pParent || !pView->IsExpanded(pParent) || pParent->maChildren.empty())
425 return 0;
427 sal_uLong nCount = 0;
428 sal_uInt16 nRefDepth = GetDepth( pParent );
429 sal_uInt16 nActDepth = nRefDepth;
432 pParent = NextVisible( pView, pParent, &nActDepth );
433 nCount++;
434 } while( pParent && nRefDepth < nActDepth );
435 nCount--;
436 return nCount;
439 sal_uLong SvTreeList::GetChildSelectionCount(const SvListView* pView,SvTreeListEntry* pParent) const
441 DBG_ASSERT(pView,"GetChildSelCount:No View");
442 if ( !pParent )
443 pParent = pRootItem;
445 if (!pParent || pParent->maChildren.empty())
446 return 0;
448 sal_uLong nCount = 0;
449 sal_uInt16 nRefDepth = GetDepth( pParent );
450 sal_uInt16 nActDepth = nRefDepth;
453 pParent = Next( pParent, &nActDepth );
454 if( pParent && pView->IsSelected( pParent ) && nRefDepth < nActDepth)
455 nCount++;
456 } while( pParent && nRefDepth < nActDepth );
457 // nCount--;
458 return nCount;
461 SvTreeListEntry* SvTreeList::First() const
463 if ( nEntryCount )
464 return &pRootItem->maChildren[0];
465 else
466 return 0;
469 SvTreeListEntry* SvTreeList::Next( SvTreeListEntry* pActEntry, sal_uInt16* pDepth ) const
471 DBG_ASSERT( pActEntry && pActEntry->pParent, "SvTreeList::Next: invalid entry/parent!" );
472 if ( !pActEntry || !pActEntry->pParent )
473 return NULL;
475 sal_uInt16 nDepth = 0;
476 bool bWithDepth = false;
477 if ( pDepth )
479 nDepth = *pDepth;
480 bWithDepth = true;
483 // Get the list where the current entry belongs to (from its parent).
484 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
485 sal_uLong nActualPos = pActEntry->GetChildListPos();
487 if (!pActEntry->maChildren.empty())
489 // The current entry has children. Get its first child entry.
490 nDepth++;
491 pActEntry = &pActEntry->maChildren[0];
492 if ( bWithDepth )
493 *pDepth = nDepth;
494 return pActEntry;
497 if (pActualList->size() > (nActualPos+1))
499 // Get the next sibling of the current entry.
500 pActEntry = &(*pActualList)[nActualPos+1];
501 if ( bWithDepth )
502 *pDepth = nDepth;
503 return pActEntry;
506 // Move up level(s) until we find the level where the next sibling exists.
507 SvTreeListEntry* pParent = pActEntry->pParent;
508 nDepth--;
509 while( pParent != pRootItem && pParent != 0 )
511 DBG_ASSERT(pParent!=0,"TreeData corrupt!");
512 pActualList = &pParent->pParent->maChildren;
513 nActualPos = pParent->GetChildListPos();
514 if (pActualList->size() > (nActualPos+1))
516 pActEntry = &(*pActualList)[nActualPos+1];
517 if ( bWithDepth )
518 *pDepth = nDepth;
519 return pActEntry;
521 pParent = pParent->pParent;
522 nDepth--;
524 return 0;
527 SvTreeListEntry* SvTreeList::Prev( SvTreeListEntry* pActEntry, sal_uInt16* pDepth ) const
529 DBG_ASSERT(pActEntry!=0,"Entry?");
531 sal_uInt16 nDepth = 0;
532 int bWithDepth = sal_False;
533 if ( pDepth )
535 nDepth = *pDepth;
536 bWithDepth = sal_True;
539 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
540 sal_uLong nActualPos = pActEntry->GetChildListPos();
542 if ( nActualPos > 0 )
544 pActEntry = &(*pActualList)[nActualPos-1];
545 while (!pActEntry->maChildren.empty())
547 pActualList = &pActEntry->maChildren;
548 nDepth++;
549 pActEntry = &pActualList->back();
551 if ( bWithDepth )
552 *pDepth = nDepth;
553 return pActEntry;
555 if ( pActEntry->pParent == pRootItem )
556 return 0;
558 pActEntry = pActEntry->pParent;
560 if ( pActEntry )
562 nDepth--;
563 if ( bWithDepth )
564 *pDepth = nDepth;
565 return pActEntry;
567 return 0;
570 SvTreeListEntry* SvTreeList::Last() const
572 SvTreeListEntries* pActList = &pRootItem->maChildren;
573 SvTreeListEntry* pEntry = NULL;
574 while (!pActList->empty())
576 pEntry = &pActList->back();
577 pActList = &pEntry->maChildren;
579 return pEntry;
582 sal_uLong SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry* pEntry ) const
584 DBG_ASSERT(pView&&pEntry,"View/Entry?");
586 if ( !pView->bVisPositionsValid )
588 // to make GetVisibleCount refresh the positions
589 ((SvListView*)pView)->nVisibleCount = 0;
590 GetVisibleCount( const_cast<SvListView*>(pView) );
592 const SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
593 return pViewData->nVisPos;
596 sal_uLong SvTreeList::GetVisibleCount( SvListView* pView ) const
598 DBG_ASSERT(pView,"GetVisCount:No View");
599 if( !pView->HasViewData() )
600 return 0;
601 if ( pView->nVisibleCount )
602 return pView->nVisibleCount;
604 sal_uLong nPos = 0;
605 SvTreeListEntry* pEntry = First(); // first entry is always visible
606 while ( pEntry )
608 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
609 pViewData->nVisPos = nPos;
610 nPos++;
611 pEntry = NextVisible( pView, pEntry );
613 #ifdef DBG_UTIL
614 if( nPos > 10000000 )
616 OSL_FAIL("nVisibleCount bad");
618 #endif
619 ((SvListView*)pView)->nVisibleCount = nPos;
620 ((SvListView*)pView)->bVisPositionsValid = sal_True;
621 return nPos;
625 // For performance reasons, this function assumes that the passed entry is
626 // already visible.
627 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pActEntry,sal_uInt16* pActDepth) const
629 DBG_ASSERT(pView,"NextVisible:No View");
630 if ( !pActEntry )
631 return 0;
633 sal_uInt16 nDepth = 0;
634 int bWithDepth = sal_False;
635 if ( pActDepth )
637 nDepth = *pActDepth;
638 bWithDepth = sal_True;
641 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
642 sal_uLong nActualPos = pActEntry->GetChildListPos();
644 if ( pView->IsExpanded(pActEntry) )
646 OSL_ENSURE(!pActEntry->maChildren.empty(), "Pass entry is supposed to have child entries.");
648 nDepth++;
649 pActEntry = &pActEntry->maChildren[0];
650 if ( bWithDepth )
651 *pActDepth = nDepth;
652 return pActEntry;
655 nActualPos++;
656 if ( pActualList->size() > nActualPos )
658 pActEntry = &(*pActualList)[nActualPos];
659 if ( bWithDepth )
660 *pActDepth = nDepth;
661 return pActEntry;
664 SvTreeListEntry* pParent = pActEntry->pParent;
665 nDepth--;
666 while( pParent != pRootItem )
668 pActualList = &pParent->pParent->maChildren;
669 nActualPos = pParent->GetChildListPos();
670 nActualPos++;
671 if ( pActualList->size() > nActualPos )
673 pActEntry = &(*pActualList)[nActualPos];
674 if ( bWithDepth )
675 *pActDepth = nDepth;
676 return pActEntry;
678 pParent = pParent->pParent;
679 nDepth--;
681 return 0;
685 // For performance reasons, this function assumes that the passed entry is
686 // already visible.
688 SvTreeListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvTreeListEntry* pActEntry, sal_uInt16* pActDepth) const
690 DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
692 sal_uInt16 nDepth = 0;
693 int bWithDepth = sal_False;
694 if ( pActDepth )
696 nDepth = *pActDepth;
697 bWithDepth = sal_True;
700 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
701 sal_uLong nActualPos = pActEntry->GetChildListPos();
703 if ( nActualPos > 0 )
705 pActEntry = &(*pActualList)[nActualPos-1];
706 while( pView->IsExpanded(pActEntry) )
708 pActualList = &pActEntry->maChildren;
709 nDepth++;
710 pActEntry = &pActualList->back();
712 if ( bWithDepth )
713 *pActDepth = nDepth;
714 return pActEntry;
717 if ( pActEntry->pParent == pRootItem )
718 return 0;
720 pActEntry = pActEntry->pParent;
721 if ( pActEntry )
723 nDepth--;
724 if ( bWithDepth )
725 *pActDepth = nDepth;
726 return pActEntry;
728 return 0;
731 SvTreeListEntry* SvTreeList::LastVisible( const SvListView* pView, sal_uInt16* pDepth) const
733 DBG_ASSERT(pView,"LastVis:No View");
734 SvTreeListEntry* pEntry = Last();
735 while( pEntry && !IsEntryVisible( pView, pEntry ) )
736 pEntry = PrevVisible( pView, pEntry );
737 if ( pEntry && pDepth )
738 *pDepth = GetDepth( pEntry );
739 return pEntry;
742 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pEntry,sal_uInt16& nDelta) const
744 DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
746 sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
747 // nDelta entries existent?
748 // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
749 // nNewDelta = 10-nVisPos-1 == 4
750 if ( nVisPos+nDelta >= pView->nVisibleCount )
752 nDelta = (sal_uInt16)(pView->nVisibleCount-nVisPos);
753 nDelta--;
755 sal_uInt16 nDeltaTmp = nDelta;
756 while( nDeltaTmp )
758 pEntry = NextVisible( pView, pEntry );
759 nDeltaTmp--;
760 DBG_ASSERT(pEntry,"Entry?");
762 return pEntry;
765 SvTreeListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvTreeListEntry* pEntry, sal_uInt16& nDelta ) const
767 DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
769 sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
770 // nDelta entries existent?
771 // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
772 // nNewDelta = nNewVisPos
773 if ( nDelta > nVisPos )
774 nDelta = (sal_uInt16)nVisPos;
775 sal_uInt16 nDeltaTmp = nDelta;
776 while( nDeltaTmp )
778 pEntry = PrevVisible( pView, pEntry );
779 nDeltaTmp--;
780 DBG_ASSERT(pEntry,"Entry?");
782 return pEntry;
785 SvTreeListEntry* SvTreeList::FirstSelected( const SvListView* pView) const
787 DBG_ASSERT(pView,"FirstSel:No View");
788 if( !pView )
789 return 0;
790 SvTreeListEntry* pActSelEntry = First();
791 while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
792 pActSelEntry = NextVisible( pView, pActSelEntry );
793 return pActSelEntry;
797 SvTreeListEntry* SvTreeList::FirstChild( SvTreeListEntry* pParent ) const
799 if ( !pParent )
800 pParent = pRootItem;
801 SvTreeListEntry* pResult;
802 if (!pParent->maChildren.empty())
803 pResult = &pParent->maChildren[0];
804 else
805 pResult = 0;
806 return pResult;
809 SvTreeListEntry* SvTreeList::NextSibling( SvTreeListEntry* pEntry ) const
811 DBG_ASSERT(pEntry,"Entry?");
812 if( !pEntry )
813 return 0;
815 SvTreeListEntries& rList = pEntry->pParent->maChildren;
816 sal_uLong nPos = pEntry->GetChildListPos();
817 nPos++;
818 return nPos < rList.size() ? &rList[nPos] : NULL;
821 SvTreeListEntry* SvTreeList::PrevSibling( SvTreeListEntry* pEntry ) const
823 DBG_ASSERT(pEntry,"Entry?");
824 if( !pEntry )
825 return 0;
827 SvTreeListEntries& rList = pEntry->pParent->maChildren;
828 sal_uLong nPos = pEntry->GetChildListPos();
829 if ( nPos == 0 )
830 return 0;
831 nPos--;
832 pEntry = &rList[nPos];
833 return pEntry;
837 SvTreeListEntry* SvTreeList::LastSibling( SvTreeListEntry* pEntry ) const
839 DBG_ASSERT(pEntry,"LastSibling:Entry?");
840 if( !pEntry )
841 return 0;
843 SvTreeListEntries& rChildren = pEntry->pParent->maChildren;
844 return rChildren.empty() ? NULL : &rChildren.back();
847 SvTreeListEntry* SvTreeList::NextSelected( const SvListView* pView, SvTreeListEntry* pEntry ) const
849 DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
850 pEntry = Next( pEntry );
851 while( pEntry && !pView->IsSelected(pEntry) )
852 pEntry = Next( pEntry );
853 return pEntry;
856 SvTreeListEntry* SvTreeList::PrevSelected( const SvListView* pView, SvTreeListEntry* pEntry) const
858 DBG_ASSERT(pView&&pEntry,"PrevSel:View/Entry?");
859 pEntry = Prev( pEntry );
860 while( pEntry && !pView->IsSelected(pEntry) )
861 pEntry = Prev( pEntry );
863 return pEntry;
866 SvTreeListEntry* SvTreeList::LastSelected( const SvListView* pView ) const
868 DBG_ASSERT(pView,"LastSel:No View");
869 SvTreeListEntry* pEntry = Last();
870 while( pEntry && !pView->IsSelected(pEntry) )
871 pEntry = Prev( pEntry );
872 return pEntry;
875 sal_uLong SvTreeList::Insert( SvTreeListEntry* pEntry,SvTreeListEntry* pParent,sal_uLong nPos )
877 DBG_ASSERT( pEntry,"Entry?");
879 if ( !pParent )
880 pParent = pRootItem;
883 SvTreeListEntries& rList = pParent->maChildren;
885 // take sorting into account
886 GetInsertionPos( pEntry, pParent, nPos );
888 bAbsPositionsValid = false;
889 pEntry->pParent = pParent;
891 if (nPos < rList.size())
893 SvTreeListEntries::iterator itPos = rList.begin();
894 std::advance(itPos, nPos);
895 rList.insert(itPos, pEntry);
897 else
898 rList.push_back(pEntry);
900 nEntryCount++;
901 if (nPos != ULONG_MAX && (nPos != (rList.size()-1)))
902 SetListPositions(rList);
903 else
904 pEntry->nListPos = rList.size()-1;
906 Broadcast( LISTACTION_INSERTED, pEntry );
907 return nPos; // pEntry->nListPos;
910 sal_uLong SvTreeList::GetAbsPos( const SvTreeListEntry* pEntry) const
912 if ( !bAbsPositionsValid )
913 ((SvTreeList*)this)->SetAbsolutePositions();
914 return pEntry->nAbsPos;
917 sal_uLong SvTreeList::GetRelPos( const SvTreeListEntry* pChild ) const
919 return pChild->GetChildListPos();
922 void SvTreeList::SetAbsolutePositions()
924 sal_uLong nPos = 0;
925 SvTreeListEntry* pEntry = First();
926 while ( pEntry )
928 pEntry->nAbsPos = nPos;
929 nPos++;
930 pEntry = Next( pEntry );
932 bAbsPositionsValid = true;
935 void SvTreeList::Expand( SvListView* pView, SvTreeListEntry* pEntry )
937 DBG_ASSERT(pEntry&&pView,"Expand:View/Entry?");
938 if ( pView->IsExpanded(pEntry) )
939 return;
941 DBG_ASSERT(!pEntry->maChildren.empty(), "SvTreeList::Expand: We expected to have child entries.");
943 SvViewDataEntry* pViewData = pView->GetViewData(pEntry);
944 pViewData->SetExpanded(true);
945 SvTreeListEntry* pParent = pEntry->pParent;
946 // if parent is visible, invalidate status data
947 if ( pView->IsExpanded( pParent ) )
949 pView->bVisPositionsValid = sal_False;
950 pView->nVisibleCount = 0;
954 void SvTreeList::Collapse( SvListView* pView, SvTreeListEntry* pEntry )
956 DBG_ASSERT(pView&&pEntry,"Collapse:View/Entry?");
957 if ( !pView->IsExpanded(pEntry) )
958 return;
960 DBG_ASSERT(!pEntry->maChildren.empty(), "SvTreeList::Collapse: We expected have child entries.");
962 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
963 pViewData->SetExpanded(false);
965 SvTreeListEntry* pParent = pEntry->pParent;
966 if ( pView->IsExpanded(pParent) )
968 pView->nVisibleCount = 0;
969 pView->bVisPositionsValid = sal_False;
973 sal_Bool SvTreeList::Select( SvListView* pView, SvTreeListEntry* pEntry, sal_Bool bSelect )
975 DBG_ASSERT(pView&&pEntry,"Select:View/Entry?");
976 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
977 if ( bSelect )
979 if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
980 return sal_False;
981 else
983 pViewData->SetSelected(true);
984 pView->nSelectionCount++;
987 else
989 if ( !pViewData->IsSelected() )
990 return sal_False;
991 else
993 pViewData->SetSelected(false);
994 pView->nSelectionCount--;
997 return sal_True;
1000 bool SvTreeList::Remove( const SvTreeListEntry* pEntry )
1002 DBG_ASSERT(pEntry,"Cannot remove root, use clear");
1004 if( !pEntry->pParent )
1006 OSL_FAIL("Removing entry not in model!");
1007 // Under certain circumstances (which?), the explorer deletes entries
1008 // from the view that it hasn't inserted into the view. We don't want
1009 // to crash, so we catch this case here.
1010 return sal_False;
1013 Broadcast(LISTACTION_REMOVING, const_cast<SvTreeListEntry*>(pEntry));
1014 sal_uLong nRemoved = 1 + GetChildCount(pEntry);
1015 bAbsPositionsValid = false;
1017 SvTreeListEntry* pParent = pEntry->pParent;
1018 SvTreeListEntries& rList = pParent->maChildren;
1019 bool bLastEntry = false;
1021 // Since we need the live instance of SvTreeListEntry for broadcasting,
1022 // we first need to pop it from the container, broadcast it, then delete
1023 // the instance manually at the end.
1025 if ( pEntry->HasChildListPos() )
1027 size_t nListPos = pEntry->GetChildListPos();
1028 bLastEntry = (nListPos == (rList.size()-1)) ? true : false;
1029 SvTreeListEntries::iterator it = rList.begin();
1030 std::advance(it, nListPos);
1031 rList.release(it).release();
1033 else
1035 SvTreeListEntries::iterator it =
1036 std::find_if(rList.begin(), rList.end(), FindByPointer(pEntry));
1037 if (it != rList.end())
1038 rList.release(it).release();
1041 if (!rList.empty() && !bLastEntry)
1042 SetListPositions(rList);
1044 nEntryCount -= nRemoved;
1045 Broadcast(LISTACTION_REMOVED, const_cast<SvTreeListEntry*>(pEntry));
1046 delete pEntry;
1048 return true;
1051 void SvTreeList::SelectAll( SvListView* pView, sal_Bool bSelect )
1053 DBG_ASSERT(pView,"SelectAll:NoView");
1054 SvTreeListEntry* pEntry = First();
1055 while ( pEntry )
1057 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
1058 pViewData->SetSelected(bSelect);
1059 pEntry = Next( pEntry );
1061 if ( bSelect )
1062 pView->nSelectionCount = nEntryCount;
1063 else
1064 pView->nSelectionCount = 0;
1068 SvTreeListEntry* SvTreeList::GetEntryAtAbsPos( sal_uLong nAbsPos ) const
1070 SvTreeListEntry* pEntry = First();
1071 while ( nAbsPos && pEntry )
1073 pEntry = Next( pEntry );
1074 nAbsPos--;
1076 return pEntry;
1079 SvTreeListEntry* SvTreeList::GetEntryAtVisPos( const SvListView* pView, sal_uLong nVisPos ) const
1081 DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
1082 SvTreeListEntry* pEntry = First();
1083 while ( nVisPos && pEntry )
1085 pEntry = NextVisible( pView, pEntry );
1086 nVisPos--;
1088 return pEntry;
1091 void SvTreeList::SetListPositions( SvTreeListEntries& rEntries )
1093 if (rEntries.empty())
1094 return;
1096 SvTreeListEntry& rFirst = rEntries.front();
1097 if (rFirst.pParent)
1098 rFirst.pParent->InvalidateChildrensListPositions();
1101 void SvTreeList::InvalidateEntry( SvTreeListEntry* pEntry )
1103 Broadcast( LISTACTION_INVALIDATE_ENTRY, pEntry );
1106 SvTreeListEntry* SvTreeList::GetRootLevelParent( SvTreeListEntry* pEntry ) const
1108 DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
1109 SvTreeListEntry* pCurParent = 0;
1110 if ( pEntry )
1112 pCurParent = pEntry->pParent;
1113 if ( pCurParent == pRootItem )
1114 return pEntry; // is its own parent
1115 while( pCurParent && pCurParent->pParent != pRootItem )
1116 pCurParent = pCurParent->pParent;
1118 return pCurParent;
1121 std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator>
1122 SvTreeList::GetChildIterators(SvTreeListEntry* pParent)
1124 typedef std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator> IteratorPair;
1126 static SvTreeListEntries dummy; // prevent singular iterator asserts
1127 IteratorPair aRet(dummy.begin(), dummy.end());
1129 if (!pParent)
1130 pParent = pRootItem;
1132 if (pParent->maChildren.empty())
1133 // This entry has no children.
1134 return aRet;
1136 aRet.first = pParent->maChildren.begin();
1137 aRet.second = pParent->maChildren.end();
1139 return aRet;
1142 DBG_NAME(SvListView);
1144 SvListView::SvListView()
1146 DBG_CTOR(SvListView,0);
1147 pModel = 0;
1148 nSelectionCount = 0;
1149 nVisibleCount = 0;
1150 bVisPositionsValid = sal_False;
1154 SvListView::~SvListView()
1156 DBG_DTOR(SvListView,0);
1157 maDataTable.clear();
1160 void SvListView::InitTable()
1162 DBG_CHKTHIS(SvListView,0);
1163 DBG_ASSERT(pModel,"InitTable:No Model");
1164 DBG_ASSERT(!nSelectionCount&&!nVisibleCount&&!bVisPositionsValid,"InitTable: Not cleared!");
1166 if( maDataTable.size() )
1168 DBG_ASSERT(maDataTable.size()==1,"InitTable: TableCount != 1");
1169 // Delete the view data allocated to the Clear in the root.
1170 // Attention: The model belonging to the root entry (and thus the entry
1171 // itself) might already be deleted.
1172 maDataTable.clear();
1175 SvTreeListEntry* pEntry;
1176 SvViewDataEntry* pViewData;
1178 // insert root entry
1179 pEntry = pModel->pRootItem;
1180 pViewData = new SvViewDataEntry;
1181 pViewData->SetExpanded(true);
1182 maDataTable.insert( pEntry, pViewData );
1183 // now all the other entries
1184 pEntry = pModel->First();
1185 while( pEntry )
1187 pViewData = CreateViewData( pEntry );
1188 DBG_ASSERT(pViewData,"InitTable:No ViewData");
1189 InitViewData( pViewData, pEntry );
1190 maDataTable.insert( pEntry, pViewData );
1191 pEntry = pModel->Next( pEntry );
1195 SvViewDataEntry* SvListView::CreateViewData( SvTreeListEntry* )
1197 DBG_CHKTHIS(SvListView,0);
1198 return new SvViewDataEntry;
1201 void SvListView::Clear()
1203 maDataTable.clear();
1204 nSelectionCount = 0;
1205 nVisibleCount = 0;
1206 bVisPositionsValid = sal_False;
1207 if( pModel )
1209 // insert root entry
1210 SvTreeListEntry* pEntry = pModel->pRootItem;
1211 SvViewDataEntry* pViewData = new SvViewDataEntry;
1212 pViewData->SetExpanded(true);
1213 maDataTable.insert( pEntry, pViewData );
1217 void SvListView::SetModel( SvTreeList* pNewModel )
1219 DBG_CHKTHIS(SvListView,0);
1220 sal_Bool bBroadcastCleared = sal_False;
1221 if ( pModel )
1223 pModel->RemoveView( this );
1224 bBroadcastCleared = sal_True;
1225 ModelNotification( LISTACTION_CLEARING,0,0,0 );
1226 if ( pModel->GetRefCount() == 0 )
1227 delete pModel;
1229 pModel = pNewModel;
1230 InitTable();
1231 pNewModel->InsertView( this );
1232 if( bBroadcastCleared )
1233 ModelNotification( LISTACTION_CLEARED,0,0,0 );
1237 void SvListView::ModelHasCleared()
1239 DBG_CHKTHIS(SvListView,0);
1242 void SvListView::ModelHasInserted( SvTreeListEntry* )
1244 DBG_CHKTHIS(SvListView,0);
1247 void SvListView::ModelHasInsertedTree( SvTreeListEntry* )
1249 DBG_CHKTHIS(SvListView,0);
1252 void SvListView::ModelIsMoving( SvTreeListEntry* /* pSource */ ,
1253 SvTreeListEntry* /* pTargetParent */ , sal_uLong /* nPos */ )
1255 DBG_CHKTHIS(SvListView,0);
1259 void SvListView::ModelHasMoved( SvTreeListEntry* )
1261 DBG_CHKTHIS(SvListView,0);
1264 void SvListView::ModelIsRemoving( SvTreeListEntry* )
1266 DBG_CHKTHIS(SvListView,0);
1269 void SvListView::ModelHasRemoved( SvTreeListEntry* )
1271 //WARNING WARNING WARNING
1272 //The supplied pointer should have been deleted
1273 //before this call. Be careful not to use it!!!
1274 DBG_CHKTHIS(SvListView,0);
1277 void SvListView::ModelHasEntryInvalidated( SvTreeListEntry*)
1279 DBG_CHKTHIS(SvListView,0);
1282 void SvListView::ActionMoving( SvTreeListEntry* pEntry,SvTreeListEntry*,sal_uLong)
1284 DBG_CHKTHIS(SvListView,0);
1285 SvTreeListEntry* pParent = pEntry->pParent;
1286 DBG_ASSERT(pParent,"Model not consistent");
1287 if (pParent != pModel->pRootItem && pParent->maChildren.size() == 1)
1289 SvViewDataEntry* pViewData = maDataTable.find( pParent )->second;
1290 pViewData->SetExpanded(false);
1292 // vorlaeufig
1293 nVisibleCount = 0;
1294 bVisPositionsValid = sal_False;
1297 void SvListView::ActionMoved( SvTreeListEntry* /* pEntry */ ,
1298 SvTreeListEntry* /* pTargetPrnt */ ,
1299 sal_uLong /* nChildPos */ )
1301 DBG_CHKTHIS(SvListView,0);
1302 nVisibleCount = 0;
1303 bVisPositionsValid = sal_False;
1306 void SvListView::ActionInserted( SvTreeListEntry* pEntry )
1308 DBG_CHKTHIS(SvListView,0);
1309 DBG_ASSERT(pEntry,"Insert:No Entry");
1310 SvViewDataEntry* pData = CreateViewData( pEntry );
1311 InitViewData( pData, pEntry );
1312 #ifdef DBG_UTIL
1313 std::pair<SvDataTable::iterator, bool> aSuccess =
1314 #endif
1315 maDataTable.insert( pEntry, pData );
1316 DBG_ASSERT(aSuccess.second,"Entry already in View");
1317 if ( nVisibleCount && pModel->IsEntryVisible( this, pEntry ))
1319 nVisibleCount = 0;
1320 bVisPositionsValid = sal_False;
1324 void SvListView::ActionInsertedTree( SvTreeListEntry* pEntry )
1326 DBG_CHKTHIS(SvListView,0);
1327 if ( pModel->IsEntryVisible( this, pEntry ))
1329 nVisibleCount = 0;
1330 bVisPositionsValid = sal_False;
1332 // iterate over entry and its children
1333 SvTreeListEntry* pCurEntry = pEntry;
1334 sal_uInt16 nRefDepth = pModel->GetDepth( pCurEntry );
1335 while( pCurEntry )
1337 DBG_ASSERT(maDataTable.find(pCurEntry) != maDataTable.end(),"Entry already in Table");
1338 SvViewDataEntry* pViewData = CreateViewData( pCurEntry );
1339 DBG_ASSERT(pViewData,"No ViewData");
1340 InitViewData( pViewData, pEntry );
1341 maDataTable.insert( pCurEntry, pViewData );
1342 pCurEntry = pModel->Next( pCurEntry );
1343 if ( pCurEntry && pModel->GetDepth(pCurEntry) <= nRefDepth)
1344 pCurEntry = 0;
1348 void SvListView::RemoveViewData( SvTreeListEntry* pParent )
1350 SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1351 for (; it != itEnd; ++it)
1353 SvTreeListEntry& rEntry = *it;
1354 maDataTable.erase(&rEntry);
1355 if (rEntry.HasChildren())
1356 RemoveViewData(&rEntry);
1362 void SvListView::ActionRemoving( SvTreeListEntry* pEntry )
1364 DBG_CHKTHIS(SvListView,0);
1365 DBG_ASSERT(pEntry,"Remove:No Entry");
1367 SvViewDataEntry* pViewData = maDataTable.find( pEntry )->second;
1368 sal_uLong nSelRemoved = 0;
1369 if ( pViewData->IsSelected() )
1370 nSelRemoved = 1 + pModel->GetChildSelectionCount( this, pEntry );
1371 nSelectionCount -= nSelRemoved;
1372 sal_uLong nVisibleRemoved = 0;
1373 if ( pModel->IsEntryVisible( this, pEntry ) )
1374 nVisibleRemoved = 1 + pModel->GetVisibleChildCount( this, pEntry );
1375 if( nVisibleCount )
1377 #ifdef DBG_UTIL
1378 if( nVisibleCount < nVisibleRemoved )
1380 OSL_FAIL("nVisibleRemoved bad");
1382 #endif
1383 nVisibleCount -= nVisibleRemoved;
1385 bVisPositionsValid = sal_False;
1387 maDataTable.erase(pEntry);
1388 RemoveViewData( pEntry );
1390 SvTreeListEntry* pCurEntry = pEntry->pParent;
1391 if (pCurEntry && pCurEntry != pModel->pRootItem && pCurEntry->maChildren.size() == 1)
1393 pViewData = maDataTable.find(pCurEntry)->second;
1394 pViewData->SetExpanded(false);
1398 void SvListView::ActionRemoved( SvTreeListEntry* /* pEntry */ )
1400 DBG_CHKTHIS(SvListView,0);
1403 void SvListView::ActionClear()
1405 DBG_CHKTHIS(SvListView,0);
1406 Clear();
1409 void SvListView::ModelNotification( sal_uInt16 nActionId, SvTreeListEntry* pEntry1,
1410 SvTreeListEntry* pEntry2, sal_uLong nPos )
1412 DBG_CHKTHIS(SvListView,0);
1413 switch( nActionId )
1415 case LISTACTION_INSERTED:
1416 ActionInserted( pEntry1 );
1417 ModelHasInserted( pEntry1 );
1418 break;
1419 case LISTACTION_INSERTED_TREE:
1420 ActionInsertedTree( pEntry1 );
1421 ModelHasInsertedTree( pEntry1 );
1422 break;
1423 case LISTACTION_REMOVING:
1424 ModelIsRemoving( pEntry1 );
1425 ActionRemoving( pEntry1 );
1426 break;
1427 case LISTACTION_REMOVED:
1428 ActionRemoved( pEntry1 );
1429 ModelHasRemoved( pEntry1 );
1430 break;
1431 case LISTACTION_MOVING:
1432 ModelIsMoving( pEntry1, pEntry2, nPos );
1433 ActionMoving( pEntry1, pEntry2, nPos );
1434 break;
1435 case LISTACTION_MOVED:
1436 ActionMoved( pEntry1, pEntry2, nPos );
1437 ModelHasMoved( pEntry1 );
1438 break;
1439 case LISTACTION_CLEARING:
1440 ActionClear();
1441 ModelHasCleared(); // sic! for compatibility reasons!
1442 break;
1443 case LISTACTION_CLEARED:
1444 break;
1445 case LISTACTION_INVALIDATE_ENTRY:
1446 // no action for the base class
1447 ModelHasEntryInvalidated( pEntry1 );
1448 break;
1449 case LISTACTION_RESORTED:
1450 bVisPositionsValid = sal_False;
1451 break;
1452 case LISTACTION_RESORTING:
1453 break;
1454 default:
1455 OSL_FAIL("unknown ActionId");
1459 void SvListView::InitViewData( SvViewDataEntry*, SvTreeListEntry* )
1463 sal_Bool SvListView::IsExpanded( SvTreeListEntry* pEntry ) const
1465 DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1466 SvDataTable::const_iterator itr = maDataTable.find(pEntry);
1467 DBG_ASSERT(itr != maDataTable.end(),"Entry not in Table");
1468 if (itr == maDataTable.end())
1469 return false;
1470 return itr->second->IsExpanded();
1473 sal_Bool SvListView::IsSelected( SvTreeListEntry* pEntry ) const
1475 DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1476 SvDataTable::const_iterator itr = maDataTable.find(pEntry );
1477 if (itr == maDataTable.end())
1478 return false;
1479 return itr->second->IsSelected();
1482 void SvListView::SetEntryFocus( SvTreeListEntry* pEntry, sal_Bool bFocus )
1484 DBG_ASSERT(pEntry,"SetEntryFocus:No Entry");
1485 SvDataTable::iterator itr = maDataTable.find(pEntry);
1486 DBG_ASSERT(itr != maDataTable.end(),"Entry not in Table");
1487 itr->second->SetFocus(bFocus);
1490 const SvViewDataEntry* SvListView::GetViewData( const SvTreeListEntry* pEntry ) const
1492 SvDataTable::const_iterator itr = maDataTable.find( const_cast<SvTreeListEntry*>(pEntry) );
1493 if (itr == maDataTable.end())
1494 return NULL;
1495 return itr->second;
1498 SvViewDataEntry* SvListView::GetViewData( SvTreeListEntry* pEntry )
1500 SvDataTable::iterator itr = maDataTable.find( pEntry );
1501 DBG_ASSERT(itr != maDataTable.end(),"Entry not in model or wrong view");
1502 return itr->second;
1505 sal_Int32 SvTreeList::Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const
1507 if( aCompareLink.IsSet())
1509 SvSortData aSortData;
1510 aSortData.pLeft = pLeft;
1511 aSortData.pRight = pRight;
1512 return aCompareLink.Call( &aSortData );
1514 return 0;
1517 void SvTreeList::Resort()
1519 Broadcast( LISTACTION_RESORTING );
1520 bAbsPositionsValid = sal_False;
1521 ResortChildren( pRootItem );
1522 Broadcast( LISTACTION_RESORTED );
1525 void SvTreeList::ResortChildren( SvTreeListEntry* pParent )
1527 DBG_ASSERT(pParent,"Parent not set");
1529 if (pParent->maChildren.empty())
1530 return;
1532 // TODO: Re-implement this using ptr_vector's sort method.
1534 std::vector<SvTreeListEntry*> aStore; // Temporarily store entries.
1535 aStore.reserve(pParent->maChildren.size());
1537 SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1538 for (; it != itEnd; ++it)
1540 SvTreeListEntry* p = &(*it);
1541 aStore.push_back(p);
1544 pParent->maChildren.release().release(); // Release all stored entries and empty the container.
1546 std::vector<SvTreeListEntry*>::iterator it = aStore.begin(), itEnd = aStore.end();
1547 for (; it != itEnd; ++it)
1549 SvTreeListEntry* p = *it;
1550 sal_uLong nListPos = ULONG_MAX;
1551 GetInsertionPos(p, pParent, nListPos);
1552 if (nListPos < pParent->maChildren.size())
1554 SvTreeListEntries::iterator itPos = pParent->maChildren.begin();
1555 std::advance(itPos, nListPos);
1556 pParent->maChildren.insert(itPos, p);
1558 else
1559 pParent->maChildren.push_back(p);
1560 if (!p->maChildren.empty())
1561 // Recursively sort child entries.
1562 ResortChildren(p);
1564 SetListPositions(pParent->maChildren); // correct list position in target list
1567 void SvTreeList::GetInsertionPos( SvTreeListEntry* pEntry, SvTreeListEntry* pParent,
1568 sal_uLong& rPos )
1570 DBG_ASSERT(pEntry,"No Entry");
1572 if( eSortMode == SortNone )
1573 return;
1575 rPos = ULONG_MAX;
1576 const SvTreeListEntries& rChildList = GetChildList(pParent);
1578 if (!rChildList.empty())
1580 long i = 0;
1581 long j = rChildList.size()-1;
1582 long k;
1583 sal_Int32 nCompare = 1;
1587 k = (i+j)/2;
1588 const SvTreeListEntry* pTempEntry = &rChildList[k];
1589 nCompare = Compare( pEntry, pTempEntry );
1590 if( eSortMode == SortDescending && nCompare != 0 )
1592 if( nCompare < 0 )
1593 nCompare = 1;
1594 else
1595 nCompare = -1;
1597 if( nCompare > 0 )
1598 i = k + 1;
1599 else
1600 j = k - 1;
1601 } while( (nCompare != 0) && (i <= j) );
1603 if( nCompare != 0 )
1605 if (i > static_cast<long>(rChildList.size()-1)) // not found, end of list
1606 rPos = ULONG_MAX;
1607 else
1608 rPos = i; // not found, middle of list
1610 else
1611 rPos = k;
1615 bool SvTreeList::HasChildren( const SvTreeListEntry* pEntry ) const
1617 if ( !pEntry )
1618 pEntry = pRootItem;
1620 return !pEntry->maChildren.empty();
1623 bool SvTreeList::HasParent( const SvTreeListEntry* pEntry ) const
1625 return pEntry->pParent != pRootItem;
1628 SvTreeListEntry* SvTreeList::GetEntry( SvTreeListEntry* pParent, sal_uLong nPos ) const
1629 { if ( !pParent )
1630 pParent = pRootItem;
1631 SvTreeListEntry* pRet = 0;
1632 if (nPos < pParent->maChildren.size())
1633 pRet = &pParent->maChildren[nPos];
1634 return pRet;
1637 SvTreeListEntry* SvTreeList::GetEntry( sal_uLong nRootPos ) const
1639 SvTreeListEntry* pRet = 0;
1640 if ( nEntryCount && nRootPos < pRootItem->maChildren.size())
1641 pRet = &pRootItem->maChildren[nRootPos];
1642 return pRet;
1645 const SvTreeListEntries& SvTreeList::GetChildList( SvTreeListEntry* pParent ) const
1647 if ( !pParent )
1648 pParent = pRootItem;
1649 return pParent->maChildren;
1652 SvTreeListEntries& SvTreeList::GetChildList( SvTreeListEntry* pParent )
1654 if ( !pParent )
1655 pParent = pRootItem;
1656 return pParent->maChildren;
1659 const SvTreeListEntry* SvTreeList::GetParent( const SvTreeListEntry* pEntry ) const
1661 const SvTreeListEntry* pParent = pEntry->pParent;
1662 if (pParent == pRootItem)
1663 pParent = NULL;
1664 return pParent;
1667 SvTreeListEntry* SvTreeList::GetParent( SvTreeListEntry* pEntry )
1669 SvTreeListEntry* pParent = pEntry->pParent;
1670 if (pParent == pRootItem)
1671 pParent = NULL;
1672 return pParent;
1675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */