fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / svtools / source / contnr / treelist.cxx
blobf1283f2b8124f8e7e4f159d33a6c74ba9939d482
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 SvTreeList::SvTreeList() :
26 mbEnableInvalidate(true)
28 nEntryCount = 0;
29 bAbsPositionsValid = false;
30 nRefCount = 1;
31 pRootItem = new SvTreeListEntry;
32 eSortMode = SortNone;
35 SvTreeList::~SvTreeList()
37 Clear();
38 delete pRootItem;
39 #ifdef DBG_UTIL
40 pRootItem = 0;
41 #endif
44 void SvTreeList::Broadcast(
45 SvListAction nActionId,
46 SvTreeListEntry* pEntry1,
47 SvTreeListEntry* pEntry2,
48 sal_uLong nPos
49 ) {
50 sal_uLong nViewCount = aViewList.size();
51 for( sal_uLong nCurView = 0; nCurView < nViewCount; nCurView++ )
53 SvListView* pView = aViewList[ nCurView ];
54 if( pView )
55 pView->ModelNotification( nActionId, pEntry1, pEntry2, nPos );
59 void SvTreeList::InsertView( SvListView* pView )
61 for ( sal_uLong i = 0, n = aViewList.size(); i < n; ++i ) {
62 if ( aViewList[ i ] == pView ) {
63 return;
66 aViewList.push_back( pView );
67 nRefCount++;
70 void SvTreeList::RemoveView( SvListView* pView )
72 for ( ListViewsType::iterator it = aViewList.begin(); it != aViewList.end(); ++it )
74 if ( *it == pView )
76 aViewList.erase( it );
77 --nRefCount;
78 break;
84 // an entry is visible if all parents are expanded
85 bool SvTreeList::IsEntryVisible( const SvListView* pView, SvTreeListEntry* pEntry ) const
87 DBG_ASSERT(pView&&pEntry,"IsVisible:Invalid Params");
88 bool bRetVal = false;
91 if ( pEntry == pRootItem )
93 bRetVal = true;
94 break;
96 pEntry = pEntry->pParent;
97 } while( pView->IsExpanded( pEntry ) );
98 return bRetVal;
101 sal_uInt16 SvTreeList::GetDepth( const SvTreeListEntry* pEntry ) const
103 DBG_ASSERT(pEntry&&pEntry!=pRootItem,"GetDepth:Bad Entry");
104 sal_uInt16 nDepth = 0;
105 while( pEntry->pParent != pRootItem )
107 nDepth++;
108 pEntry = pEntry->pParent;
110 return nDepth;
113 bool SvTreeList::IsAtRootDepth( const SvTreeListEntry* pEntry ) const
115 return pEntry->pParent == pRootItem;
118 void SvTreeList::Clear()
120 Broadcast( SvListAction::CLEARING );
121 pRootItem->ClearChildren();
122 nEntryCount = 0;
123 Broadcast( SvListAction::CLEARED );
126 bool SvTreeList::IsChild(const SvTreeListEntry* pParent, const SvTreeListEntry* pChild) const
128 if ( !pParent )
129 pParent = pRootItem;
131 if (pParent->maChildren.empty())
132 return false;
134 SvTreeListEntries::const_iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
135 for (; it != itEnd; ++it)
137 const SvTreeListEntry* pThis = &(*it);
138 if (pThis == pChild)
139 return true;
140 else
142 bool bIsChild = IsChild(pThis, pChild);
143 if (bIsChild)
144 return true;
147 return false;
150 namespace {
152 class FindByPointer : std::unary_function<SvTreeListEntry, bool>
154 const SvTreeListEntry* mpEntry;
155 public:
156 FindByPointer(const SvTreeListEntry* p) : mpEntry(p) {}
158 bool operator() (const SvTreeListEntry& rEntry) const
160 return mpEntry == &rEntry;
164 sal_uLong findEntryPosition(const SvTreeListEntries& rDst, const SvTreeListEntry* pEntry)
166 SvTreeListEntries::const_iterator itPos = std::find_if(rDst.begin(), rDst.end(), FindByPointer(pEntry));
167 if (itPos == rDst.end())
168 return static_cast<sal_uLong>(~0);
170 return static_cast<sal_uLong>(std::distance(rDst.begin(), itPos));
175 sal_uLong SvTreeList::Move(SvTreeListEntry* pSrcEntry,SvTreeListEntry* pTargetParent,sal_uLong nListPos)
177 // pDest may be 0!
178 DBG_ASSERT(pSrcEntry,"Entry?");
179 if ( !pTargetParent )
180 pTargetParent = pRootItem;
181 DBG_ASSERT(pSrcEntry!=pTargetParent,"Move:Source=Target");
183 Broadcast( SvListAction::MOVING, pSrcEntry, pTargetParent, nListPos );
185 if ( pSrcEntry == pTargetParent )
186 // You can't move an entry onto itself as the parent. Just return its
187 // position and bail out.
188 return pSrcEntry->GetChildListPos();
190 bAbsPositionsValid = false;
192 SvTreeListEntries& rDst = pTargetParent->maChildren;
193 SvTreeListEntries& rSrc = pSrcEntry->pParent->maChildren;
195 bool bSameParent = pTargetParent == pSrcEntry->pParent;
197 // Find the position of the entry being moved in the source container.
198 SvTreeListEntries::iterator itSrcPos = rSrc.begin(), itEnd = rSrc.end();
199 for (; itSrcPos != itEnd; ++itSrcPos)
201 const SvTreeListEntry* p = &(*itSrcPos);
202 if (p == pSrcEntry)
203 // Found
204 break;
207 if (itSrcPos == itEnd)
209 OSL_FAIL("Source entry not found! This should never happen.");
210 return pSrcEntry->GetChildListPos();
213 if (bSameParent)
215 // Moving within the same parent.
217 size_t nSrcPos = std::distance(rSrc.begin(), itSrcPos);
218 if (nSrcPos == nListPos)
219 // Nothing to move here.
220 return pSrcEntry->GetChildListPos();
222 if (nSrcPos < nListPos)
223 // Destination position shifts left after removing the original.
224 --nListPos;
226 // Release the original.
227 SvTreeListEntries::auto_type p = rSrc.release(itSrcPos);
228 // Determine the insertion position.
229 SvTreeListEntries::iterator itDstPos = rSrc.end();
230 if (nListPos < rSrc.size())
232 itDstPos = rSrc.begin();
233 std::advance(itDstPos, nListPos);
235 rSrc.insert(itDstPos, p.release());
237 else
239 // Moving from one parent to another.
240 SvTreeListEntries::iterator itDstPos = rDst.end();
241 if (nListPos < rDst.size())
243 itDstPos = rDst.begin();
244 std::advance(itDstPos, nListPos);
246 SvTreeListEntries::auto_type p = rSrc.release(itSrcPos);
247 rDst.insert(itDstPos, p.release());
250 // move parent umsetzen (do this only now, because we need the parent for
251 // deleting the old child list!)
252 pSrcEntry->pParent = pTargetParent;
254 // correct list position in target list
255 SetListPositions(rDst);
256 if (!bSameParent)
257 SetListPositions(rSrc);
259 sal_uLong nRetVal = findEntryPosition(rDst, pSrcEntry);
260 OSL_ENSURE(nRetVal == pSrcEntry->GetChildListPos(), "ListPos not valid");
261 Broadcast( SvListAction::MOVED,pSrcEntry,pTargetParent,nRetVal);
262 return nRetVal;
265 sal_uLong SvTreeList::Copy(SvTreeListEntry* pSrcEntry,SvTreeListEntry* pTargetParent,sal_uLong nListPos)
267 // pDest may be 0!
268 DBG_ASSERT(pSrcEntry,"Entry?");
269 if ( !pTargetParent )
270 pTargetParent = pRootItem;
272 bAbsPositionsValid = false;
274 sal_uLong nCloneCount = 0;
275 SvTreeListEntry* pClonedEntry = Clone( pSrcEntry, nCloneCount );
276 nEntryCount += nCloneCount;
278 SvTreeListEntries& rDst = pTargetParent->maChildren;
280 pClonedEntry->pParent = pTargetParent; // move parent
282 if (nListPos < rDst.size())
284 SvTreeListEntries::iterator itPos = rDst.begin(); // insertion position.
285 std::advance(itPos, nListPos);
286 rDst.insert(itPos, pClonedEntry);
288 else
289 rDst.push_back(pClonedEntry);
291 SetListPositions(rDst); // correct list position in target list
293 Broadcast( SvListAction::INSERTED_TREE, pClonedEntry );
294 sal_uLong nRetVal = findEntryPosition(rDst, pClonedEntry);
295 return nRetVal;
298 void SvTreeList::Move( SvTreeListEntry* pSrcEntry, SvTreeListEntry* pDstEntry )
300 SvTreeListEntry* pParent;
301 sal_uLong nPos;
303 if ( !pDstEntry )
305 pParent = pRootItem;
306 nPos = 0UL;
308 else
310 pParent = pDstEntry->pParent;
311 nPos = pDstEntry->GetChildListPos();
312 nPos++; // (On screen:) insert _below_ pDstEntry
314 Move( pSrcEntry, pParent, nPos );
317 void SvTreeList::InsertTree(SvTreeListEntry* pSrcEntry,
318 SvTreeListEntry* pTargetParent,sal_uLong nListPos)
320 DBG_ASSERT(pSrcEntry,"InsertTree:Entry?");
321 if ( !pSrcEntry )
322 return;
324 if ( !pTargetParent )
325 pTargetParent = pRootItem;
327 // take sorting into account
328 GetInsertionPos( pSrcEntry, pTargetParent, nListPos );
330 bAbsPositionsValid = false;
332 pSrcEntry->pParent = pTargetParent; // move parent
333 SvTreeListEntries& rDst = pTargetParent->maChildren;
335 if (nListPos < rDst.size())
337 SvTreeListEntries::iterator itPos = rDst.begin();
338 std::advance(itPos, nListPos);
339 rDst.insert(itPos, pSrcEntry);
341 else
342 rDst.push_back(pSrcEntry);
344 SetListPositions(rDst); // correct list position in target list
345 nEntryCount += GetChildCount( pSrcEntry );
346 nEntryCount++; // the parent is new, too
348 Broadcast(SvListAction::INSERTED_TREE, pSrcEntry );
351 SvTreeListEntry* SvTreeList::CloneEntry( SvTreeListEntry* pSource ) const
353 if( aCloneLink.IsSet() )
354 return reinterpret_cast<SvTreeListEntry*>(aCloneLink.Call( pSource ));
355 SvTreeListEntry* pEntry = CreateEntry();
356 pEntry->Clone(pSource);
357 return pEntry;
360 SvTreeListEntry* SvTreeList::CreateEntry()
362 return new SvTreeListEntry;
365 SvTreeListEntry* SvTreeList::Clone( SvTreeListEntry* pEntry, sal_uLong& nCloneCount ) const
367 SvTreeListEntry* pClonedEntry = CloneEntry( pEntry );
368 nCloneCount = 1;
369 if (!pEntry->maChildren.empty())
370 // Clone the child entries.
371 CloneChildren(pClonedEntry->maChildren, nCloneCount, pEntry->maChildren, pClonedEntry);
373 return pClonedEntry;
376 void SvTreeList::CloneChildren(
377 SvTreeListEntries& rDst, sal_uLong& rCloneCount, SvTreeListEntries& rSrc, SvTreeListEntry* pNewParent) const
379 SvTreeListEntries aClone;
380 SvTreeListEntries::iterator it = rSrc.begin(), itEnd = rSrc.end();
381 for (; it != itEnd; ++it)
383 SvTreeListEntry& rEntry = *it;
384 SvTreeListEntry* pNewEntry = CloneEntry(&rEntry);
385 ++rCloneCount;
386 pNewEntry->pParent = pNewParent;
387 if (!rEntry.maChildren.empty())
388 // Clone entries recursively.
389 CloneChildren(pNewEntry->maChildren, rCloneCount, rEntry.maChildren, pNewEntry);
391 aClone.push_back(pNewEntry);
394 rDst.swap(aClone);
397 sal_uLong SvTreeList::GetChildCount( const SvTreeListEntry* pParent ) const
399 if ( !pParent )
400 return GetEntryCount();
402 if (!pParent || pParent->maChildren.empty())
403 return 0;
405 sal_uLong nCount = 0;
406 sal_uInt16 nRefDepth = GetDepth( pParent );
407 sal_uInt16 nActDepth = nRefDepth;
410 pParent = Next(const_cast<SvTreeListEntry*>(pParent), &nActDepth);
411 nCount++;
412 } while( pParent && nRefDepth < nActDepth );
413 nCount--;
414 return nCount;
417 sal_uLong SvTreeList::GetVisibleChildCount(const SvListView* pView, SvTreeListEntry* pParent) const
419 DBG_ASSERT(pView,"GetVisChildCount:No View");
420 if ( !pParent )
421 pParent = pRootItem;
423 if (!pParent || !pView->IsExpanded(pParent) || pParent->maChildren.empty())
424 return 0;
426 sal_uLong nCount = 0;
427 sal_uInt16 nRefDepth = GetDepth( pParent );
428 sal_uInt16 nActDepth = nRefDepth;
431 pParent = NextVisible( pView, pParent, &nActDepth );
432 nCount++;
433 } while( pParent && nRefDepth < nActDepth );
434 nCount--;
435 return nCount;
438 sal_uLong SvTreeList::GetChildSelectionCount(const SvListView* pView,SvTreeListEntry* pParent) const
440 DBG_ASSERT(pView,"GetChildSelCount:No View");
441 if ( !pParent )
442 pParent = pRootItem;
444 if (!pParent || pParent->maChildren.empty())
445 return 0;
447 sal_uLong nCount = 0;
448 sal_uInt16 nRefDepth = GetDepth( pParent );
449 sal_uInt16 nActDepth = nRefDepth;
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;
460 SvTreeListEntry* SvTreeList::First() const
462 if ( nEntryCount )
463 return &pRootItem->maChildren[0];
464 else
465 return 0;
468 SvTreeListEntry* SvTreeList::Next( SvTreeListEntry* pActEntry, sal_uInt16* pDepth ) const
470 DBG_ASSERT( pActEntry && pActEntry->pParent, "SvTreeList::Next: invalid entry/parent!" );
471 if ( !pActEntry || !pActEntry->pParent )
472 return NULL;
474 sal_uInt16 nDepth = 0;
475 bool bWithDepth = false;
476 if ( pDepth )
478 nDepth = *pDepth;
479 bWithDepth = true;
482 // Get the list where the current entry belongs to (from its parent).
483 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
484 sal_uLong nActualPos = pActEntry->GetChildListPos();
486 if (!pActEntry->maChildren.empty())
488 // The current entry has children. Get its first child entry.
489 nDepth++;
490 pActEntry = &pActEntry->maChildren[0];
491 if ( bWithDepth )
492 *pDepth = nDepth;
493 return pActEntry;
496 if (pActualList->size() > (nActualPos+1))
498 // Get the next sibling of the current entry.
499 pActEntry = &(*pActualList)[nActualPos+1];
500 if ( bWithDepth )
501 *pDepth = nDepth;
502 return pActEntry;
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 && pParent != 0 )
510 DBG_ASSERT(pParent!=0,"TreeData corrupt!");
511 pActualList = &pParent->pParent->maChildren;
512 nActualPos = pParent->GetChildListPos();
513 if (pActualList->size() > (nActualPos+1))
515 pActEntry = &(*pActualList)[nActualPos+1];
516 if ( bWithDepth )
517 *pDepth = nDepth;
518 return pActEntry;
520 pParent = pParent->pParent;
521 nDepth--;
523 return 0;
526 SvTreeListEntry* SvTreeList::Prev( SvTreeListEntry* pActEntry, sal_uInt16* pDepth ) const
528 DBG_ASSERT(pActEntry!=0,"Entry?");
530 sal_uInt16 nDepth = 0;
531 bool bWithDepth = false;
532 if ( pDepth )
534 nDepth = *pDepth;
535 bWithDepth = true;
538 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
539 sal_uLong nActualPos = pActEntry->GetChildListPos();
541 if ( nActualPos > 0 )
543 pActEntry = &(*pActualList)[nActualPos-1];
544 while (!pActEntry->maChildren.empty())
546 pActualList = &pActEntry->maChildren;
547 nDepth++;
548 pActEntry = &pActualList->back();
550 if ( bWithDepth )
551 *pDepth = nDepth;
552 return pActEntry;
554 if ( pActEntry->pParent == pRootItem )
555 return 0;
557 pActEntry = pActEntry->pParent;
559 if ( pActEntry )
561 nDepth--;
562 if ( bWithDepth )
563 *pDepth = nDepth;
564 return pActEntry;
566 return 0;
569 SvTreeListEntry* SvTreeList::Last() const
571 SvTreeListEntries* pActList = &pRootItem->maChildren;
572 SvTreeListEntry* pEntry = NULL;
573 while (!pActList->empty())
575 pEntry = &pActList->back();
576 pActList = &pEntry->maChildren;
578 return pEntry;
581 sal_uLong SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry* pEntry ) const
583 DBG_ASSERT(pView&&pEntry,"View/Entry?");
585 if ( !pView->bVisPositionsValid )
587 // to make GetVisibleCount refresh the positions
588 const_cast<SvListView*>(pView)->nVisibleCount = 0;
589 GetVisibleCount( const_cast<SvListView*>(pView) );
591 const SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
592 return pViewData->nVisPos;
595 sal_uLong SvTreeList::GetVisibleCount( SvListView* pView ) const
597 assert(pView && "GetVisCount:No View");
598 if( !pView->HasViewData() )
599 return 0;
600 if ( pView->nVisibleCount )
601 return pView->nVisibleCount;
603 sal_uLong nPos = 0;
604 SvTreeListEntry* pEntry = First(); // first entry is always visible
605 while ( pEntry )
607 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
608 pViewData->nVisPos = nPos;
609 nPos++;
610 pEntry = NextVisible( pView, pEntry );
612 #ifdef DBG_UTIL
613 if( nPos > 10000000 )
615 OSL_FAIL("nVisibleCount bad");
617 #endif
618 pView->nVisibleCount = nPos;
619 pView->bVisPositionsValid = true;
620 return nPos;
624 // For performance reasons, this function assumes that the passed entry is
625 // already visible.
626 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pActEntry,sal_uInt16* pActDepth) const
628 DBG_ASSERT(pView,"NextVisible:No View");
629 if ( !pActEntry )
630 return 0;
632 sal_uInt16 nDepth = 0;
633 bool bWithDepth = false;
634 if ( pActDepth )
636 nDepth = *pActDepth;
637 bWithDepth = true;
640 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
641 sal_uLong nActualPos = pActEntry->GetChildListPos();
643 if ( pView->IsExpanded(pActEntry) )
645 OSL_ENSURE(!pActEntry->maChildren.empty(), "Pass entry is supposed to have child entries.");
647 nDepth++;
648 pActEntry = &pActEntry->maChildren[0];
649 if ( bWithDepth )
650 *pActDepth = nDepth;
651 return pActEntry;
654 nActualPos++;
655 if ( pActualList->size() > nActualPos )
657 pActEntry = &(*pActualList)[nActualPos];
658 if ( bWithDepth )
659 *pActDepth = nDepth;
660 return pActEntry;
663 SvTreeListEntry* pParent = pActEntry->pParent;
664 nDepth--;
665 while( pParent != pRootItem )
667 pActualList = &pParent->pParent->maChildren;
668 nActualPos = pParent->GetChildListPos();
669 nActualPos++;
670 if ( pActualList->size() > nActualPos )
672 pActEntry = &(*pActualList)[nActualPos];
673 if ( bWithDepth )
674 *pActDepth = nDepth;
675 return pActEntry;
677 pParent = pParent->pParent;
678 nDepth--;
680 return 0;
684 // For performance reasons, this function assumes that the passed entry is
685 // already visible.
687 SvTreeListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvTreeListEntry* pActEntry, sal_uInt16* pActDepth) const
689 DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
691 sal_uInt16 nDepth = 0;
692 bool bWithDepth = false;
693 if ( pActDepth )
695 nDepth = *pActDepth;
696 bWithDepth = true;
699 SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
700 sal_uLong nActualPos = pActEntry->GetChildListPos();
702 if ( nActualPos > 0 )
704 pActEntry = &(*pActualList)[nActualPos-1];
705 while( pView->IsExpanded(pActEntry) )
707 pActualList = &pActEntry->maChildren;
708 nDepth++;
709 pActEntry = &pActualList->back();
711 if ( bWithDepth )
712 *pActDepth = nDepth;
713 return pActEntry;
716 if ( pActEntry->pParent == pRootItem )
717 return 0;
719 pActEntry = pActEntry->pParent;
720 if ( pActEntry )
722 nDepth--;
723 if ( bWithDepth )
724 *pActDepth = nDepth;
725 return pActEntry;
727 return 0;
730 SvTreeListEntry* SvTreeList::LastVisible( const SvListView* pView, sal_uInt16* pDepth) const
732 DBG_ASSERT(pView,"LastVis:No View");
733 SvTreeListEntry* pEntry = Last();
734 while( pEntry && !IsEntryVisible( pView, pEntry ) )
735 pEntry = PrevVisible( pView, pEntry );
736 if ( pEntry && pDepth )
737 *pDepth = GetDepth( pEntry );
738 return pEntry;
741 SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pEntry,sal_uInt16& nDelta) const
743 DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
745 sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
746 // nDelta entries existent?
747 // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
748 // nNewDelta = 10-nVisPos-1 == 4
749 if ( nVisPos+nDelta >= pView->nVisibleCount )
751 nDelta = (sal_uInt16)(pView->nVisibleCount-nVisPos);
752 nDelta--;
754 sal_uInt16 nDeltaTmp = nDelta;
755 while( nDeltaTmp )
757 pEntry = NextVisible( pView, pEntry );
758 nDeltaTmp--;
759 DBG_ASSERT(pEntry,"Entry?");
761 return pEntry;
764 SvTreeListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvTreeListEntry* pEntry, sal_uInt16& nDelta ) const
766 DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
768 sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
769 // nDelta entries existent?
770 // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
771 // nNewDelta = nNewVisPos
772 if ( nDelta > nVisPos )
773 nDelta = (sal_uInt16)nVisPos;
774 sal_uInt16 nDeltaTmp = nDelta;
775 while( nDeltaTmp )
777 pEntry = PrevVisible( pView, pEntry );
778 nDeltaTmp--;
779 DBG_ASSERT(pEntry,"Entry?");
781 return pEntry;
784 SvTreeListEntry* SvTreeList::FirstSelected( const SvListView* pView) const
786 DBG_ASSERT(pView,"FirstSel:No View");
787 if( !pView )
788 return 0;
789 SvTreeListEntry* pActSelEntry = First();
790 while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
791 pActSelEntry = NextVisible( pView, pActSelEntry );
792 return pActSelEntry;
796 SvTreeListEntry* SvTreeList::FirstChild( SvTreeListEntry* pParent ) const
798 if ( !pParent )
799 pParent = pRootItem;
800 SvTreeListEntry* pResult;
801 if (!pParent->maChildren.empty())
802 pResult = &pParent->maChildren[0];
803 else
804 pResult = 0;
805 return pResult;
808 SvTreeListEntry* SvTreeList::NextSibling( SvTreeListEntry* pEntry )
810 DBG_ASSERT(pEntry,"Entry?");
811 if( !pEntry )
812 return 0;
814 SvTreeListEntries& rList = pEntry->pParent->maChildren;
815 sal_uLong nPos = pEntry->GetChildListPos();
816 nPos++;
817 return nPos < rList.size() ? &rList[nPos] : NULL;
820 SvTreeListEntry* SvTreeList::PrevSibling( SvTreeListEntry* pEntry )
822 DBG_ASSERT(pEntry,"Entry?");
823 if( !pEntry )
824 return 0;
826 SvTreeListEntries& rList = pEntry->pParent->maChildren;
827 sal_uLong nPos = pEntry->GetChildListPos();
828 if ( nPos == 0 )
829 return 0;
830 nPos--;
831 pEntry = &rList[nPos];
832 return pEntry;
836 SvTreeListEntry* SvTreeList::LastSibling( SvTreeListEntry* pEntry )
838 DBG_ASSERT(pEntry,"LastSibling:Entry?");
839 if( !pEntry )
840 return 0;
842 SvTreeListEntries& rChildren = pEntry->pParent->maChildren;
843 return rChildren.empty() ? NULL : &rChildren.back();
846 SvTreeListEntry* SvTreeList::NextSelected( const SvListView* pView, SvTreeListEntry* pEntry ) const
848 DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
849 pEntry = Next( pEntry );
850 while( pEntry && !pView->IsSelected(pEntry) )
851 pEntry = Next( pEntry );
852 return pEntry;
855 SvTreeListEntry* SvTreeList::PrevSelected( const SvListView* pView, SvTreeListEntry* pEntry) const
857 DBG_ASSERT(pView&&pEntry,"PrevSel:View/Entry?");
858 pEntry = Prev( pEntry );
859 while( pEntry && !pView->IsSelected(pEntry) )
860 pEntry = Prev( pEntry );
862 return pEntry;
865 SvTreeListEntry* SvTreeList::LastSelected( const SvListView* pView ) const
867 DBG_ASSERT(pView,"LastSel:No View");
868 SvTreeListEntry* pEntry = Last();
869 while( pEntry && !pView->IsSelected(pEntry) )
870 pEntry = Prev( pEntry );
871 return pEntry;
874 sal_uLong SvTreeList::Insert( SvTreeListEntry* pEntry,SvTreeListEntry* pParent,sal_uLong nPos )
876 DBG_ASSERT( pEntry,"Entry?");
878 if ( !pParent )
879 pParent = pRootItem;
882 SvTreeListEntries& rList = pParent->maChildren;
884 // take sorting into account
885 GetInsertionPos( pEntry, pParent, nPos );
887 bAbsPositionsValid = false;
888 pEntry->pParent = pParent;
890 if (nPos < rList.size())
892 SvTreeListEntries::iterator itPos = rList.begin();
893 std::advance(itPos, nPos);
894 rList.insert(itPos, pEntry);
896 else
897 rList.push_back(pEntry);
899 nEntryCount++;
900 if (nPos != TREELIST_APPEND && (nPos != (rList.size()-1)))
901 SetListPositions(rList);
902 else
903 pEntry->nListPos = rList.size()-1;
905 Broadcast( SvListAction::INSERTED, pEntry );
906 return nPos; // pEntry->nListPos;
909 sal_uLong SvTreeList::GetAbsPos( const SvTreeListEntry* pEntry) const
911 if ( !bAbsPositionsValid )
912 const_cast<SvTreeList*>(this)->SetAbsolutePositions();
913 return pEntry->nAbsPos;
916 sal_uLong SvTreeList::GetRelPos( const SvTreeListEntry* pChild )
918 return pChild->GetChildListPos();
921 void SvTreeList::SetAbsolutePositions()
923 sal_uLong nPos = 0;
924 SvTreeListEntry* pEntry = First();
925 while ( pEntry )
927 pEntry->nAbsPos = nPos;
928 nPos++;
929 pEntry = Next( pEntry );
931 bAbsPositionsValid = true;
934 void SvTreeList::Expand( SvListView* pView, SvTreeListEntry* pEntry )
936 DBG_ASSERT(pEntry&&pView,"Expand:View/Entry?");
937 if ( pView->IsExpanded(pEntry) )
938 return;
940 DBG_ASSERT(!pEntry->maChildren.empty(), "SvTreeList::Expand: We expected to have child entries.");
942 SvViewDataEntry* pViewData = pView->GetViewData(pEntry);
943 pViewData->SetExpanded(true);
944 SvTreeListEntry* pParent = pEntry->pParent;
945 // if parent is visible, invalidate status data
946 if ( pView->IsExpanded( pParent ) )
948 pView->bVisPositionsValid = false;
949 pView->nVisibleCount = 0;
953 void SvTreeList::Collapse( SvListView* pView, SvTreeListEntry* pEntry )
955 DBG_ASSERT(pView&&pEntry,"Collapse:View/Entry?");
956 if ( !pView->IsExpanded(pEntry) )
957 return;
959 DBG_ASSERT(!pEntry->maChildren.empty(), "SvTreeList::Collapse: We expected have child entries.");
961 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
962 pViewData->SetExpanded(false);
964 SvTreeListEntry* pParent = pEntry->pParent;
965 if ( pView->IsExpanded(pParent) )
967 pView->nVisibleCount = 0;
968 pView->bVisPositionsValid = false;
972 bool SvTreeList::Select( SvListView* pView, SvTreeListEntry* pEntry, bool bSelect )
974 DBG_ASSERT(pView&&pEntry,"Select:View/Entry?");
975 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
976 if ( bSelect )
978 if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
979 return false;
980 else
982 pViewData->SetSelected(true);
983 pView->nSelectionCount++;
986 else
988 if ( !pViewData->IsSelected() )
989 return false;
990 else
992 pViewData->SetSelected(false);
993 pView->nSelectionCount--;
996 return true;
999 bool SvTreeList::Remove( const SvTreeListEntry* pEntry )
1001 DBG_ASSERT(pEntry,"Cannot remove root, use clear");
1003 if( !pEntry->pParent )
1005 OSL_FAIL("Removing entry not in model!");
1006 // Under certain circumstances (which?), the explorer deletes entries
1007 // from the view that it hasn't inserted into the view. We don't want
1008 // to crash, so we catch this case here.
1009 return false;
1012 Broadcast(SvListAction::REMOVING, const_cast<SvTreeListEntry*>(pEntry));
1013 sal_uLong nRemoved = 1 + GetChildCount(pEntry);
1014 bAbsPositionsValid = false;
1016 SvTreeListEntry* pParent = pEntry->pParent;
1017 SvTreeListEntries& rList = pParent->maChildren;
1018 bool bLastEntry = false;
1020 // Since we need the live instance of SvTreeListEntry for broadcasting,
1021 // we first need to pop it from the container, broadcast it, then delete
1022 // the instance manually at the end.
1024 if ( pEntry->HasChildListPos() )
1026 size_t nListPos = pEntry->GetChildListPos();
1027 bLastEntry = (nListPos == (rList.size()-1));
1028 SvTreeListEntries::iterator it = rList.begin();
1029 std::advance(it, nListPos);
1030 rList.release(it).release();
1032 else
1034 SvTreeListEntries::iterator it =
1035 std::find_if(rList.begin(), rList.end(), FindByPointer(pEntry));
1036 if (it != rList.end())
1037 rList.release(it).release();
1040 if (!rList.empty() && !bLastEntry)
1041 SetListPositions(rList);
1043 nEntryCount -= nRemoved;
1044 Broadcast(SvListAction::REMOVED, const_cast<SvTreeListEntry*>(pEntry));
1045 delete pEntry;
1047 return true;
1050 void SvTreeList::SelectAll( SvListView* pView, bool bSelect )
1052 assert(pView && "SelectAll:NoView");
1053 SvTreeListEntry* pEntry = First();
1054 while ( pEntry )
1056 SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
1057 pViewData->SetSelected(bSelect);
1058 pEntry = Next( pEntry );
1060 if ( bSelect )
1061 pView->nSelectionCount = nEntryCount;
1062 else
1063 pView->nSelectionCount = 0;
1067 SvTreeListEntry* SvTreeList::GetEntryAtAbsPos( sal_uLong nAbsPos ) const
1069 SvTreeListEntry* pEntry = First();
1070 while ( nAbsPos && pEntry )
1072 pEntry = Next( pEntry );
1073 nAbsPos--;
1075 return pEntry;
1078 SvTreeListEntry* SvTreeList::GetEntryAtVisPos( const SvListView* pView, sal_uLong nVisPos ) const
1080 DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
1081 SvTreeListEntry* pEntry = First();
1082 while ( nVisPos && pEntry )
1084 pEntry = NextVisible( pView, pEntry );
1085 nVisPos--;
1087 return pEntry;
1090 void SvTreeList::SetListPositions( SvTreeListEntries& rEntries )
1092 if (rEntries.empty())
1093 return;
1095 SvTreeListEntry& rFirst = rEntries.front();
1096 if (rFirst.pParent)
1097 rFirst.pParent->InvalidateChildrensListPositions();
1100 void SvTreeList::EnableInvalidate( bool bEnable )
1102 mbEnableInvalidate = bEnable;
1105 void SvTreeList::InvalidateEntry( SvTreeListEntry* pEntry )
1107 if (!mbEnableInvalidate)
1108 return;
1110 Broadcast( SvListAction::INVALIDATE_ENTRY, pEntry );
1113 SvTreeListEntry* SvTreeList::GetRootLevelParent( SvTreeListEntry* pEntry ) const
1115 DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
1116 SvTreeListEntry* pCurParent = 0;
1117 if ( pEntry )
1119 pCurParent = pEntry->pParent;
1120 if ( pCurParent == pRootItem )
1121 return pEntry; // is its own parent
1122 while( pCurParent && pCurParent->pParent != pRootItem )
1123 pCurParent = pCurParent->pParent;
1125 return pCurParent;
1128 std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator>
1129 SvTreeList::GetChildIterators(SvTreeListEntry* pParent)
1131 typedef std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator> IteratorPair;
1133 static SvTreeListEntries dummy; // prevent singular iterator asserts
1134 IteratorPair aRet(dummy.begin(), dummy.end());
1136 if (!pParent)
1137 pParent = pRootItem;
1139 if (pParent->maChildren.empty())
1140 // This entry has no children.
1141 return aRet;
1143 aRet.first = pParent->maChildren.begin();
1144 aRet.second = pParent->maChildren.end();
1146 return aRet;
1150 SvListView::SvListView()
1152 pModel = 0;
1153 nSelectionCount = 0;
1154 nVisibleCount = 0;
1155 bVisPositionsValid = false;
1159 SvListView::~SvListView()
1161 maDataTable.clear();
1164 void SvListView::InitTable()
1166 DBG_ASSERT(pModel,"InitTable:No Model");
1167 DBG_ASSERT(!nSelectionCount&&!nVisibleCount&&!bVisPositionsValid,"InitTable: Not cleared!");
1169 if( maDataTable.size() )
1171 DBG_ASSERT(maDataTable.size()==1,"InitTable: TableCount != 1");
1172 // Delete the view data allocated to the Clear in the root.
1173 // Attention: The model belonging to the root entry (and thus the entry
1174 // itself) might already be deleted.
1175 maDataTable.clear();
1178 SvTreeListEntry* pEntry;
1179 SvViewDataEntry* pViewData;
1181 // insert root entry
1182 pEntry = pModel->pRootItem;
1183 pViewData = new SvViewDataEntry;
1184 pViewData->SetExpanded(true);
1185 maDataTable.insert( pEntry, pViewData );
1186 // now all the other entries
1187 pEntry = pModel->First();
1188 while( pEntry )
1190 pViewData = CreateViewData( pEntry );
1191 DBG_ASSERT(pViewData,"InitTable:No ViewData");
1192 InitViewData( pViewData, pEntry );
1193 maDataTable.insert( pEntry, pViewData );
1194 pEntry = pModel->Next( pEntry );
1198 SvViewDataEntry* SvListView::CreateViewData( SvTreeListEntry* )
1200 return new SvViewDataEntry;
1203 void SvListView::Clear()
1205 maDataTable.clear();
1206 nSelectionCount = 0;
1207 nVisibleCount = 0;
1208 bVisPositionsValid = false;
1209 if( pModel )
1211 // insert root entry
1212 SvTreeListEntry* pEntry = pModel->pRootItem;
1213 SvViewDataEntry* pViewData = new SvViewDataEntry;
1214 pViewData->SetExpanded(true);
1215 maDataTable.insert( pEntry, pViewData );
1219 void SvListView::SetModel( SvTreeList* pNewModel )
1221 bool bBroadcastCleared = false;
1222 if ( pModel )
1224 pModel->RemoveView( this );
1225 bBroadcastCleared = true;
1226 ModelNotification( SvListAction::CLEARING,0,0,0 );
1227 if ( pModel->GetRefCount() == 0 )
1228 delete pModel;
1230 pModel = pNewModel;
1231 InitTable();
1232 pNewModel->InsertView( this );
1233 if( bBroadcastCleared )
1234 ModelNotification( SvListAction::CLEARED,0,0,0 );
1238 void SvListView::ModelHasCleared()
1242 void SvListView::ModelHasInserted( SvTreeListEntry* )
1246 void SvListView::ModelHasInsertedTree( SvTreeListEntry* )
1250 void SvListView::ModelIsMoving( SvTreeListEntry* /* pSource */ ,
1251 SvTreeListEntry* /* pTargetParent */ , sal_uLong /* nPos */ )
1256 void SvListView::ModelHasMoved( SvTreeListEntry* )
1260 void SvListView::ModelIsRemoving( SvTreeListEntry* )
1264 void SvListView::ModelHasRemoved( SvTreeListEntry* )
1266 //WARNING WARNING WARNING
1267 //The supplied pointer should have been deleted
1268 //before this call. Be careful not to use it!!!
1271 void SvListView::ModelHasEntryInvalidated( SvTreeListEntry*)
1275 void SvListView::ActionMoving( SvTreeListEntry* pEntry,SvTreeListEntry*,sal_uLong)
1277 SvTreeListEntry* pParent = pEntry->pParent;
1278 DBG_ASSERT(pParent,"Model not consistent");
1279 if (pParent != pModel->pRootItem && pParent->maChildren.size() == 1)
1281 SvViewDataEntry* pViewData = maDataTable.find( pParent )->second;
1282 pViewData->SetExpanded(false);
1284 // vorlaeufig
1285 nVisibleCount = 0;
1286 bVisPositionsValid = false;
1289 void SvListView::ActionMoved( SvTreeListEntry* /* pEntry */ ,
1290 SvTreeListEntry* /* pTargetPrnt */ ,
1291 sal_uLong /* nChildPos */ )
1293 nVisibleCount = 0;
1294 bVisPositionsValid = false;
1297 void SvListView::ActionInserted( SvTreeListEntry* pEntry )
1299 DBG_ASSERT(pEntry,"Insert:No Entry");
1300 SvViewDataEntry* pData = CreateViewData( pEntry );
1301 InitViewData( pData, pEntry );
1302 #ifdef DBG_UTIL
1303 std::pair<SvDataTable::iterator, bool> aSuccess =
1304 #endif
1305 maDataTable.insert( pEntry, pData );
1306 DBG_ASSERT(aSuccess.second,"Entry already in View");
1307 if ( nVisibleCount && pModel->IsEntryVisible( this, pEntry ))
1309 nVisibleCount = 0;
1310 bVisPositionsValid = false;
1314 void SvListView::ActionInsertedTree( SvTreeListEntry* pEntry )
1316 if ( pModel->IsEntryVisible( this, pEntry ))
1318 nVisibleCount = 0;
1319 bVisPositionsValid = false;
1321 // iterate over entry and its children
1322 SvTreeListEntry* pCurEntry = pEntry;
1323 sal_uInt16 nRefDepth = pModel->GetDepth( pCurEntry );
1324 while( pCurEntry )
1326 DBG_ASSERT(maDataTable.find(pCurEntry) != maDataTable.end(),"Entry already in Table");
1327 SvViewDataEntry* pViewData = CreateViewData( pCurEntry );
1328 DBG_ASSERT(pViewData,"No ViewData");
1329 InitViewData( pViewData, pEntry );
1330 maDataTable.insert( pCurEntry, pViewData );
1331 pCurEntry = pModel->Next( pCurEntry );
1332 if ( pCurEntry && pModel->GetDepth(pCurEntry) <= nRefDepth)
1333 pCurEntry = 0;
1337 void SvListView::RemoveViewData( SvTreeListEntry* pParent )
1339 SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1340 for (; it != itEnd; ++it)
1342 SvTreeListEntry& rEntry = *it;
1343 maDataTable.erase(&rEntry);
1344 if (rEntry.HasChildren())
1345 RemoveViewData(&rEntry);
1351 void SvListView::ActionRemoving( SvTreeListEntry* pEntry )
1353 DBG_ASSERT(pEntry,"Remove:No Entry");
1355 SvViewDataEntry* pViewData = maDataTable.find( pEntry )->second;
1356 sal_uLong nSelRemoved = 0;
1357 if ( pViewData->IsSelected() )
1358 nSelRemoved = 1 + pModel->GetChildSelectionCount( this, pEntry );
1359 nSelectionCount -= nSelRemoved;
1360 sal_uLong nVisibleRemoved = 0;
1361 if ( pModel->IsEntryVisible( this, pEntry ) )
1362 nVisibleRemoved = 1 + pModel->GetVisibleChildCount( this, pEntry );
1363 if( nVisibleCount )
1365 #ifdef DBG_UTIL
1366 if( nVisibleCount < nVisibleRemoved )
1368 OSL_FAIL("nVisibleRemoved bad");
1370 #endif
1371 nVisibleCount -= nVisibleRemoved;
1373 bVisPositionsValid = false;
1375 maDataTable.erase(pEntry);
1376 RemoveViewData( pEntry );
1378 SvTreeListEntry* pCurEntry = pEntry->pParent;
1379 if (pCurEntry && pCurEntry != pModel->pRootItem && pCurEntry->maChildren.size() == 1)
1381 pViewData = maDataTable.find(pCurEntry)->second;
1382 pViewData->SetExpanded(false);
1386 void SvListView::ActionClear()
1388 Clear();
1391 void SvListView::ModelNotification( SvListAction nActionId, SvTreeListEntry* pEntry1,
1392 SvTreeListEntry* pEntry2, sal_uLong nPos )
1394 switch( nActionId )
1396 case SvListAction::INSERTED:
1397 ActionInserted( pEntry1 );
1398 ModelHasInserted( pEntry1 );
1399 break;
1400 case SvListAction::INSERTED_TREE:
1401 ActionInsertedTree( pEntry1 );
1402 ModelHasInsertedTree( pEntry1 );
1403 break;
1404 case SvListAction::REMOVING:
1405 ModelIsRemoving( pEntry1 );
1406 ActionRemoving( pEntry1 );
1407 break;
1408 case SvListAction::REMOVED:
1409 ModelHasRemoved( pEntry1 );
1410 break;
1411 case SvListAction::MOVING:
1412 ModelIsMoving( pEntry1, pEntry2, nPos );
1413 ActionMoving( pEntry1, pEntry2, nPos );
1414 break;
1415 case SvListAction::MOVED:
1416 ActionMoved( pEntry1, pEntry2, nPos );
1417 ModelHasMoved( pEntry1 );
1418 break;
1419 case SvListAction::CLEARING:
1420 ActionClear();
1421 ModelHasCleared(); // sic! for compatibility reasons!
1422 break;
1423 case SvListAction::CLEARED:
1424 break;
1425 case SvListAction::INVALIDATE_ENTRY:
1426 // no action for the base class
1427 ModelHasEntryInvalidated( pEntry1 );
1428 break;
1429 case SvListAction::RESORTED:
1430 bVisPositionsValid = false;
1431 break;
1432 case SvListAction::RESORTING:
1433 break;
1434 case SvListAction::REVERSING:
1435 break;
1436 case SvListAction::REVERSED:
1437 bVisPositionsValid = false;
1438 break;
1439 default:
1440 OSL_FAIL("unknown ActionId");
1444 void SvListView::InitViewData( SvViewDataEntry*, SvTreeListEntry* )
1448 bool SvListView::IsExpanded( SvTreeListEntry* pEntry ) const
1450 DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1451 SvDataTable::const_iterator itr = maDataTable.find(pEntry);
1452 DBG_ASSERT(itr != maDataTable.end(),"Entry not in Table");
1453 if (itr == maDataTable.end())
1454 return false;
1455 return itr->second->IsExpanded();
1458 bool SvListView::IsSelected( SvTreeListEntry* pEntry ) const
1460 DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1461 SvDataTable::const_iterator itr = maDataTable.find(pEntry );
1462 if (itr == maDataTable.end())
1463 return false;
1464 return itr->second->IsSelected();
1467 void SvListView::SetEntryFocus( SvTreeListEntry* pEntry, bool bFocus )
1469 DBG_ASSERT(pEntry,"SetEntryFocus:No Entry");
1470 SvDataTable::iterator itr = maDataTable.find(pEntry);
1471 DBG_ASSERT(itr != maDataTable.end(),"Entry not in Table");
1472 itr->second->SetFocus(bFocus);
1475 const SvViewDataEntry* SvListView::GetViewData( const SvTreeListEntry* pEntry ) const
1477 SvDataTable::const_iterator itr = maDataTable.find( const_cast<SvTreeListEntry*>(pEntry) );
1478 if (itr == maDataTable.end())
1479 return NULL;
1480 return itr->second;
1483 SvViewDataEntry* SvListView::GetViewData( SvTreeListEntry* pEntry )
1485 SvDataTable::iterator itr = maDataTable.find( pEntry );
1486 DBG_ASSERT(itr != maDataTable.end(),"Entry not in model or wrong view");
1487 return itr->second;
1490 sal_Int32 SvTreeList::Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const
1492 if( aCompareLink.IsSet())
1494 SvSortData aSortData;
1495 aSortData.pLeft = pLeft;
1496 aSortData.pRight = pRight;
1497 return aCompareLink.Call( &aSortData );
1499 return 0;
1502 void SvTreeList::Resort()
1504 Broadcast( SvListAction::RESORTING );
1505 bAbsPositionsValid = false;
1506 ResortChildren( pRootItem );
1507 Broadcast( SvListAction::RESORTED );
1510 namespace {
1512 class SortComparator : public std::binary_function<SvTreeListEntry,SvTreeListEntry,bool>
1514 SvTreeList& mrList;
1515 public:
1517 SortComparator( SvTreeList& rList ) : mrList(rList) {}
1519 bool operator() ( const SvTreeListEntry& rLeft, const SvTreeListEntry& rRight ) const
1521 return mrList.Compare(&rLeft, &rRight) < 0;
1527 void SvTreeList::ResortChildren( SvTreeListEntry* pParent )
1529 DBG_ASSERT(pParent,"Parent not set");
1531 if (pParent->maChildren.empty())
1532 return;
1534 SortComparator aComp(*this);
1535 pParent->maChildren.sort(aComp);
1537 // Recursively sort child entries.
1538 SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1539 for (; it != itEnd; ++it)
1541 SvTreeListEntry& r = *it;
1542 ResortChildren(&r);
1545 SetListPositions(pParent->maChildren); // correct list position in target list
1548 void SvTreeList::Reverse()
1550 Broadcast(SvListAction::REVERSING);
1551 bAbsPositionsValid = false;
1552 ReverseChildren(pRootItem);
1553 Broadcast(SvListAction::REVERSED);
1556 void SvTreeList::ReverseChildren( SvTreeListEntry* pParent )
1558 DBG_ASSERT(pParent,"Parent not set");
1560 if (pParent->maChildren.empty())
1561 return;
1563 std::reverse(pParent->maChildren.base().begin(), pParent->maChildren.base().end());
1564 // Recursively sort child entries.
1565 SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1566 for (; it != itEnd; ++it)
1568 SvTreeListEntry& r = *it;
1569 ReverseChildren(&r);
1572 SetListPositions(pParent->maChildren); // correct list position in target list
1575 void SvTreeList::GetInsertionPos( SvTreeListEntry* pEntry, SvTreeListEntry* pParent,
1576 sal_uLong& rPos )
1578 DBG_ASSERT(pEntry,"No Entry");
1580 if( eSortMode == SortNone )
1581 return;
1583 rPos = TREELIST_ENTRY_NOTFOUND;
1584 const SvTreeListEntries& rChildList = GetChildList(pParent);
1586 if (!rChildList.empty())
1588 long i = 0;
1589 long j = rChildList.size()-1;
1590 long k;
1591 sal_Int32 nCompare = 1;
1595 k = (i+j)/2;
1596 const SvTreeListEntry* pTempEntry = &rChildList[k];
1597 nCompare = Compare( pEntry, pTempEntry );
1598 if( eSortMode == SortDescending && nCompare != 0 )
1600 if( nCompare < 0 )
1601 nCompare = 1;
1602 else
1603 nCompare = -1;
1605 if( nCompare > 0 )
1606 i = k + 1;
1607 else
1608 j = k - 1;
1609 } while( (nCompare != 0) && (i <= j) );
1611 if( nCompare != 0 )
1613 if (i > static_cast<long>(rChildList.size()-1)) // not found, end of list
1614 rPos = TREELIST_ENTRY_NOTFOUND;
1615 else
1616 rPos = i; // not found, middle of list
1618 else
1619 rPos = k;
1623 bool SvTreeList::HasChildren( const SvTreeListEntry* pEntry ) const
1625 if ( !pEntry )
1626 pEntry = pRootItem;
1628 return !pEntry->maChildren.empty();
1631 bool SvTreeList::HasParent( const SvTreeListEntry* pEntry ) const
1633 return pEntry->pParent != pRootItem;
1636 SvTreeListEntry* SvTreeList::GetEntry( SvTreeListEntry* pParent, sal_uLong nPos ) const
1637 { if ( !pParent )
1638 pParent = pRootItem;
1639 SvTreeListEntry* pRet = 0;
1640 if (nPos < pParent->maChildren.size())
1641 pRet = &pParent->maChildren[nPos];
1642 return pRet;
1645 SvTreeListEntry* SvTreeList::GetEntry( sal_uLong nRootPos ) const
1647 SvTreeListEntry* pRet = 0;
1648 if ( nEntryCount && nRootPos < pRootItem->maChildren.size())
1649 pRet = &pRootItem->maChildren[nRootPos];
1650 return pRet;
1653 const SvTreeListEntries& SvTreeList::GetChildList( SvTreeListEntry* pParent ) const
1655 if ( !pParent )
1656 pParent = pRootItem;
1657 return pParent->maChildren;
1660 SvTreeListEntries& SvTreeList::GetChildList( SvTreeListEntry* pParent )
1662 if ( !pParent )
1663 pParent = pRootItem;
1664 return pParent->maChildren;
1667 const SvTreeListEntry* SvTreeList::GetParent( const SvTreeListEntry* pEntry ) const
1669 const SvTreeListEntry* pParent = pEntry->pParent;
1670 if (pParent == pRootItem)
1671 pParent = NULL;
1672 return pParent;
1675 SvTreeListEntry* SvTreeList::GetParent( SvTreeListEntry* pEntry )
1677 SvTreeListEntry* pParent = pEntry->pParent;
1678 if (pParent == pRootItem)
1679 pParent = NULL;
1680 return pParent;
1683 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */